package models3D;
import java.awt.event.KeyEvent;
import java.io.File;
import javax.media.opengl.GL;
import org.mt4j.MTApplication;
import org.mt4j.components.MTComponent;
import org.mt4j.components.MTLight;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.shapes.MTPolygon;
import org.mt4j.components.visibleComponents.shapes.mesh.MTSphere;
import org.mt4j.components.visibleComponents.shapes.mesh.MTSphere.TextureMode;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleEvent;
import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
import org.mt4j.sceneManagement.AbstractScene;
import org.mt4j.util.ConstantsAndSettings;
import org.mt4j.util.animation.Animation;
import org.mt4j.util.animation.AnimationEvent;
import org.mt4j.util.animation.IAnimationListener;
import org.mt4j.util.animation.MultiPurposeInterpolator;
import org.mt4j.util.math.Tools3D;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.opengl.GLMaterial;
import org.mt4j.util.opengl.GLTexture;
import org.mt4j.util.opengl.GLTextureParameters;
public class ModelDisplayScene extends AbstractScene {
private MTApplication pa;
private MTComponent meshGroup;
//TODO make earth panable with velocity?
/**
* Instantiates a new model display scene.
*
* @param mtApplication the mt application
* @param name the name
*/
public ModelDisplayScene(MTApplication mtApplication, String name) {
super(mtApplication, name);
this.pa = mtApplication;
this.setClearColor(200, 200, 200, 255);
if (!ConstantsAndSettings.getInstance().isOpenGlMode()){
System.err.println("Scene only usable when using the OpenGL renderer! - See settings.txt");
return;
}
GLTextureParameters tp = new GLTextureParameters();
tp.minFilter = GLTextureParameters.LINEAR;
GLTexture tex = new GLTexture(pa, System.getProperty("user.dir") + File.separator + "examples" + File.separator + "models3D" + File.separator + "data" + File.separator +
"3040.jpg", tp);
float width = pa.width;
float height = pa.height;
float u = width/tex.width;
float v = height/tex.height;
MTPolygon poly = new MTPolygon(
new Vertex[]{
new Vertex(0,0,0, 0,0),
new Vertex(width,0,0, u,0),
new Vertex(width,height,0, u,v),
new Vertex(0,height,0, 0,v),
new Vertex(0,0,0, 0,0)
}
,pa);
poly.setTexture(tex);
poly.setPickable(false);
getCanvas().addChild(poly);
// getCanvas().addChild(new MTRectangle(new GLTexture(pa, System.getProperty("user.dir") + File.separator + "examples" + File.separator + "models3D" + File.separator + "data" + File.separator +
// "stars_background_17.jpg"), pa));
//Init light settings
MTLight.enableLightningAndAmbient(pa, 150, 150, 150, 255);
//Create a light source //I think GL_LIGHT0 is used by processing!
MTLight light = new MTLight(pa, GL.GL_LIGHT3, new Vector3D(0,0,0));
//Set up a material
GLMaterial material = new GLMaterial(Tools3D.getGL(pa));
material.setAmbient(new float[]{ .3f, .3f, .3f, 1f });
material.setDiffuse(new float[]{ .9f, .9f, .9f, 1f } );
material.setEmission(new float[]{ .0f, .0f, .0f, 1f });
material.setSpecular(new float[]{ 1.0f, 1.0f, 1.0f, 1f }); // almost white: very reflective
material.setShininess(110);// 0=no shine, 127=max shine
/*
try {
//Create a group and set the light for the whole group ->better for performance than setting light to more comps
meshGroup = new MTComponent(pa, "Mesh group");
meshGroup.setLight(light);
//Get the factory for loading .3ds files
ModelImporterFactory modelFactory = ModelImporterFactory.getFactory(
".3ds");
// ".obj");
MTTriangleMesh[] meshi = modelFactory.loadModel(pa, System.getProperty("user.dir") + File.separator + "examples" + File.separator + "models3D" + File.separator + "data" + File.separator +
// "monkey.obj", 180, true, true );
"kentosaurus" + File.separator + "kentrosaurus.3ds", 180, true, false );
Vector3D translationToScreenCenter = new Vector3D();
float initialWidth = 0;
float destinationScale = pa.width*0.96f;
//Get the biggest mesh and extract its width
float currentBiggestWidth = Float.MIN_VALUE;
MTTriangleMesh currentBiggestMesh = null;
for (int i = 0; i < meshi.length; i++) {
MTTriangleMesh triangleMesh = meshi[i];
float width = triangleMesh.getWidthXY(TransformSpace.GLOBAL);
if (width > currentBiggestWidth){
currentBiggestWidth = width;
currentBiggestMesh = triangleMesh;
}
}
if (currentBiggestMesh != null){
System.out.println("M center global :" + currentBiggestMesh.getCenterPointGlobal());
translationToScreenCenter.setValues(new Vector3D(pa.width/2, pa.height/2,0).subtractLocal(currentBiggestMesh.getCenterPointGlobal()));
System.out.println("Translation vect: " + translationToScreenCenter);
initialWidth = currentBiggestWidth;
}
destinationScale = destinationScale/initialWidth;
for (int i = 0; i < meshi.length; i++) {
final MTTriangleMesh mesh = meshi[i];
meshGroup.addChild(mesh);
//Scaling gesture is only supported in 2D
mesh.setGestureAllowance(ScaleProcessor.class, false);
mesh.setGestureAllowance(DragProcessor.class, false);
//Register arcball manipulation gesture with the mesh
mesh.registerInputProcessor(new ArcballProcessor(pa, mesh));
mesh.addGestureListener(ArcballProcessor.class, new IGestureEventListener(){
@Override
public boolean processGestureEvent(MTGestureEvent ge) {
ArcBallGestureEvent aEvt = (ArcBallGestureEvent)ge;
if (aEvt.getId() == ArcBallGestureEvent.GESTURE_UPDATED){
mesh.transform(aEvt.getTransformationMatrix());
}
return true;
}
});
mesh.setPickable(true);
//If the mesh has more than 20 vertices, use a Vertex Buffer Object for faster drawing
if (mesh.getVertexCount() > 20){
mesh.setUseVBOs(true);
//mesh.generateAndUseDisplayLists(); //or use a displaylist for drawing..
}
//Set the material to the mesh (determines the reaction to the lightning)
if (mesh.getMaterial() == null){
mesh.setMaterial(material);
}
mesh.setDrawNormals(false);
mesh.scaleGlobal(destinationScale, mesh.getCenterPointGlobal());
//Move mesh to screen center
mesh.translateGlobal(translationToScreenCenter);
}
this.getCanvas().addChild(meshGroup);
//
//TODO bei manchen models normalen falsch? f16 polygon richtung (right/left) -> inkonsistentem polygon winding!?
//TODO methode indexify()machen? manche modelle scheinen nicht zu smoothen weil die triangles nicht auf den gleichen zeigen
} catch (Exception e) {
e.printStackTrace();
}
this.getCanvas().addChild(meshGroup);
*/
////////////////////////////////////////////////////////
// /*
//Create a group and set the light for the whole group ->better for performance than setting light to more comps
final MTSphere earth = new MTSphere(pa, "earth", 40, 40, 150, TextureMode.Projected); //TextureMode.Polar);
earth.setLight(light);
earth.setMaterial(material);
earth.rotateX(earth.getCenterPointRelativeToParent(), -90);
earth.setTexture(new GLTexture(pa, System.getProperty("user.dir") + File.separator + "examples" + File.separator + "models3D" + File.separator + "data" + File.separator +
"worldMap.jpg"));
earth.generateAndUseDisplayLists();
earth.setPositionGlobal(new Vector3D(pa.width/2f, pa.height/2f, 250)); //earth.setPositionGlobal(new Vector3D(200, 200, 250));
//Animate earth rotation
new Animation("rotation animation", new MultiPurposeInterpolator(0,360, 12000, 0, 1, -1) , earth).addAnimationListener(new IAnimationListener(){
@Override
public void processAnimationEvent(AnimationEvent ae) {
earth.rotateY(earth.getCenterPointLocal(), ae.getAnimation().getInterpolator().getCurrentStepDelta(), TransformSpace.LOCAL);
}}).start();
//Scale earth from center
earth.removeAllGestureEventListeners(ScaleProcessor.class);
earth.addGestureListener(ScaleProcessor.class, new IGestureEventListener() {
@Override
public boolean processGestureEvent(MTGestureEvent ge) {
ScaleEvent se = (ScaleEvent)ge;
earth.scaleGlobal(se.getScaleFactorX(), se.getScaleFactorY(), se.getScaleFactorX(), earth.getCenterPointGlobal());
return true;
}
});
this.getCanvas().addChild(earth);
//Create the moon
final MTSphere moonSphere = new MTSphere(pa, "moon", 35, 35, 25, TextureMode.Polar);
moonSphere.setLight(light);
moonSphere.setMaterial(material);
moonSphere.translate(new Vector3D(earth.getRadius() + moonSphere.getRadius() + 50, 0,0));
moonSphere.setTexture(new GLTexture(pa, System.getProperty("user.dir") + File.separator + "examples" + File.separator + "models3D" + File.separator + "data" + File.separator +
"moonmap1k.jpg"));
moonSphere.generateAndUseDisplayLists();
moonSphere.setGestureAllowance(DragProcessor.class, false);
moonSphere.setGestureAllowance(RotateProcessor.class, false);
moonSphere.setGestureAllowance(ScaleProcessor.class, false);
new Animation("moon animation", new MultiPurposeInterpolator(0,360, 12000, 0, 1, -1) , moonSphere).addAnimationListener(new IAnimationListener(){
@Override
public void processAnimationEvent(AnimationEvent ae) {
moonSphere.rotateZ(earth.getCenterPointLocal(), ae.getAnimation().getInterpolator().getCurrentStepDelta(), TransformSpace.RELATIVE_TO_PARENT);
}}).start();
new Animation("moon animation around own axis", new MultiPurposeInterpolator(0,360, 9000, 0, 1, -1) , moonSphere).addAnimationListener(new IAnimationListener(){
@Override
public void processAnimationEvent(AnimationEvent ae) {
moonSphere.rotateZ(moonSphere.getCenterPointLocal(), -3*ae.getAnimation().getInterpolator().getCurrentStepDelta(), TransformSpace.LOCAL);
}}).start();
earth.addChild(moonSphere);
}
@Override
public void init() {
pa.registerKeyEvent(this);
}
@Override
public void shutDown() {
pa.unregisterKeyEvent(this);
}
public void keyEvent(KeyEvent e){
//System.out.println(e.getKeyCode());
int evtID = e.getID();
if (evtID != KeyEvent.KEY_PRESSED)
return;
switch (e.getKeyCode()){
case KeyEvent.VK_F:
System.out.println("FPS: " + pa.frameRate);
break;
default:
break;
}
}
}