package com.akjava.gwt.three.client.java.utils; import javax.annotation.Nullable; import com.akjava.gwt.lib.client.JavaScriptUtils; import com.akjava.gwt.lib.client.LogUtils; import com.akjava.gwt.three.client.gwt.GWTParamUtils; import com.akjava.gwt.three.client.gwt.JSONModelFile; import com.akjava.gwt.three.client.gwt.loader.JSONLoaderObject; import com.akjava.gwt.three.client.js.THREE; import com.akjava.gwt.three.client.js.cameras.Camera; import com.akjava.gwt.three.client.js.core.Geometry; import com.akjava.gwt.three.client.js.loaders.JSONLoader; import com.akjava.gwt.three.client.js.loaders.JSONLoader.JSONLoadHandler; import com.akjava.gwt.three.client.js.materials.Material; import com.akjava.gwt.three.client.js.math.Color; import com.akjava.gwt.three.client.js.math.Euler; import com.akjava.gwt.three.client.js.math.Matrix4; import com.akjava.gwt.three.client.js.math.Quaternion; import com.akjava.gwt.three.client.js.math.Vector3; import com.akjava.gwt.three.client.js.objects.Mesh; 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.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONValue; public class GWTThreeUtils { public static class InvalidModelFormatException extends Exception{ public InvalidModelFormatException(String string) { super(string); } /** * */ private static final long serialVersionUID = 1L; } public static void loadJsonModel(JSONModelFile modelFile,JSONLoadHandler handler,String texturePath){ JSONLoader loader=THREE.JSONLoader(); JavaScriptObject jsobject=loader.parse(modelFile, texturePath); JSONObject newobject=new JSONObject(jsobject); //LogUtils.log(newobject.getJavaScriptObject()); JsArray<Material> materials=null; if(newobject.get("materials")!=null){ JSONArray array=newobject.get("materials").isArray(); if(array!=null){ materials=array.getJavaScriptObject().cast(); }else{ LogUtils.log("materials contains. but it's not array"); } // } handler.loaded((Geometry) newobject.get("geometry").isObject().getJavaScriptObject(),materials); } public static void loadJsonModel(JSONModelFile modelformat,JSONLoadHandler handler){ loadJsonModel(modelformat,handler,null); } public static JSONModelFile parseJsonObject(String jsonText) throws InvalidModelFormatException{ JSONValue lastJsonValue = JSONParser.parseStrict(jsonText); JSONObject object=lastJsonValue.isObject(); if(object==null){ throw new InvalidModelFormatException("invalid-json object"); } JSONModelFile file=(JSONModelFile)object.getJavaScriptObject(); if(file.getMetaData()==null){ throw new InvalidModelFormatException("no metadatas"); } if(file.getMetaData().getFormatVersion()==0){ throw new InvalidModelFormatException("invalid version:"+file.getMetaData().getFormatVersion()); } LogUtils.log("format:"+file.getMetaData().getFormatVersion()); LogUtils.log("version:"+file.getMetaData().getVersion()); //somehow complex if(file.getMetaData().getVersion()>=4){ file=(JSONModelFile)object.get("data").isObject().getJavaScriptObject(); } return file; } public static void changeMeshMaterialColor(Mesh mesh,int newColor){ Material material=mesh.getMaterial(); if(material==null){ return; } Color color=material.gwtGetColor(); if(color==null){ return; } color.set(newColor); } /* * get angle from p1 to p2 ,use Z vector */ public static Vector3 getRotation(Vector3 p1,Vector3 p2){ Vector3 up=THREE.Vector3(0, 1, 0); Matrix4 mx=THREE.Matrix4(); mx.lookAt(p2,p1,up); Vector3 ret=THREE.Vector3(); ret.getRotationFromMatrix(mx); return ret; } public static Quaternion degreeRotationQuaternion(Vector3 vec){ return rotationQuaternion(rotationToMatrix4(degreeToRagiant(vec))); } public static Quaternion rotationQuaternion(Vector3 vec){ return rotationQuaternion(rotationToMatrix4(vec)); } public static Quaternion rotationQuaternion(Matrix4 mx){ Quaternion q=THREE.Quaternion(); q.setFromRotationMatrix(mx); return q; } //Object positon to Screen Position public static native final Vector3 toScreenXY(Vector3 canvasXY,Camera camera,int width,int height)/*-{ var pos = canvasXY.clone(); projScreenMat = new $wnd.THREE.Matrix4(); projScreenMat.multiply( camera.projectionMatrix, camera.matrixWorldInverse ); projScreenMat.multiplyVector3( pos ); return new $wnd.THREE.Vector3( ( pos.x + 1 ) * width / 2, ( - pos.y + 1) * height / 2 ,0); }-*/; //for camera position & rotation 0,0,0, public static Vector3 toWebGLXY(int mouseX,int mouseY,Camera camera,int width,int height){ Vector3 mouseXY=THREE.Vector3(mouseX-width/2, -(mouseY-height/2), 0); Vector3 pj=mouseXY.project(camera); return pj; } /* * really need this? */ public static Mesh createSimpleBox(Vector3 position,double size,int color){ Mesh mesh=THREE.Mesh(THREE.BoxGeometry(size, size, size), THREE.MeshLambertMaterial(GWTParamUtils.MeshLambertMaterial().color(color))); mesh.setPosition(position); return mesh; } public static Vector3 radiantToDegree(Euler euler){ Vector3 ret=THREE.Vector3(); ret.setX(Math.toDegrees(euler.getX())); ret.setY(Math.toDegrees(euler.getY())); ret.setZ(Math.toDegrees(euler.getZ())); return ret; } public static Vector3 radiantToDegree(Vector3 vec){ Vector3 ret=THREE.Vector3(); ret.setX(Math.toDegrees(vec.getX())); ret.setY(Math.toDegrees(vec.getY())); ret.setZ(Math.toDegrees(vec.getZ())); return ret; } public static Vector3 degreeToRagiant(Vector3 vec){ Vector3 ret=THREE.Vector3(); ret.setX(Math.toRadians(vec.getX())); ret.setY(Math.toRadians(vec.getY())); ret.setZ(Math.toRadians(vec.getZ())); return ret; } public static Matrix4 degitRotationToMatrix4(double x,double y,double z){ return GWTThreeUtils.rotationToMatrix4(GWTThreeUtils.degreeToRagiant(THREE.Vector3(x,y,z))); } public static Matrix4 degitRotationToMatrix4(Vector3 angle){ return GWTThreeUtils.rotationToMatrix4(GWTThreeUtils.degreeToRagiant(angle)); } public static Matrix4 rotationToMatrix4(Vector3 vec){ return rotationToMatrix4(vec,"XYZ"); } public static Matrix4 rotationToMatrix4(Quaternion q){ return THREE.Matrix4().makeRotationFromQuaternion(q); } public static Matrix4 rotationToMatrix4(Vector3 vec,String order){ Matrix4 mx=THREE.Matrix4(); mx.makeRotationFromEuler(THREE.Euler(vec.getX(), vec.getY(), vec.getZ(), order)); return mx; } public static Vector3 rotationToVector3(Quaternion q){ Matrix4 mx=THREE.Matrix4().makeRotationFromQuaternion(q); return rotationToVector3(mx); } public static Vector3 rotationToVector3(Matrix4 mx){ Vector3 vec=THREE.Vector3(); vec.getRotationFromMatrix(mx); return vec; } public static Vector3 rotationToDegreeVector3(Matrix4 mx){ Vector3 vec=THREE.Vector3(); vec.getRotationFromMatrix(mx); return radiantToDegree(vec); } public static Matrix4 translateToMatrix4(Vector3 vec){ return THREE.Matrix4().makeTranslation(vec.getX(),vec.getY(),vec.getZ()); } public static Vector3 toPositionVec(Matrix4 mx){ return THREE.Vector3().setFromMatrixPosition(mx); } public static Vector3 toDegreeAngle(Matrix4 mx){ Vector3 vec=THREE.Vector3(); vec.getRotationFromMatrix(mx); double x=Math.toDegrees(vec.getX()); x%=360; if(x>180){ x=-(360-x); } //vec.setX(x); double y=Math.toDegrees(vec.getY()); y%=360; if(y>180){ y=-(360-y); } //vec.setY(y); double z=Math.toDegrees(vec.getZ()); z%=360; if(z>180){ z=-(360-z); } //vec.setY(z); //return vec; //i have no idea but sometime return radiant value. return THREE.Vector3(x, y, z); } /** * @deprecated use fromArray() * @param array * @return */ public static final Vector3 jsArrayToVector3(JsArrayNumber array){ return THREE.Vector3(array.get(0),array.get(1), array.get(2)); } public static final JsArrayNumber clone(JsArrayNumber array){ JsArrayNumber cloned=(JsArrayNumber) JsArrayNumber.createArray(); for(int i=0;i<array.length();i++){ cloned.push(array.get(i)); } return cloned; } public static final Quaternion jsArrayToQuaternion(JsArrayNumber array){ return THREE.Quaternion(array.get(0),array.get(1), array.get(2),array.get(3)); } public static final JsArrayNumber createJsArray(double x,double y,double z){ JsArrayNumber array=(JsArrayNumber) JsArrayNumber.createArray(); array.push(x); array.push(y); array.push(z); return array; } public static final JsArrayNumber quaternionToJsArray(Quaternion q){ JsArrayNumber array=(JsArrayNumber) JsArrayNumber.createArray(); array.push(q.getX()); array.push(q.getY()); array.push(q.getZ()); array.push(q.getW()); return array; } public static final native double getWindowDevicePixelRatio()/*-{ return $wnd.devicePixelRatio; }-*/; public static final JsArray<JsArrayNumber> toJsArrayNumber(@Nullable JsArray<Vector3> values){ if(values==null){ return null; } JsArray<JsArrayNumber> numbers=JavaScriptUtils.createJSArray(); for(int i=0;i<values.length();i++){ numbers.push(values.get(i).toArray()); } return numbers; } public static final JsArray<Vector3> fromJsArrayNumberToVector3(@Nullable JsArray<JsArrayNumber> values){ if(values==null){ return null; } JsArray<Vector3> numbers=JavaScriptUtils.createJSArray(); for(int i=0;i<values.length();i++){ numbers.push(THREE.Vector3().fromArray(values.get(i))); } return numbers; } public static JSONLoaderObject parseJSONGeometry(String text){ JSONObject object=parseJSONGeometryObject(text); if(object==null){ LogUtils.log("parseJSONGeometry:parse faild"); return null; } return THREE.JSONLoader().parse(object.getJavaScriptObject()); } public static JSONObject parseJSONGeometryObject(String text){ JSONValue json=JSONParser.parseStrict(text); JSONObject jsonObject=json.isObject(); boolean hasData=jsonObject.get("data")!=null;//4.* format has this if(hasData){ jsonObject=jsonObject.get("data").isObject(); } return jsonObject; } }