/examples/advanced/models3D/Models3DScene.java

http://mt4j.googlecode.com/ · Java · 205 lines · 146 code · 37 blank · 22 comment · 14 complexity · a02743550d93c96bd2ac09e14ca75160 MD5 · raw file

  1. package advanced.models3D;
  2. import java.awt.event.KeyEvent;
  3. import javax.media.opengl.GL;
  4. import org.mt4j.MTApplication;
  5. import org.mt4j.components.MTComponent;
  6. import org.mt4j.components.MTLight;
  7. import org.mt4j.components.TransformSpace;
  8. import org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh;
  9. import org.mt4j.input.gestureAction.DefaultRotateAction;
  10. import org.mt4j.input.gestureAction.DefaultZoomAction;
  11. import org.mt4j.input.inputProcessors.IGestureEventListener;
  12. import org.mt4j.input.inputProcessors.MTGestureEvent;
  13. import org.mt4j.input.inputProcessors.componentProcessors.arcballProcessor.ArcBallGestureEvent;
  14. import org.mt4j.input.inputProcessors.componentProcessors.arcballProcessor.ArcballProcessor;
  15. import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
  16. import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleEvent;
  17. import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
  18. import org.mt4j.input.inputProcessors.componentProcessors.zoomProcessor.ZoomProcessor;
  19. import org.mt4j.input.inputProcessors.globalProcessors.CursorTracer;
  20. import org.mt4j.sceneManagement.AbstractScene;
  21. import org.mt4j.util.MT4jSettings;
  22. import org.mt4j.util.MTColor;
  23. import org.mt4j.util.math.Tools3D;
  24. import org.mt4j.util.math.Vector3D;
  25. import org.mt4j.util.modelImporter.ModelImporterFactory;
  26. import org.mt4j.util.opengl.GLMaterial;
  27. import org.mt4jx.input.gestureAction.Rotate3DAction;
  28. import org.mt4jx.input.inputProcessors.componentProcessors.Rotate3DProcessor.Rotate3DProcessor;
  29. public class Models3DScene extends AbstractScene {
  30. private MTApplication mtApp;
  31. //TODO switch button/wireframe
  32. // private String modelsPath = System.getProperty("user.dir") + File.separator + "examples" + File.separator +"advanced"+ File.separator + "models3D" + File.separator + "data" + File.separator;
  33. private String modelsPath = "advanced" + MTApplication.separator + "models3D" + MTApplication.separator + "data" + MTApplication.separator;
  34. public Models3DScene(MTApplication mtApplication, String name) {
  35. super(mtApplication, name);
  36. mtApp = mtApplication;
  37. this.setClearColor(new MTColor(40,40,40,255));
  38. this.registerGlobalInputProcessor(new CursorTracer(mtApp, this));
  39. //Make canvas zoomable
  40. this.getCanvas().registerInputProcessor(new ZoomProcessor(mtApp));
  41. this.getCanvas().addGestureListener(ZoomProcessor.class, new DefaultZoomAction());
  42. if (!(MT4jSettings.getInstance().isOpenGlMode())){
  43. System.err.println(this.getClass().getName() + " example can only be run in OpenGL mode.");
  44. return;
  45. }
  46. //Init light settings
  47. MTLight.enableLightningAndAmbient(mtApplication, 150, 150, 150, 255);
  48. //Create a light source //I think GL_LIGHT0 is used by processing!
  49. MTLight light = new MTLight(mtApplication, GL.GL_LIGHT3, new Vector3D(0,-300,0));
  50. //Set up a material to react to the light
  51. GLMaterial material = new GLMaterial(Tools3D.getGL(mtApplication));
  52. material.setAmbient(new float[]{ .5f, .5f, .5f, 1f });
  53. material.setDiffuse(new float[]{ .8f, .8f, .8f, 1f } );
  54. material.setEmission(new float[]{ .0f, .0f, .0f, 1f });
  55. material.setSpecular(new float[]{ 0.9f, 0.9f, 0.9f, 1f }); // almost white: very reflective
  56. material.setShininess(110);// 0=no shine, 127=max shine
  57. //Group used to move to the screen center and to put the mesh group in
  58. MTComponent group1 = new MTComponent(mtApplication);
  59. //Create a group and set the light for the whole mesh group ->better for performance than setting light to more comps
  60. final MTComponent meshGroup = new MTComponent(mtApplication, "Mesh group");
  61. meshGroup.setLight(light);
  62. //Desired position for the meshes to appear at
  63. Vector3D destinationPosition = new Vector3D(mtApplication.width/2, mtApplication.height/2, 50);
  64. //Desired scale for the meshes
  65. float destinationScale = mtApplication.width*0.85f;
  66. //Load the meshes with the ModelImporterFactory (A file can contain more than 1 mesh)
  67. //Loads 3ds model
  68. MTTriangleMesh[] meshes = ModelImporterFactory.loadModel(mtApplication, modelsPath + "jazz_Obj" + MTApplication.separator + "honda_jazz.obj", 180, true, false );
  69. //Get the biggest mesh in the group to use as a reference for setting the position/scale
  70. final MTTriangleMesh biggestMesh = this.getBiggestMesh(meshes);
  71. Vector3D translationToScreenCenter = new Vector3D(destinationPosition);
  72. translationToScreenCenter.subtractLocal(biggestMesh.getCenterPointGlobal());
  73. Vector3D scalingPoint = new Vector3D(biggestMesh.getCenterPointGlobal());
  74. float biggestWidth = biggestMesh.getWidthXY(TransformSpace.GLOBAL);
  75. float scale = destinationScale/biggestWidth;
  76. //Move the group the the desired position
  77. group1.scaleGlobal(scale, scale, scale, scalingPoint);
  78. group1.translateGlobal(translationToScreenCenter);
  79. this.getCanvas().addChild(group1);
  80. group1.addChild(meshGroup);
  81. //Inverts the normals, if they are calculated pointing inside of the mesh instead of outside
  82. boolean invertNormals = true;
  83. for (MTTriangleMesh mesh : meshes) {
  84. meshGroup.addChild(mesh);
  85. mesh.unregisterAllInputProcessors(); //Clear previously registered input processors
  86. mesh.setPickable(true);
  87. if (invertNormals) {
  88. Vector3D[] normals = mesh.getGeometryInfo().getNormals();
  89. for (Vector3D vector3d : normals) {
  90. vector3d.scaleLocal(-1);
  91. }
  92. mesh.getGeometryInfo().setNormals(mesh.getGeometryInfo().getNormals(), mesh.isUseDirectGL(), mesh.isUseVBOs());
  93. }
  94. //If the mesh has more than 20 vertices, use a display list for faster rendering
  95. if (mesh.getVertexCount() > 20)
  96. mesh.generateAndUseDisplayLists();
  97. //Set the material to the mesh (determines the reaction to the lightning)
  98. if (mesh.getMaterial() == null)
  99. mesh.setMaterial(material);
  100. mesh.setDrawNormals(false);
  101. }
  102. //Register arcball gesture manipulation to the whole mesh-group
  103. meshGroup.setComposite(true); //-> Group gets picked instead of its children
  104. meshGroup.registerInputProcessor(new ArcballProcessor(mtApplication, biggestMesh));
  105. meshGroup.addGestureListener(ArcballProcessor.class, new IGestureEventListener(){
  106. //@Override
  107. public boolean processGestureEvent(MTGestureEvent ge) {
  108. ArcBallGestureEvent aEvt = (ArcBallGestureEvent)ge;
  109. meshGroup.transform(aEvt.getTransformationMatrix());
  110. return false;
  111. }
  112. });
  113. meshGroup.registerInputProcessor(new ScaleProcessor(mtApplication));
  114. meshGroup.addGestureListener(ScaleProcessor.class, new IGestureEventListener(){
  115. //@Override
  116. public boolean processGestureEvent(MTGestureEvent ge) {
  117. ScaleEvent se = (ScaleEvent)ge;
  118. meshGroup.scaleGlobal(se.getScaleFactorX(), se.getScaleFactorY(), se.getScaleFactorX(), biggestMesh.getCenterPointGlobal());
  119. return false;
  120. }
  121. });
  122. meshGroup.registerInputProcessor(new RotateProcessor(mtApplication));
  123. meshGroup.addGestureListener(RotateProcessor.class, new DefaultRotateAction());
  124. meshGroup.registerInputProcessor(new Rotate3DProcessor(mtApplication, meshGroup));
  125. meshGroup.addGestureListener(Rotate3DProcessor.class, new Rotate3DAction(mtApplication, meshGroup));
  126. }
  127. public MTTriangleMesh getBiggestMesh(MTTriangleMesh[] meshes){
  128. MTTriangleMesh currentBiggestMesh = null;
  129. //Get the biggest mesh and extract its width
  130. float currentBiggestWidth = Float.MIN_VALUE;
  131. for (MTTriangleMesh triangleMesh : meshes) {
  132. float width = triangleMesh.getWidthXY(TransformSpace.GLOBAL);
  133. if (width >= currentBiggestWidth || currentBiggestWidth == Float.MIN_VALUE) {
  134. currentBiggestWidth = width;
  135. currentBiggestMesh = triangleMesh;
  136. }
  137. }
  138. return currentBiggestMesh;
  139. }
  140. public void onEnter() {
  141. getMTApplication().registerKeyEvent(this);
  142. }
  143. public void onLeave() {
  144. getMTApplication().unregisterKeyEvent(this);
  145. }
  146. public void keyEvent(KeyEvent e){
  147. //System.out.println(e.getKeyCode());
  148. int evtID = e.getID();
  149. if (evtID != KeyEvent.KEY_PRESSED)
  150. return;
  151. switch (e.getKeyCode()){
  152. case KeyEvent.VK_F:
  153. System.out.println("FPS: " + mtApp.frameRate);
  154. break;
  155. case KeyEvent.VK_PLUS:
  156. this.getSceneCam().moveCamAndViewCenter(0, 0, -10);
  157. break;
  158. case KeyEvent.VK_MINUS:
  159. this.getSceneCam().moveCamAndViewCenter(0, 0, +10);
  160. break;
  161. case KeyEvent.VK_F12:
  162. getMTApplication().saveFrame(); //Screenshot
  163. break;
  164. default:
  165. break;
  166. }
  167. }
  168. }