OSDN Git Service

Set optimal mime types and executable settings.
[mikumikustudio/MikuMikuStudio.git] / src / jmetest / TutorialGuide / HelloLOD.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
17  *   may be used to endorse or promote products derived from this software 
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 package jmetest.TutorialGuide;
34
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 import java.net.URL;
39 import java.util.logging.Level;
40 import java.util.logging.Logger;
41
42 import com.jme.app.SimpleGame;
43 import com.jme.bounding.BoundingSphere;
44 import com.jme.curve.BezierCurve;
45 import com.jme.curve.CurveController;
46 import com.jme.input.InputHandler;
47 import com.jme.input.KeyInput;
48 import com.jme.input.action.KeyExitAction;
49 import com.jme.math.Matrix3f;
50 import com.jme.math.Vector3f;
51 import com.jme.scene.CameraNode;
52 import com.jme.scene.Controller;
53 import com.jme.scene.Node;
54 import com.jme.scene.Spatial;
55 import com.jme.scene.TriMesh;
56 import com.jme.scene.lod.AreaClodMesh;
57 import com.jme.scene.state.RenderState;
58 import com.jme.util.export.binary.BinaryImporter;
59 import com.jmex.model.converters.FormatConverter;
60 import com.jmex.model.converters.ObjToJme;
61
62 /**
63  * Started Date: Aug 16, 2004<br><br>
64  *
65  * This program teaches Complex Level of Detail mesh objects.  To use this program, move
66  * the camera backwards and watch the model disappear.
67  * 
68  * @author Jack Lindamood
69  */
70 public class HelloLOD extends SimpleGame {
71     private static final Logger logger = Logger.getLogger(HelloLOD.class
72             .getName());
73
74     CameraNode cn;
75
76     public static void main(String[] args) {
77         HelloLOD app = new HelloLOD();
78         app.setConfigShowMode(ConfigShowMode.AlwaysShow);
79         app.start();
80     }
81
82     protected void simpleInitGame() {
83         // Point to a URL of my model
84         URL model=HelloModelLoading.class.getClassLoader().getResource("jmetest/data/model/maggie.obj");
85
86         // Create something to convert .obj format to .jme
87         FormatConverter converter=new ObjToJme();
88         // Point the converter to where it will find the .mtl file from
89         converter.setProperty("mtllib",model);
90
91         // This byte array will hold my .jme file
92         ByteArrayOutputStream BO=new ByteArrayOutputStream();
93         Spatial maggie = null;
94         try {
95             // Use the format converter to convert .obj to .jme
96             converter.convert(model.openStream(), BO);
97
98             // Load the binary .jme format into a scene graph
99             maggie=(Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
100             
101
102         } catch (IOException e) {   // Just in case anything happens
103             logger.logp(Level.SEVERE, this.getClass().toString(),
104                     "simpleInitGame()", "Exception", e);
105             System.exit(0);
106         }
107
108         // Create a clod duplicate of meshParent.
109         Node clodNode=getClodNodeFromParent((Node)maggie);
110
111         // Attach the clod mesh at the origin.
112         clodNode.setLocalScale(.1f);
113         rootNode.attachChild(clodNode);
114
115         // Attach the original at -15,0,0
116         maggie.setLocalScale(.1f);
117         maggie.setLocalTranslation(new Vector3f(-15,0,0));
118
119         rootNode.attachChild(maggie);
120
121         // Clear the keyboard commands that can move the camera.
122         input = new InputHandler();
123         // Insert a keyboard command that can exit the application.
124         input.addAction( new KeyExitAction(this), "exit", KeyInput.KEY_ESCAPE, false );
125
126         // The path the camera will take.
127         Vector3f[]cameraPoints=new Vector3f[]{
128             new Vector3f(0,5,20),
129             new Vector3f(0,20,90),
130             new Vector3f(0,30,200),
131             new Vector3f(0,100,300),
132             new Vector3f(0,150,400),
133         };
134         // Create a path for the camera.
135         BezierCurve bc=new BezierCurve("camera path",cameraPoints);
136
137         // Create a camera node to move along that path.
138         cn=new CameraNode("camera node",cam);
139
140         // Create a curve controller to move the CameraNode along the path
141         CurveController cc=new CurveController(bc,cn);
142
143         // Cycle the animation.
144         cc.setRepeatType(Controller.RT_CYCLE);
145
146         // Slow down the curve controller a bit
147         cc.setSpeed(.25f);
148
149         // Add the controller to the node.
150         cn.addController(cc);
151
152         // Attach the node to rootNode
153         rootNode.attachChild(cn);
154     }
155
156     private Node getClodNodeFromParent(Node meshParent) {
157         // Create a node to hold my cLOD mesh objects
158         Node clodNode=new Node("Clod node");
159         // For each mesh in maggie
160         for (int i=0;i<meshParent.getQuantity();i++){
161             final Spatial child = meshParent.getChild(i);
162             if ( child instanceof Node )
163             {
164                 clodNode.attachChild( getClodNodeFromParent( (Node) child ) );
165             }
166             else if ( child instanceof TriMesh )
167             {
168                 // Create an AreaClodMesh for that mesh.  Let it compute records automatically
169                 AreaClodMesh acm=new AreaClodMesh("part"+i,(TriMesh) child,null);
170                 acm.setModelBound(new BoundingSphere());
171                 acm.updateModelBound();
172
173                 // Allow 1/2 of a triangle in every pixel on the screen in the bounds.
174                 acm.setTrisPerPixel(.5f);
175
176                 // Force a move of 2 units before updating the mesh geometry
177                 acm.setDistanceTolerance(2);
178
179                 // Give the clodMesh node the material state that the original had.
180                 acm.setRenderState(child.getRenderState(RenderState.StateType.Material));
181
182                 // Attach clod node.
183                 clodNode.attachChild(acm);
184             }
185             else
186             {
187                 logger.warning("Unhandled Spatial type: " + child.getClass());
188             }
189         }
190         return clodNode;
191     }
192
193     Vector3f up=new Vector3f(0,1,0);
194     Vector3f left=new Vector3f(1,0,0);
195
196     private static Vector3f tempVa=new Vector3f();
197     private static Vector3f tempVb=new Vector3f();
198     private static Vector3f tempVc=new Vector3f();
199     private static Vector3f tempVd=new Vector3f();
200     private static Matrix3f tempMa=new Matrix3f();
201
202     protected void simpleUpdate(){
203         // Get the center of root's bound.
204         Vector3f objectCenter=rootNode.getWorldBound().getCenter(tempVa);
205
206         // My direction is the place I want to look minus the location of the camera.
207         Vector3f lookAtObject=tempVb.set(objectCenter).subtractLocal(cam.getLocation()).normalizeLocal();
208
209         // Left vector
210         tempMa.setColumn(0,up.cross(lookAtObject,tempVc).normalizeLocal());
211         // Up vector
212         tempMa.setColumn(1,left.cross(lookAtObject,tempVd).normalizeLocal());
213         // Direction vector
214         tempMa.setColumn(2,lookAtObject);
215
216         cn.setLocalRotation(tempMa);
217     }
218 }