PageRenderTime 29ms CodeModel.GetById 15ms app.highlight 11ms RepoModel.GetById 0ms app.codeStats 1ms

/examples/advanced/models3D/Models3DScene.java

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