OSDN Git Service

Set optimal mime types and executable settings.
[mikumikustudio/MikuMikuStudio.git] / src / jmetest / intersection / TestTrianglePick.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.intersection;
34
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 import java.net.URL;
39 import java.nio.FloatBuffer;
40 import java.util.List;
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43
44 import com.jme.app.SimpleGame;
45 import com.jme.bounding.BoundingSphere;
46 import com.jme.image.Texture;
47 import com.jme.input.AbsoluteMouse;
48 import com.jme.input.MouseInput;
49 import com.jme.intersection.PickData;
50 import com.jme.intersection.TrianglePickResults;
51 import com.jme.math.Quaternion;
52 import com.jme.math.Ray;
53 import com.jme.math.Vector2f;
54 import com.jme.math.Vector3f;
55 import com.jme.renderer.ColorRGBA;
56 import com.jme.scene.Line;
57 import com.jme.scene.Point;
58 import com.jme.scene.Spatial;
59 import com.jme.scene.TriMesh;
60 import com.jme.scene.state.BlendState;
61 import com.jme.scene.state.TextureState;
62 import com.jme.scene.state.ZBufferState;
63 import com.jme.util.TextureManager;
64 import com.jme.util.export.binary.BinaryImporter;
65 import com.jme.util.geom.BufferUtils;
66 import com.jmex.model.converters.FormatConverter;
67 import com.jmex.model.converters.ObjToJme;
68
69 /**
70  * Started Date: Jul 22, 2004 <br>
71  * <br>
72  * Demonstrates picking with the mouse.
73  * 
74  * @author Jack Lindamood
75  */
76 public class TestTrianglePick extends SimpleGame {
77     private static final Logger logger = Logger
78             .getLogger(TestTrianglePick.class.getName());
79
80     // This will be my mouse
81     AbsoluteMouse am;
82
83     private Point pointSelection;
84
85     Spatial maggie;
86
87     private Line[] selection;
88
89     public static void main(String[] args) {
90         TestTrianglePick app = new TestTrianglePick();
91         app.setConfigShowMode(ConfigShowMode.AlwaysShow);
92         app.start();
93     }
94
95     protected void simpleInitGame() {
96         // Create a new mouse. Restrict its movements to the display screen.
97         am = new AbsoluteMouse("The Mouse", display.getWidth(), display
98                 .getHeight());
99
100         // Get a picture for my mouse.
101         TextureState ts = display.getRenderer().createTextureState();
102         URL cursorLoc = TestTrianglePick.class.getClassLoader().getResource(
103                 "jmetest/data/cursor/cursor1.png");
104         Texture t = TextureManager.loadTexture(cursorLoc, Texture.MinificationFilter.NearestNeighborNoMipMaps,
105                 Texture.MagnificationFilter.Bilinear);
106         ts.setTexture(t);
107         am.setRenderState(ts);
108
109         // Make the mouse's background blend with what's already there
110         BlendState as = display.getRenderer().createBlendState();
111         as.setBlendEnabled(true);
112         as.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
113         as.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
114         as.setTestEnabled(true);
115         as.setTestFunction(BlendState.TestFunction.GreaterThan);
116         am.setRenderState(as);
117
118         // Move the mouse to the middle of the screen to start with
119         am.setLocalTranslation(new Vector3f(display.getWidth() / 2, display
120                 .getHeight() / 2, 0));
121         // Assign the mouse to an input handler
122         am.registerWithInputHandler(input);
123
124         // Create the box in the middle. Give it a bounds
125         URL model = TestTrianglePick.class.getClassLoader().getResource(
126                 "jmetest/data/model/maggie.obj");
127         try {
128             FormatConverter converter = new ObjToJme();
129             converter.setProperty("mtllib", model);
130             ByteArrayOutputStream BO = new ByteArrayOutputStream();
131             converter.convert(model.openStream(), BO);
132             maggie = (Spatial) BinaryImporter.getInstance().load(
133                     new ByteArrayInputStream(BO.toByteArray()));
134             // scale rotate and translate to confirm that world transforms are
135             // handled
136             // correctly.
137             maggie.setLocalScale(.1f);
138             maggie.setLocalTranslation(new Vector3f(3, 1, -5));
139             Quaternion q = new Quaternion();
140             q.fromAngleAxis(0.5f, new Vector3f(0, 1, 0));
141             maggie.setLocalRotation(q);
142         } catch (IOException e) { // Just in case anything happens
143             logger.logp(Level.SEVERE, this.getClass().toString(),
144                     "simpleInitGame()", "Exception", e);
145             System.exit(0);
146         }
147
148         maggie.setModelBound(new BoundingSphere());
149         maggie.updateModelBound();
150         // Attach Children
151         rootNode.attachChild(maggie);
152         rootNode.attachChild(am);
153
154         maggie.lockBounds();
155         maggie.lockTransforms();
156         results.setCheckDistance(true);
157
158         pointSelection = new Point("selected triangle", new Vector3f[1], null,
159                 new ColorRGBA[1], null);
160         pointSelection.setSolidColor(new ColorRGBA(1, 0, 0, 1));
161         pointSelection.setPointSize(10);
162         pointSelection.setAntialiased(true);
163         ZBufferState zbs = display.getRenderer().createZBufferState();
164         zbs.setFunction(ZBufferState.TestFunction.Always);
165         pointSelection.setRenderState(zbs);
166         pointSelection.setLightCombineMode(Spatial.LightCombineMode.Off);
167
168         rootNode.attachChild(pointSelection);
169     }
170
171     private void createSelectionTriangles(int number) {
172         clearPreviousSelections();
173         selection = new Line[number];
174         for (int i = 0; i < selection.length; i++) {
175             selection[i] = new Line("selected triangle" + i, new Vector3f[4],
176                     null, new ColorRGBA[4], null);
177             selection[i].setSolidColor(new ColorRGBA(0, 1, 0, 1));
178             selection[i].setLineWidth(5);
179             selection[i].setAntialiased(true);
180             selection[i].setMode(Line.Mode.Connected);
181
182             ZBufferState zbs = display.getRenderer().createZBufferState();
183             zbs.setFunction(ZBufferState.TestFunction.Always);
184             selection[i].setRenderState(zbs);
185             selection[i].setLightCombineMode(Spatial.LightCombineMode.Off);
186
187             rootNode.attachChild(selection[i]);
188         }
189
190         rootNode.updateGeometricState(0, true);
191         rootNode.updateRenderState();
192     }
193
194     private void clearPreviousSelections() {
195         if (selection != null) {
196             for (Line line : selection) {
197                 rootNode.detachChild(line);
198             }
199         }
200     }
201
202     TrianglePickResults results = new TrianglePickResults() {
203
204         public void processPick() {
205
206             // initialize selection triangles, this can go across multiple
207             // target
208             // meshes.
209             int total = 0;
210             for (int i = 0; i < getNumber(); i++) {
211                 total += getPickData(i).getTargetTris().size();
212             }
213             createSelectionTriangles(total);
214             if (getNumber() > 0) {
215                 int previous = 0;
216                 for (int num = 0; num < getNumber(); num++) {
217                     PickData pData = getPickData(num);
218                     List<Integer> tris = pData.getTargetTris();
219                     TriMesh mesh = (TriMesh) pData.getTargetMesh();
220
221                     for (int i = 0; i < tris.size(); i++) {
222                         int triIndex = tris.get(i);
223                         Vector3f[] vec = new Vector3f[3];
224                         mesh.getTriangle(triIndex, vec);
225                         FloatBuffer buff = selection[i + previous]
226                                 .getVertexBuffer();
227
228                         for (Vector3f v : vec) {
229                             v.multLocal(mesh.getWorldScale());
230                             mesh.getWorldRotation().mult(v, v);
231                             v.addLocal(mesh.getWorldTranslation());
232                         }
233
234                         BufferUtils.setInBuffer(vec[0], buff, 0);
235                         BufferUtils.setInBuffer(vec[1], buff, 1);
236                         BufferUtils.setInBuffer(vec[2], buff, 2);
237                         BufferUtils.setInBuffer(vec[0], buff, 3);
238
239                         if (num == 0 && i == 0) {
240                             selection[i + previous]
241                                     .setSolidColor(new ColorRGBA(1, 0, 0, 1));
242                             Vector3f loc = new Vector3f();
243                             pData.getRay().intersectWhere(vec[0], vec[1],
244                                     vec[2], loc);
245                             BufferUtils.setInBuffer(loc, pointSelection
246                                     .getVertexBuffer(), 0);
247                         }
248                     }
249
250                     previous = tris.size();
251                 }
252             }
253         }
254     };
255
256     // This is called every frame. Do changing of values here.
257     protected void simpleUpdate() {
258
259         // Is button 0 down? Button 0 is left click
260         if (MouseInput.get().isButtonDown(0)) {
261             Vector2f screenPos = new Vector2f();
262             // Get the position that the mouse is pointing to
263             screenPos.set(am.getHotSpotPosition().x, am.getHotSpotPosition().y);
264             // Get the world location of that X,Y value
265             Vector3f worldCoords = display.getWorldCoordinates(screenPos, 1.0f);
266             // Create a ray starting from the camera, and going in the direction
267             // of the mouse's location
268             final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
269                     .subtractLocal(cam.getLocation()));
270             mouseRay.getDirection().normalizeLocal();
271             results.clear();
272
273             maggie.calculatePick(mouseRay, results);
274
275         }
276     }
277 }