package com.akjava.gwt.three.client.gwt; import static com.google.common.base.Preconditions.checkNotNull; import com.akjava.gwt.lib.client.LogUtils; import com.akjava.gwt.three.client.gwt.boneanimation.AnimationBone; import com.akjava.gwt.three.client.js.core.Face3; import com.akjava.gwt.three.client.js.math.Vector2; import com.akjava.gwt.three.client.js.math.Vector3; import com.akjava.gwt.three.client.js.math.Vector4; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayNumber; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; /* * create JSON Model format 3 data * https://github.com/mrdoob/three.js/wiki/JSON-Model-format-3 * * format3 should be loaded by JSONLoader */ public class JSONModelFile extends JavaScriptObject{ protected JSONModelFile(){} public static JSONModelFile create(){ return create("GWT JSONModelFile r63"); } @SuppressWarnings("unchecked") public static JSONModelFile create(String generatedBy){ JSONModelFile f=(JSONModelFile) JSONModelFile.createObject(); MetaData mdata=(MetaData) MetaData.createObject(); mdata.setFormatVersion(3.1); f.setMetaData(mdata); f.setNormals((JsArrayNumber) JavaScriptObject.createArray()); f.setColors((JsArrayNumber) JavaScriptObject.createArray()); f.setVertices((JsArrayNumber) JavaScriptObject.createArray()); f.setFaces((JsArrayNumber) JavaScriptObject.createArray()); f.setUvs((JsArray<JsArrayNumber>) JsArray.createArray()); f.setMaterials((JsArray<ModelMaterials>) JsArray.createArray()); f.setSkinIndices((JsArrayNumber) JavaScriptObject.createArray()); f.setSkinWeights((JsArrayNumber) JavaScriptObject.createArray()); f.getMaterials().push(ModelMaterials.createDefault()); return f; } /* * basically just create from JSONParser.parseStrict(text); */ public final static JSONModelFile create(JSONValue jsonValues){ checkNotNull(jsonValues, "JSONModelFile-create:null"); JSONObject object=jsonValues.isObject(); if(object==null){ LogUtils.log("JSONModelFile-create:not object"); return null; } return (JSONModelFile)object.getJavaScriptObject(); } public final String getJsonText(){ //TODO print pretty return new JSONObject(this).toString(); } public native final void setVertices (JsArrayNumber vertices)/*-{ this["vertices"]=vertices; }-*/; public native final double getScale()/*-{ return this["scale"]; }-*/; public native final void setScale(double scale)/*-{ this["scale"]=scale; }-*/; public native final JsArrayNumber getVertices ()/*-{ return this["vertices"]; }-*/; public native final void setFaces (JsArrayNumber faces)/*-{ this["faces"]=faces; }-*/; public native final JsArrayNumber getFaces ()/*-{ return this["faces"]; }-*/; public native final void setNormals (JsArrayNumber normals)/*-{ this["normals"]=normals; }-*/; //vertex normal public native final void setNormals (JsArray<Face3> faces)/*-{ this["normals"]=[]; for (i = 0; i <faces.length; i++) { for(j=0;j<3;j++){ this["normals"].push(faces[i].vertexNormals[j].x); this["normals"].push(faces[i].vertexNormals[j].y); this["normals"].push(faces[i].vertexNormals[j].z); } } }-*/; public native final JsArrayNumber getNormals ()/*-{ return this["normals"]; }-*/; public native final void setColors (JsArrayNumber colors)/*-{ this["colors"]=colors; }-*/; public native final JsArrayNumber getColors ()/*-{ return this["colors"]; }-*/; public native final JsArrayNumber getSkinWeights ()/*-{ return this["skinWeights"]; }-*/; public native final void setSkinWeights(JsArrayNumber skinWeights)/*-{ this["skinWeights"]=skinWeights; }-*/; public native final void setSkinIndices (JsArrayNumber skinIndices)/*-{ this["skinIndices"]=skinIndices; }-*/; public native final JsArrayNumber getSkinIndices ()/*-{ return this["skinIndices"]; }-*/; public native final void setUvs (JsArray<JsArrayNumber> uvs)/*-{ this["uvs"]=uvs; }-*/; public native final JsArray<JsArrayNumber> getUvs ()/*-{ return this["uvs"]; }-*/; public native final void setMaterials (JsArray<ModelMaterials> materials)/*-{ this["materials"]=materials; }-*/; public native final JsArray<ModelMaterials> getMaterials ()/*-{ return this["materials"]; }-*/; public native final JavaScriptObject getAnimation ()/*-{ return this["animation"]; }-*/; public native final void setAnimation (JavaScriptObject animation)/*-{ this["animation"]=animation; }-*/; public native final JsArray<JavaScriptObject> getBones ()/*-{ return this["bones"]; }-*/; public native final void setBones (JsArray<? extends JavaScriptObject> bones)/*-{ this["bones"]=bones; }-*/; public native final JsArray<JavaScriptObject> getMorphTargets ()/*-{ return this["morphTargets"]; }-*/; /* * set converted json * [ * { * name:"morphName", * vertex][v1x,v1y,v1z,v2x,v2y,v2z,...] * } * ] */ public native final void setMorphTargets (JsArray<JavaScriptObject> morphTargets)/*-{ this["morphTargets"]=morphTargets; }-*/; public native final JsArray<JavaScriptObject> getMorphColors ()/*-{ return this["morphColors"]; }-*/; public native final void setMorphColors (JsArray<JavaScriptObject> morphColors)/*-{ this["morphColors"]=morphColors; }-*/; public final void setSkinIndicesAndWeights(JsArray<Vector4> indices,JsArray<Vector4> weights){ JsArrayNumber indicesArray=(JsArrayNumber) JsArrayNumber.createArray(); for(int i=0;i<indices.length();i++){ indicesArray.push(indices.get(i).getX()); indicesArray.push(indices.get(i).getY()); } JsArrayNumber weightsArray=(JsArrayNumber) JsArrayNumber.createArray(); for(int i=0;i<weights.length();i++){ weightsArray.push(weights.get(i).getX()); weightsArray.push(weights.get(i).getY()); } //LogUtils.log("indicesArray.length:"+indicesArray.length()); //LogUtils.log("weightsArray.length:"+weightsArray.length()); setSkinIndices(indicesArray); setSkinWeights(weightsArray); } public final void setVertices(JsArray<Vector3> vx){ JsArrayNumber nums=(JsArrayNumber) JsArrayNumber.createArray(); for(int i=0;i<vx.length();i++){ nums.push(vx.get(i).getX()); nums.push(vx.get(i).getY()); nums.push(vx.get(i).getZ()); } setVertices(nums); } /* * single uv only */ public final void setGeometryUvs(JsArray<JsArray<JsArray<Vector2>>> uvss){ @SuppressWarnings("unchecked") JsArray<JsArrayNumber> uvArray=(JsArray<JsArrayNumber>) JsArray.createArray(); for(int k=0;k<uvss.length();k++){//usually get 1 JsArray<JsArray<Vector2>> uvs=uvss.get(k); JsArrayNumber nums=(JsArrayNumber) JsArrayNumber.createArray(); uvArray.push(nums); //LogUtils.log("uvs:"+uvs.length()); for(int i=0;i<uvs.length();i++){//same as face number JsArray<Vector2> u=uvs.get(i); //LogUtils.log("uvs:-u"+u.length()); for(int j=0;j<u.length();j++){//usually 3 Vector2 uv=u.get(j); nums.push(uv.getX()); nums.push(uv.getY()); } } } setUvs(uvArray); } /** * call setUvs first * @param faces */ public final void setFaces(JsArray<Face3> faces){ boolean hasUv=getUvs().length()>0; boolean hasNormal=getNormals().length()>0; JsArrayNumber nums=(JsArrayNumber) JsArrayNumber.createArray(); int faceIndex=0; for(int i=0;i<faces.length();i++){ Face3 face=faces.get(i); if(face.isFace4()){ int v=1;if(hasUv){v=8+1;};if(hasNormal){v+=32;} nums.push(v); // quad nums.push(face.getA()); nums.push(face.getB()); nums.push(face.getC()); nums.push(face.getD()); if(hasUv){//uv is same as vx nums.push(faceIndex); nums.push(faceIndex+1); nums.push(faceIndex+2); nums.push(faceIndex+3); } if(hasNormal){ nums.push(faceIndex); nums.push(faceIndex+1); nums.push(faceIndex+2); nums.push(faceIndex+3); } faceIndex+=4; }else{ int v=0;if(hasUv){v=8+0;};if(hasNormal){v+=32;} nums.push(v); // triangle nums.push(face.getA()); nums.push(face.getB()); nums.push(face.getC()); if(hasUv){//uv is same as vx nums.push(faceIndex); nums.push(faceIndex+1); nums.push(faceIndex+2); } if(hasNormal){ nums.push(faceIndex); nums.push(faceIndex+1); nums.push(faceIndex+2); } faceIndex+=3; } } setFaces(nums); } public native final void setMetaData(MetaData meta)/*-{ this["metadata"]=meta; }-*/; public native final MetaData getMetaData()/*-{ return this["metadata"]; }-*/; public final JSONModelFile clone(){ JSONModelFile newFile=create(); //metadata newFile.setMetaData(this.getMetaData().clone()); newFile.setScale(this.getScale()); //TODO clone completly newFile.setMaterials(this.getMaterials());//warning shared if(this.getMorphTargets()!=null){ newFile.setMorphTargets(this.getMorphTargets()); } if(this.getMorphColors()!=null){ newFile.setMorphColors(this.getMorphColors()); } if(this.getBones()!=null){ newFile.setBones(this.getBones()); } if(this.getAnimation()!=null){ newFile.setAnimation(this.getAnimation()); } //clone uvs if(this.getUvs()!=null){ JsArray<JsArrayNumber> valuesUvs=this.getUvs(); for(int i=0;i<valuesUvs.length();i++){ JsArrayNumber uvs=valuesUvs.get(i); JsArrayNumber array=(JsArrayNumber) JavaScriptObject.createArray(); for(int j=0;j<uvs.length();j++){ array.push(uvs.get(j)); } newFile.getUvs().push(array); } } //clone faces,normals,colors,vertices,skinIndices,skinWeights if(this.getFaces()!=null){ JsArrayNumber values=this.getFaces(); for(int i=0;i<values.length();i++){ newFile.getFaces().push(values.get(i)); } } if(this.getNormals()!=null){ JsArrayNumber values=this.getNormals(); for(int i=0;i<values.length();i++){ newFile.getNormals().push(values.get(i)); } } if(this.getColors()!=null){ JsArrayNumber values=this.getColors(); for(int i=0;i<values.length();i++){ newFile.getColors().push(values.get(i)); } } if(this.getVertices()!=null){ JsArrayNumber values=this.getVertices(); for(int i=0;i<values.length();i++){ newFile.getVertices().push(values.get(i)); } } if(this.getSkinIndices()!=null){ JsArrayNumber values=this.getSkinIndices(); for(int i=0;i<values.length();i++){ newFile.getSkinIndices().push(values.get(i)); } } if(this.getSkinWeights()!=null){ JsArrayNumber values=this.getSkinWeights(); for(int i=0;i<values.length();i++){ newFile.getSkinWeights().push(values.get(i)); } } return newFile; } }