• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 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 jme3test.bullet;
33 
34 import com.jme3.animation.*;
35 import com.jme3.app.SimpleApplication;
36 import com.jme3.asset.TextureKey;
37 import com.jme3.bullet.BulletAppState;
38 import com.jme3.bullet.PhysicsSpace;
39 import com.jme3.bullet.collision.PhysicsCollisionEvent;
40 import com.jme3.bullet.collision.PhysicsCollisionObject;
41 import com.jme3.bullet.collision.RagdollCollisionListener;
42 import com.jme3.bullet.collision.shapes.SphereCollisionShape;
43 import com.jme3.bullet.control.KinematicRagdollControl;
44 import com.jme3.bullet.control.RigidBodyControl;
45 import com.jme3.font.BitmapText;
46 import com.jme3.input.KeyInput;
47 import com.jme3.input.MouseInput;
48 import com.jme3.input.controls.ActionListener;
49 import com.jme3.input.controls.KeyTrigger;
50 import com.jme3.input.controls.MouseButtonTrigger;
51 import com.jme3.light.DirectionalLight;
52 import com.jme3.material.Material;
53 import com.jme3.math.ColorRGBA;
54 import com.jme3.math.FastMath;
55 import com.jme3.math.Quaternion;
56 import com.jme3.math.Vector3f;
57 import com.jme3.scene.Geometry;
58 import com.jme3.scene.Node;
59 import com.jme3.scene.debug.SkeletonDebugger;
60 import com.jme3.scene.shape.Sphere;
61 import com.jme3.scene.shape.Sphere.TextureMode;
62 import com.jme3.texture.Texture;
63 
64 /**
65  * PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET!
66  * @author normenhansen
67  */
68 public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener {
69 
70     private BulletAppState bulletAppState;
71     Material matBullet;
72     Node model;
73     KinematicRagdollControl ragdoll;
74     float bulletSize = 1f;
75     Material mat;
76     Material mat3;
77     private Sphere bullet;
78     private SphereCollisionShape bulletCollisionShape;
79 
main(String[] args)80     public static void main(String[] args) {
81         TestBoneRagdoll app = new TestBoneRagdoll();
82         app.start();
83     }
84 
simpleInitApp()85     public void simpleInitApp() {
86         initCrossHairs();
87         initMaterial();
88 
89         cam.setLocation(new Vector3f(0.26924422f, 6.646658f, 22.265987f));
90         cam.setRotation(new Quaternion(-2.302544E-4f, 0.99302495f, -0.117888905f, -0.0019395084f));
91 
92 
93         bulletAppState = new BulletAppState();
94         bulletAppState.setEnabled(true);
95         stateManager.attach(bulletAppState);
96         bullet = new Sphere(32, 32, 1.0f, true, false);
97         bullet.setTextureMode(TextureMode.Projected);
98         bulletCollisionShape = new SphereCollisionShape(1.0f);
99 
100 //        bulletAppState.getPhysicsSpace().enableDebug(assetManager);
101         PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
102         setupLight();
103 
104         model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
105 
106         //  model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X));
107 
108         //debug view
109         AnimControl control = model.getControl(AnimControl.class);
110         SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
111         Material mat2 = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
112         mat2.getAdditionalRenderState().setWireframe(true);
113         mat2.setColor("Color", ColorRGBA.Green);
114         mat2.getAdditionalRenderState().setDepthTest(false);
115         skeletonDebug.setMaterial(mat2);
116         skeletonDebug.setLocalTranslation(model.getLocalTranslation());
117 
118         //Note: PhysicsRagdollControl is still TODO, constructor will change
119         ragdoll = new KinematicRagdollControl(0.5f);
120         setupSinbad(ragdoll);
121         ragdoll.addCollisionListener(this);
122         model.addControl(ragdoll);
123 
124         float eighth_pi = FastMath.PI * 0.125f;
125         ragdoll.setJointLimit("Waist", eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi);
126         ragdoll.setJointLimit("Chest", eighth_pi, eighth_pi, 0, 0, eighth_pi, eighth_pi);
127 
128 
129         //Oto's head is almost rigid
130         //    ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0);
131 
132         getPhysicsSpace().add(ragdoll);
133         speed = 1.3f;
134 
135         rootNode.attachChild(model);
136         // rootNode.attachChild(skeletonDebug);
137         flyCam.setMoveSpeed(50);
138 
139 
140         animChannel = control.createChannel();
141         animChannel.setAnim("Dance");
142         control.addListener(this);
143 
144         inputManager.addListener(new ActionListener() {
145 
146             public void onAction(String name, boolean isPressed, float tpf) {
147                 if (name.equals("toggle") && isPressed) {
148 
149                     Vector3f v = new Vector3f();
150                     v.set(model.getLocalTranslation());
151                     v.y = 0;
152                     model.setLocalTranslation(v);
153                     Quaternion q = new Quaternion();
154                     float[] angles = new float[3];
155                     model.getLocalRotation().toAngles(angles);
156                     q.fromAngleAxis(angles[1], Vector3f.UNIT_Y);
157                     model.setLocalRotation(q);
158                     if (angles[0] < 0) {
159                         animChannel.setAnim("StandUpBack");
160                         ragdoll.blendToKinematicMode(0.5f);
161                     } else {
162                         animChannel.setAnim("StandUpFront");
163                         ragdoll.blendToKinematicMode(0.5f);
164                     }
165 
166                 }
167                 if (name.equals("bullet+") && isPressed) {
168                     bulletSize += 0.1f;
169 
170                 }
171                 if (name.equals("bullet-") && isPressed) {
172                     bulletSize -= 0.1f;
173 
174                 }
175 
176                 if (name.equals("stop") && isPressed) {
177                     ragdoll.setEnabled(!ragdoll.isEnabled());
178                     ragdoll.setRagdollMode();
179                 }
180 
181                 if (name.equals("shoot") && !isPressed) {
182                     Geometry bulletg = new Geometry("bullet", bullet);
183                     bulletg.setMaterial(matBullet);
184                     bulletg.setLocalTranslation(cam.getLocation());
185                     bulletg.setLocalScale(bulletSize);
186                     bulletCollisionShape = new SphereCollisionShape(bulletSize);
187                     RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10);
188                     bulletNode.setCcdMotionThreshold(0.001f);
189                     bulletNode.setLinearVelocity(cam.getDirection().mult(80));
190                     bulletg.addControl(bulletNode);
191                     rootNode.attachChild(bulletg);
192                     getPhysicsSpace().add(bulletNode);
193                 }
194                 if (name.equals("boom") && !isPressed) {
195                     Geometry bulletg = new Geometry("bullet", bullet);
196                     bulletg.setMaterial(matBullet);
197                     bulletg.setLocalTranslation(cam.getLocation());
198                     bulletg.setLocalScale(bulletSize);
199                     bulletCollisionShape = new SphereCollisionShape(bulletSize);
200                     BombControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1);
201                     bulletNode.setForceFactor(8);
202                     bulletNode.setExplosionRadius(20);
203                     bulletNode.setCcdMotionThreshold(0.001f);
204                     bulletNode.setLinearVelocity(cam.getDirection().mult(180));
205                     bulletg.addControl(bulletNode);
206                     rootNode.attachChild(bulletg);
207                     getPhysicsSpace().add(bulletNode);
208                 }
209             }
210         }, "toggle", "shoot", "stop", "bullet+", "bullet-", "boom");
211         inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
212         inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
213         inputManager.addMapping("boom", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
214         inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_H));
215         inputManager.addMapping("bullet-", new KeyTrigger(KeyInput.KEY_COMMA));
216         inputManager.addMapping("bullet+", new KeyTrigger(KeyInput.KEY_PERIOD));
217 
218 
219     }
220 
setupLight()221     private void setupLight() {
222         // AmbientLight al = new AmbientLight();
223         //  al.setColor(ColorRGBA.White.mult(1));
224         //   rootNode.addLight(al);
225 
226         DirectionalLight dl = new DirectionalLight();
227         dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
228         dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
229         rootNode.addLight(dl);
230     }
231 
getPhysicsSpace()232     private PhysicsSpace getPhysicsSpace() {
233         return bulletAppState.getPhysicsSpace();
234     }
235 
initMaterial()236     public void initMaterial() {
237 
238         matBullet = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
239         TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
240         key2.setGenerateMips(true);
241         Texture tex2 = assetManager.loadTexture(key2);
242         matBullet.setTexture("ColorMap", tex2);
243     }
244 
initCrossHairs()245     protected void initCrossHairs() {
246         guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
247         BitmapText ch = new BitmapText(guiFont, false);
248         ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
249         ch.setText("+"); // crosshairs
250         ch.setLocalTranslation( // center
251                 settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
252                 settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
253         guiNode.attachChild(ch);
254     }
255 
collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event)256     public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event) {
257 
258         if (object.getUserObject() != null && object.getUserObject() instanceof Geometry) {
259             Geometry geom = (Geometry) object.getUserObject();
260             if ("Floor".equals(geom.getName())) {
261                 return;
262             }
263         }
264 
265         ragdoll.setRagdollMode();
266 
267     }
268 
setupSinbad(KinematicRagdollControl ragdoll)269     private void setupSinbad(KinematicRagdollControl ragdoll) {
270         ragdoll.addBoneName("Ulna.L");
271         ragdoll.addBoneName("Ulna.R");
272         ragdoll.addBoneName("Chest");
273         ragdoll.addBoneName("Foot.L");
274         ragdoll.addBoneName("Foot.R");
275         ragdoll.addBoneName("Hand.R");
276         ragdoll.addBoneName("Hand.L");
277         ragdoll.addBoneName("Neck");
278         ragdoll.addBoneName("Root");
279         ragdoll.addBoneName("Stomach");
280         ragdoll.addBoneName("Waist");
281         ragdoll.addBoneName("Humerus.L");
282         ragdoll.addBoneName("Humerus.R");
283         ragdoll.addBoneName("Thigh.L");
284         ragdoll.addBoneName("Thigh.R");
285         ragdoll.addBoneName("Calf.L");
286         ragdoll.addBoneName("Calf.R");
287         ragdoll.addBoneName("Clavicle.L");
288         ragdoll.addBoneName("Clavicle.R");
289 
290     }
291     float elTime = 0;
292     boolean forward = true;
293     AnimControl animControl;
294     AnimChannel animChannel;
295     Vector3f direction = new Vector3f(0, 0, 1);
296     Quaternion rotate = new Quaternion().fromAngleAxis(FastMath.PI / 8, Vector3f.UNIT_Y);
297     boolean dance = true;
298 
299     @Override
simpleUpdate(float tpf)300     public void simpleUpdate(float tpf) {
301         // System.out.println(((BoundingBox) model.getWorldBound()).getYExtent());
302 //        elTime += tpf;
303 //        if (elTime > 3) {
304 //            elTime = 0;
305 //            if (dance) {
306 //                rotate.multLocal(direction);
307 //            }
308 //            if (Math.random() > 0.80) {
309 //                dance = true;
310 //                animChannel.setAnim("Dance");
311 //            } else {
312 //                dance = false;
313 //                animChannel.setAnim("RunBase");
314 //                rotate.fromAngleAxis(FastMath.QUARTER_PI * ((float) Math.random() - 0.5f), Vector3f.UNIT_Y);
315 //                rotate.multLocal(direction);
316 //            }
317 //        }
318 //        if (!ragdoll.hasControl() && !dance) {
319 //            if (model.getLocalTranslation().getZ() < -10) {
320 //                direction.z = 1;
321 //                direction.normalizeLocal();
322 //            } else if (model.getLocalTranslation().getZ() > 10) {
323 //                direction.z = -1;
324 //                direction.normalizeLocal();
325 //            }
326 //            if (model.getLocalTranslation().getX() < -10) {
327 //                direction.x = 1;
328 //                direction.normalizeLocal();
329 //            } else if (model.getLocalTranslation().getX() > 10) {
330 //                direction.x = -1;
331 //                direction.normalizeLocal();
332 //            }
333 //            model.move(direction.multLocal(tpf * 8));
334 //            direction.normalizeLocal();
335 //            model.lookAt(model.getLocalTranslation().add(direction), Vector3f.UNIT_Y);
336 //        }
337     }
338 
onAnimCycleDone(AnimControl control, AnimChannel channel, String animName)339     public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
340 //        if(channel.getAnimationName().equals("StandUpFront")){
341 //            channel.setAnim("Dance");
342 //        }
343 
344         if (channel.getAnimationName().equals("StandUpBack") || channel.getAnimationName().equals("StandUpFront")) {
345             channel.setLoopMode(LoopMode.DontLoop);
346             channel.setAnim("IdleTop", 5);
347             channel.setLoopMode(LoopMode.Loop);
348         }
349 //        if(channel.getAnimationName().equals("IdleTop")){
350 //            channel.setAnim("StandUpFront");
351 //        }
352 
353     }
354 
onAnimChange(AnimControl control, AnimChannel channel, String animName)355     public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
356     }
357 }
358