OSDN Git Service

55d0515e90e91ab481b262e7fe432685de7e5462
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / scene / SharedMesh.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 com.jme.scene;
34
35 import java.io.IOException;
36 import java.nio.FloatBuffer;
37 import java.nio.IntBuffer;
38 import java.util.ArrayList;
39 import java.util.logging.Logger;
40
41 import com.jme.bounding.BoundingVolume;
42 import com.jme.math.Ray;
43 import com.jme.math.Vector3f;
44 import com.jme.renderer.ColorRGBA;
45 import com.jme.renderer.Renderer;
46 import com.jme.scene.state.RenderState;
47 import com.jme.util.export.InputCapsule;
48 import com.jme.util.export.JMEExporter;
49 import com.jme.util.export.JMEImporter;
50 import com.jme.util.export.OutputCapsule;
51
52 /**
53  * <code>SharedMesh</code> allows the sharing of data between multiple nodes.
54  * A provided TriMesh is used as the model for this node. This allows the user
55  * to place multiple copies of the same object throughout the scene without
56  * having to duplicate data. It should be known that any change to the provided
57  * target mesh will affect the appearance of this mesh, including animations.
58  * Secondly, the SharedMesh is read only. Any attempt to write to the mesh data
59  * via set* methods, will result in a warning being logged and nothing else. Any
60  * changes to the mesh should happened to the target mesh being shared. <br>
61  * If you plan to use collisions with a <code>SharedMesh</code> it is
62  * recommended that you disable the passing of <code>updateCollisionTree</code>
63  * calls to the target mesh. This is to prevent multiple calls to the target's
64  * <code>updateCollisionTree</code> method, from different shared meshes.
65  * Instead of this method being called from the scenegraph, you can now invoke
66  * it directly on the target mesh, thus ensuring it will only be invoked once.
67  * <br>
68  * <b>Important:</b> It is highly recommended that the Target mesh is NOT
69  * placed into the scenegraph, as its translation, rotation and scale are
70  * replaced by the shared meshes using it before they are rendered. <br>
71  * <b>Note:</b> Special thanks to Kevin Glass.
72  * 
73  * @author Mark Powell
74  * @version $id$
75  */
76 public class SharedMesh extends TriMesh {
77     private static final Logger logger = Logger.getLogger(SharedMesh.class
78             .getName());
79
80     private static final long serialVersionUID = 1L;
81
82     private TriMesh target;
83
84     public SharedMesh() {
85         super();
86         defaultColor = null;
87     }
88
89         /**
90          * Constructor creates a new <code>SharedMesh</code> object. Uses the name
91          * of the target.
92          * 
93          * @param target
94          *            the TriMesh to share the data.
95          */
96     public SharedMesh(TriMesh target) {
97         this(target.getName(), target);
98     }
99
100     /**
101      * Constructor creates a new <code>SharedMesh</code> object.
102      * 
103      * @param name
104      *            the name of this shared mesh.
105      * @param target
106      *            the TriMesh to share the data.
107      */
108     public SharedMesh(String name, TriMesh target) {
109
110         super(name);
111         defaultColor = null;
112
113         if (target instanceof SharedMesh) {
114             setTarget(((SharedMesh) target).getTarget());
115             this.setName(target.getName());
116             this.setCullHint(target.cullHint);
117             this.setLightCombineMode(target.lightCombineMode);
118             this.getLocalRotation().set(target.getLocalRotation());
119             this.getLocalScale().set(target.getLocalScale());
120             this.getLocalTranslation().set(target.getLocalTranslation());
121             this.setRenderQueueMode(target.renderQueueMode);
122             this.setTextureCombineMode(target.textureCombineMode);
123             this.setZOrder(target.getZOrder());
124             for (RenderState.StateType type : RenderState.StateType.values()) {
125                 RenderState state = target.getRenderState( type );
126                 if (state != null) {
127                     this.setRenderState(state );
128                 }
129             }
130         } else {
131             setTarget(target);
132         }
133
134         this.localRotation.set(target.getLocalRotation());
135         this.localScale.set(target.getLocalScale());
136         this.localTranslation.set(target.getLocalTranslation());
137     }
138
139     /**
140      * <code>setTarget</code> sets the shared data mesh.
141      * 
142      * @param target
143      *            the TriMesh to share the data.
144      */
145     public void setTarget(TriMesh target) {
146         this.target = target;
147         UserDataManager.getInstance().bind(this, target);
148         for (RenderState.StateType type : RenderState.StateType.values()) {
149             RenderState state = this.target.getRenderState( type );
150             if (state != null) {
151                 setRenderState(state);
152             }
153         }
154
155         setCullHint(target.getLocalCullHint());
156         setLightCombineMode(target.getLocalLightCombineMode());
157         setRenderQueueMode(target.getLocalRenderQueueMode());
158         setTextureCombineMode(target.getLocalTextureCombineMode());
159         setZOrder(target.getZOrder());
160     }
161
162     /**
163      * <code>getTarget</code> returns the mesh that is being shared by this
164      * object.
165      * 
166      * @return the mesh being shared.
167      */
168     public TriMesh getTarget() {
169         return target;
170     }
171
172     /**
173      * <code>reconstruct</code> is not supported in SharedMesh.
174      * 
175      * @param vertices
176      *            the new vertices to use.
177      * @param normals
178      *            the new normals to use.
179      * @param colors
180      *            the new colors to use.
181      * @param textureCoords
182      *            the new texture coordinates to use (position 0).
183      */
184     @Override
185     public void reconstruct(FloatBuffer vertices, FloatBuffer normals,
186             FloatBuffer colors, TexCoords textureCoords) {
187         logger.info("SharedMesh will ignore reconstruct.");
188     }
189
190     /**
191      * <code>setVBOInfo</code> is not supported in SharedMesh.
192      */
193     @Override
194     public void setVBOInfo(VBOInfo info) {
195         logger.warning("SharedMesh does not allow the manipulation"
196                 + "of the the mesh data.");
197     }
198
199     /**
200      * <code>getVBOInfo</code> returns the target mesh's vbo info.
201      */
202     @Override
203     public VBOInfo getVBOInfo() {
204         return target.getVBOInfo();
205     }
206
207     /**
208      * <code>setSolidColor</code> is not supported by SharedMesh.
209      * 
210      * @param color
211      *            the color to set.
212      */
213     @Override
214     public void setSolidColor(ColorRGBA color) {
215         logger.warning("SharedMesh does not allow the manipulation"
216                 + "of the the mesh data.");
217     }
218
219     /**
220      * <code>setRandomColors</code> is not supported by SharedMesh.
221      */
222     @Override
223     public void setRandomColors() {
224         logger.warning("SharedMesh does not allow the manipulation"
225                 + "of the the mesh data.");
226     }
227
228     /**
229      * <code>getVertexBuffer</code> returns the float buffer that contains the
230      * target geometry's vertex information.
231      * 
232      * @return the float buffer that contains the target geometry's vertex
233      *         information.
234      */
235     @Override
236     public FloatBuffer getVertexBuffer() {
237         return target.getVertexBuffer();
238     }
239
240     /**
241      * <code>setVertexBuffer</code> is not supported by SharedMesh.
242      * 
243      * @param buff
244      *            the new vertex buffer.
245      */
246     @Override
247     public void setVertexBuffer(FloatBuffer buff) {
248         logger.warning("SharedMesh does not allow the manipulation"
249                 + "of the the mesh data.");
250     }
251
252     /**
253      * Returns the number of vertexes defined in the target's Geometry object.
254      * 
255      * @return The number of vertexes in the target Geometry object.
256      */
257     @Override
258     public int getVertexCount() {
259         return target.getVertexCount();
260     }
261
262     /**
263      * <code>getNormalBuffer</code> retrieves the target geometry's normal
264      * information as a float buffer.
265      * 
266      * @return the float buffer containing the target geometry information.
267      */
268     @Override
269     public FloatBuffer getNormalBuffer() {
270         return target.getNormalBuffer();
271     }
272
273     /**
274      * <code>setNormalBuffer</code> is not supported by SharedMesh.
275      * 
276      * @param buff
277      *            the new normal buffer.
278      */
279     @Override
280     public void setNormalBuffer(FloatBuffer buff) {
281         logger.warning("SharedMesh does not allow the manipulation"
282                 + "of the the mesh data.");
283     }
284
285     /**
286      * <code>getColorBuffer</code> retrieves the float buffer that contains
287      * the target geometry's color information.
288      * 
289      * @return the buffer that contains the target geometry's color information.
290      */
291     @Override
292     public FloatBuffer getColorBuffer() {
293         return target.getColorBuffer();
294     }
295
296     /**
297      * <code>setColorBuffer</code> is not supported by SharedMesh.
298      * 
299      * @param buff
300      *            the new color buffer.
301      */
302     @Override
303     public void setColorBuffer(FloatBuffer buff) {
304         logger.warning("SharedMesh does not allow the manipulation"
305                 + "of the the mesh data.");
306     }
307
308     /**
309      * <code>getIndexAsBuffer</code> retrieves the target's indices array as
310      * an <code>IntBuffer</code>.
311      * 
312      * @return the indices array as an <code>IntBuffer</code>.
313      */
314     @Override
315     public IntBuffer getIndexBuffer() {
316         return target.getIndexBuffer();
317     }
318
319     /**
320      * <code>setIndexBuffer</code> is not supported by SharedMesh.
321      * 
322      * @param indices
323      *            the index array as an IntBuffer.
324      */
325     @Override
326     public void setIndexBuffer(IntBuffer indices) {
327         logger.warning("SharedMesh does not allow the manipulation"
328                 + "of the the mesh data.");
329     }
330
331     /**
332      * Stores in the <code>storage</code> array the indices of triangle
333      * <code>i</code>. If <code>i</code> is an invalid index, or if
334      * <code>storage.length<3</code>, then nothing happens
335      * 
336      * @param i
337      *            The index of the triangle to get.
338      * @param storage
339      *            The array that will hold the i's indexes.
340      */
341     @Override
342     public void getTriangle(int i, int[] storage) {
343         target.getTriangle(i, storage);
344     }
345
346     /**
347      * Stores in the <code>vertices</code> array the vertex values of triangle
348      * <code>i</code>. If <code>i</code> is an invalid triangle index,
349      * nothing happens.
350      * 
351      * @param i
352      * @param vertices
353      */
354     @Override
355     public void getTriangle(int i, Vector3f[] vertices) {
356         target.getTriangle(i, vertices);
357     }
358
359     /**
360      * Returns the number of triangles the target TriMesh contains.
361      * 
362      * @return The current number of triangles.
363      */
364     @Override
365     public int getTriangleCount() {
366         return target.getTriangleCount();
367     }
368
369     /**
370      * <code>copyTextureCoords</code> is not supported by SharedMesh.
371      * 
372      * @param fromIndex
373      *            the coordinates to copy.
374      * @param toIndex
375      *            the texture unit to set them to.
376      */
377     @Override
378     public void copyTextureCoordinates(int fromIndex, int toIndex, float factor) {
379         logger.warning("SharedMesh does not allow the manipulation"
380                 + "of the the mesh data.");
381     }
382
383     /**
384      * <code>getTextureBuffers</code> retrieves the target geometry's texture
385      * information contained within a float buffer array.
386      * 
387      * @return the float buffers that contain the target geometry's texture
388      *         information.
389      */
390     @Override
391     public ArrayList<TexCoords> getTextureCoords() {
392         return target.getTextureCoords();
393     }
394
395     /**
396      * <code>getTextureAsFloatBuffer</code> retrieves the texture buffer of a
397      * given texture unit.
398      * 
399      * @param textureUnit
400      *            the texture unit to check.
401      * @return the texture coordinates at the given texture unit.
402      */
403     @Override
404     public TexCoords getTextureCoords(int textureUnit) {
405         return target.getTextureCoords(textureUnit);
406     }
407
408     /**
409      * retrieves the mesh as triangle vertices of the target mesh.
410      */
411     @Override
412     public Vector3f[] getMeshAsTrianglesVertices(Vector3f[] verts) {
413         return target.getMeshAsTrianglesVertices(verts);
414     }
415
416     /**
417      * clearBuffers is not supported by SharedMesh
418      */
419     @Override
420     public void clearBuffers() {
421         logger.warning("SharedMesh does not allow the manipulation"
422                 + "of the the mesh data.");
423     }
424
425     /**
426      * This function checks for intersection between the target trimesh and the
427      * given one. On the first intersection, true is returned.
428      * 
429      * @param toCheck
430      *            The intersection testing mesh.
431      * @return True if they intersect.
432      */
433     @Override
434     public boolean hasTriangleCollision(TriMesh toCheck) {
435         target.setLocalTranslation(worldTranslation);
436         target.setLocalRotation(worldRotation);
437         target.setLocalScale(worldScale);
438         target.updateWorldBound();
439         return target.hasTriangleCollision(toCheck);
440     }
441
442     /**
443      * This function finds all intersections between this trimesh and the
444      * checking one. The intersections are stored as Integer objects of Triangle
445      * indexes in each of the parameters.
446      * 
447      * @param toCheck
448      *            The TriMesh to check.
449      * @param thisIndex
450      *            The array of triangle indexes intersecting in this mesh.
451      * @param otherIndex
452      *            The array of triangle indexes intersecting in the given mesh.
453      */
454     @Override
455     public void findTriangleCollision(TriMesh toCheck,
456             ArrayList<Integer> thisIndex, ArrayList<Integer> otherIndex) {
457         target.setLocalTranslation(worldTranslation);
458         target.setLocalRotation(worldRotation);
459         target.setLocalScale(worldScale);
460         target.updateWorldBound();
461         target.findTriangleCollision(toCheck, thisIndex, otherIndex);
462     }
463
464     /**
465      * <code>findTrianglePick</code> determines the triangles of the target
466      * trimesh that are being touched by the ray. The indices of the triangles
467      * are stored in the provided ArrayList.
468      * 
469      * @param toTest
470      *            the ray to test.
471      * @param results
472      *            the indices to the triangles.
473      */
474     @Override
475     public void findTrianglePick(Ray toTest, ArrayList<Integer> results) {
476         target.setLocalTranslation(worldTranslation);
477         target.setLocalRotation(worldRotation);
478         target.setLocalScale(worldScale);
479         target.updateWorldBound();
480         target.findTrianglePick(toTest, results);
481     }
482
483     @Override
484     public void write(JMEExporter e) throws IOException {
485         OutputCapsule capsule = e.getCapsule(this);
486         capsule.write(target, "target", null);
487         super.write(e);
488     }
489
490     @Override
491     public void read(JMEImporter e) throws IOException {
492         InputCapsule capsule = e.getCapsule(this);
493         target = (TriMesh) capsule.readSavable("target", null);
494         super.read(e);
495     }
496
497     /**
498      * @see Geometry#randomVertex(Vector3f)
499      */
500     @Override
501     public Vector3f randomVertex(Vector3f fill) {
502         return target.randomVertex(fill);
503     }
504
505     /**
506      * <code>setTextureBuffer</code> is not supported by SharedMesh.
507      * 
508      * @param buff
509      *            the new vertex buffer.
510      */
511     @Override
512     public void setTextureCoords(TexCoords buff) {
513         logger.warning("SharedMesh does not allow the manipulation"
514                 + "of the the mesh data.");
515     }
516
517     /**
518      * <code>setTextureBuffer</code> not supported by SharedMesh
519      * 
520      * @param buff
521      *            the new vertex buffer.
522      */
523     @Override
524     public void setTextureCoords(TexCoords buff, int position) {
525         logger.warning("SharedMesh does not allow the manipulation"
526                 + "of the the mesh data.");
527     }
528
529     @Override
530     public void setTangentBuffer(FloatBuffer tangentBuf) {
531         logger.warning("SharedMesh does not allow the manipulation"
532                 + "of the the mesh data.");
533     }
534
535     @Override
536     public FloatBuffer getTangentBuffer() {
537         return target.getTangentBuffer();
538     }
539
540     @Override
541     public void setBinormalBuffer(FloatBuffer binormalBuf) {
542         logger.warning("SharedMesh does not allow the manipulation"
543                 + "of the the mesh data.");
544     }
545
546     @Override
547     public FloatBuffer getBinormalBuffer() {
548         return target.getBinormalBuffer();
549     }
550
551     /**
552      * <code>updateWorldBound</code> updates the bounding volume that contains
553      * this geometry. The location of the geometry is based on the location of
554      * all this node's parents.
555      * 
556      * @see com.jme.scene.Spatial#updateWorldBound()
557      */
558     @Override
559     public void updateWorldBound() {
560         if (target.getModelBound() != null) {
561             worldBound = target.getModelBound().transform(getWorldRotation(),
562                     getWorldTranslation(), getWorldScale(), worldBound);
563         }
564     }
565
566     /**
567      * <code>setModelBound</code> sets the bounding object for this geometry.
568      * 
569      * @param modelBound
570      *            the bounding object for this geometry.
571      */
572     @Override
573     public void setModelBound(BoundingVolume modelBound) {
574         target.setModelBound(modelBound);
575     }
576
577     /**
578      * <code>updateBound</code> recalculates the bounding object assigned to
579      * the geometry. This resets it parameters to adjust for any changes to the
580      * vertex information.
581      */
582     @Override
583     public void updateModelBound() {
584         if (target.getModelBound() != null) {
585             target.updateModelBound();
586             updateWorldBound();
587         }
588     }
589
590     /**
591      * returns the model bound of the target object.
592      */
593     @Override
594     public BoundingVolume getModelBound() {
595         return target.getModelBound();
596     }
597
598     /**
599      * draw renders the target mesh, at the translation, rotation and scale of
600      * this shared mesh.
601      * 
602      * @see com.jme.scene.Spatial#draw(com.jme.renderer.Renderer)
603      */
604     @Override
605     public void draw(Renderer r) {
606         if (!r.isProcessingQueue()) {
607             if (r.checkAndAdd(this))
608                 return;
609         }
610
611         target.getWorldTranslation().set(getWorldTranslation());
612         target.getWorldRotation().set(getWorldRotation());
613         target.getWorldScale().set(getWorldScale());
614         target.setDefaultColor(getDefaultColor());
615         System.arraycopy(this.states, 0, target.states, 0, states.length);
616
617         r.draw(target);
618     }
619
620     @Override
621     public void lockMeshes(Renderer r) {
622         target.lockMeshes(r);
623     }
624
625     @Override
626     public boolean hasDirtyVertices() {
627         return target.hasDirtyVertices;
628     }
629
630     @Override
631     public ColorRGBA getDefaultColor() {
632         if (defaultColor == null) {
633             return target.getDefaultColor();
634         } else {
635             return defaultColor;
636         }
637     }
638 }