OSDN Git Service

68df35565a51c29cdd00dd4898cf32208c6bc98b
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / util / BoneDebugger.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 package com.jme.util;
33
34 import com.jme.animation.Bone;
35 import com.jme.math.Quaternion;
36 import com.jme.math.Vector3f;
37 import com.jme.renderer.ColorRGBA;
38 import com.jme.renderer.Renderer;
39 import com.jme.scene.Node;
40 import com.jme.scene.Spatial;
41 import com.jme.scene.shape.Box;
42 import com.jme.scene.shape.Cylinder;
43 import com.jme.scene.shape.Sphere;
44 import com.jme.scene.state.TextureState;
45 import com.jme.scene.state.ZBufferState;
46
47 /**
48  *  BoneDebugger is responsible for visually representing a skeletal system (a
49  *  heirarchy of Bone nodes). To visualize the skeleton, a Bone is represented
50  *  as a red sphere and the connection between bones as a white cylinder. Additionally,
51  *  hardpoints are presented as green boxes. 
52  *  
53  *  Standard usage requires the passing in of the model that contains a skeleton 
54  *  to the drawBones method. This method will render the bones on screen as 
55  *  required. 
56  *  
57  *  @see com.jme.animation.Bone
58  *
59  */
60 public final class BoneDebugger {
61
62     private static Sphere boneSphere = new Sphere("boneSphere", new Vector3f(), 6, 6, .125f);
63     private static Box hardpointBox = new Box("hardpoint", new Vector3f(), 0.125f, 0.125f, 0.125f);
64     private static Cylinder boneCylinder = new Cylinder("boneCylinder", 3, 8, .03f, 1f);
65     static {
66         boneSphere.setLightCombineMode(Spatial.LightCombineMode.Off);
67         boneSphere.setTextureCombineMode(Spatial.TextureCombineMode.Off);
68         boneSphere.setSolidColor(ColorRGBA.red.clone());
69         boneSphere.setRenderQueueMode(Renderer.QUEUE_SKIP);
70         
71         hardpointBox.setLightCombineMode(Spatial.LightCombineMode.Off);
72         hardpointBox.setTextureCombineMode(Spatial.TextureCombineMode.Off);
73         hardpointBox.setSolidColor(ColorRGBA.green.clone());
74         hardpointBox.setRenderQueueMode(Renderer.QUEUE_SKIP);
75
76         boneCylinder.setLightCombineMode(Spatial.LightCombineMode.Off);
77         boneCylinder.setTextureCombineMode(Spatial.TextureCombineMode.Off);
78         boneCylinder.setSolidColor(ColorRGBA.white.clone());
79         boneCylinder.setRenderQueueMode(Renderer.QUEUE_SKIP);
80     }
81
82     private static boolean inited = false;
83     private static Vector3f tempTrans = new Vector3f();
84     private static Vector3f tempScale = new Vector3f();
85     private static Quaternion tempRot = new Quaternion();
86     private static Quaternion tempQ = new Quaternion();
87     private static Vector3f tempA = new Vector3f();
88     private static Vector3f tempB = new Vector3f();
89     private static Vector3f tempC = new Vector3f();
90     private static Vector3f tempD = new Vector3f();
91
92     public static void drawBones(Spatial spat, Renderer r) {
93         drawBones(spat, r, true);
94     }
95
96     public static void drawBones(Spatial spat, Renderer r, boolean drawChildren) {
97         if (!inited) {
98             TextureState noTextureState = r.createTextureState();
99             noTextureState.setEnabled(false);
100             boneSphere.setRenderState(noTextureState);
101             hardpointBox.setRenderState(noTextureState);
102             boneCylinder.setRenderState(noTextureState);
103             
104             ZBufferState noBufferState = r.createZBufferState();
105             noBufferState.setEnabled(true);
106             noBufferState.setWritable(true);
107             noBufferState.setFunction(ZBufferState.TestFunction.Always);
108             boneSphere.setRenderState(noBufferState);
109             hardpointBox.setRenderState(noBufferState);
110             boneCylinder.setRenderState(noBufferState);
111
112             boneSphere.updateRenderState();
113             boneSphere.updateGeometricState(0, false);
114             hardpointBox.updateRenderState();
115             hardpointBox.updateGeometricState(0, false);
116             boneCylinder.updateRenderState();
117             boneCylinder.updateGeometricState(0, false);
118             boneSphere.lockMeshes();
119             hardpointBox.lockMeshes();
120             boneCylinder.lockMeshes();
121             inited = true;
122         }
123         
124         if (spat instanceof Bone) {
125             drawTheBones(null, (Bone)spat, r);
126         }
127
128         if ((spat instanceof Node) && drawChildren) {
129             Node n = (Node) spat;
130             for (int x = 0, count = n.getQuantity(); x < count; x++) {
131                 drawBones(n.getChild(x), r, true);
132             }
133         }
134     }
135
136     private static void drawTheBones(Spatial skin, Bone bone, Renderer r) {
137         if(skin == null) {
138             tempTrans.set(0,0,0);
139             tempRot.set(0, 0, 0, 1);
140             tempScale.set(1,1,1);
141         } else {
142             tempTrans.set(skin.getWorldTranslation());
143             tempRot.set(skin.getWorldRotation());
144             tempScale.set(skin.getWorldScale());
145         }
146         
147         if(bone.isHardpoint()) {
148             hardpointBox.getWorldTranslation().set(tempTrans).addLocal(tempRot.mult(bone.getWorldTranslation(), tempA));
149             hardpointBox.getWorldRotation().set(tempRot).multLocal(bone.getWorldRotation());
150             hardpointBox.getWorldScale().set(tempScale).multLocal(bone.getWorldScale());
151             
152             hardpointBox.draw(r);
153         } else {
154             boneSphere.getWorldTranslation().set(tempTrans).addLocal(tempRot.mult(bone.getWorldTranslation(), tempA));
155             boneSphere.getWorldRotation().set(tempRot).multLocal(bone.getWorldRotation());
156             boneSphere.getWorldScale().set(tempScale).multLocal(bone.getWorldScale());
157             
158             boneSphere.draw(r);
159         }
160
161         Vector3f here = tempA;
162         Vector3f there = tempB;
163         Vector3f diff = tempC;
164
165         if (bone.getQuantity() > 0) {
166             bone.localToWorld(Vector3f.ZERO, here);
167             float hX, hY, hZ;
168             hX = here.getX();
169             hY = here.getY();
170             hZ = here.getZ();
171             for (int x = 0, count = bone.getQuantity(); x < count; x++) {
172                 Spatial child = bone.getChild(x);
173                 if (child instanceof Bone) {
174                     child.localToWorld(Vector3f.ZERO, there);
175                     diff.set(there).subtractLocal(here);
176     
177                     float distance = here.distance(there);
178                     
179                     boneCylinder.getWorldScale().set(1, 1, distance);
180                     boneCylinder.getWorldTranslation().set(diff).multLocal(0.5f).addLocal(here);
181                     tempD.set(boneCylinder.getWorldTranslation());
182                     boneCylinder.getWorldTranslation().set(tempTrans).addLocal(tempRot.mult(tempD, tempD));
183     
184                     diff.normalizeLocal();
185                     boneCylinder.getWorldRotation().set(bone.getWorldRotation()).lookAt(diff, Vector3f.UNIT_Z);
186                     tempQ.set(boneCylinder.getWorldRotation());
187                     boneCylinder.getWorldRotation().set(tempRot).multLocal(tempQ);
188     
189     
190                     boneCylinder.draw(r);
191                     drawTheBones(skin, (Bone)child, r);
192                     here.set(hX, hY, hZ);
193                 }
194             }
195         }
196     }
197
198 }