From d55776d081770e81df1d2ad65aca3ab7b902c2c1 Mon Sep 17 00:00:00 2001 From: Stephen Gold Date: Sat, 30 Mar 2019 14:09:52 -0700 Subject: [PATCH] revise TestBoneRagdoll & TestRagdollCharacter to use DynamicAnimControl --- .../java/jme3test/bullet/TestBoneRagdoll.java | 414 +++++++----------- .../jme3test/bullet/TestRagdollCharacter.java | 273 ++++++------ 2 files changed, 301 insertions(+), 386 deletions(-) diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestBoneRagdoll.java b/jme3-examples/src/main/java/jme3test/bullet/TestBoneRagdoll.java index 8b86f1b0c..d3ac39e1d 100644 --- a/jme3-examples/src/main/java/jme3test/bullet/TestBoneRagdoll.java +++ b/jme3-examples/src/main/java/jme3test/bullet/TestBoneRagdoll.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2019 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,43 +31,51 @@ */ package jme3test.bullet; -import com.jme3.animation.*; +import com.jme3.anim.AnimComposer; +import com.jme3.anim.tween.Tweens; +import com.jme3.anim.tween.action.Action; import com.jme3.app.SimpleApplication; import com.jme3.asset.TextureKey; import com.jme3.bullet.BulletAppState; import com.jme3.bullet.PhysicsSpace; -import com.jme3.bullet.collision.*; +import com.jme3.bullet.animation.DynamicAnimControl; +import com.jme3.bullet.animation.PhysicsLink; +import com.jme3.bullet.animation.RagdollCollisionListener; +import com.jme3.bullet.collision.PhysicsCollisionEvent; +import com.jme3.bullet.collision.PhysicsCollisionObject; import com.jme3.bullet.collision.shapes.SphereCollisionShape; -import com.jme3.bullet.control.KinematicRagdollControl; import com.jme3.bullet.control.RigidBodyControl; import com.jme3.font.BitmapText; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; -import com.jme3.input.controls.*; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.KeyTrigger; +import com.jme3.input.controls.MouseButtonTrigger; import com.jme3.light.DirectionalLight; import com.jme3.material.Material; -import com.jme3.math.*; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Quaternion; +import com.jme3.math.Transform; +import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.Node; -import com.jme3.scene.debug.SkeletonDebugger; import com.jme3.scene.shape.Sphere; import com.jme3.scene.shape.Sphere.TextureMode; import com.jme3.texture.Texture; /** - * PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET! * @author normenhansen */ -//TODO rework this Test when the new animation system is done. -public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener { - - private BulletAppState bulletAppState; - Material matBullet; - Node model; - KinematicRagdollControl ragdoll; - float bulletSize = 1f; - Material mat; - Material mat3; +public class TestBoneRagdoll + extends SimpleApplication + implements ActionListener, RagdollCollisionListener { + + private AnimComposer composer; + private DynamicAnimControl ragdoll; + private float bulletSize = 1f; + private Material matBullet; + private Node model; + private PhysicsSpace physicsSpace; private Sphere bullet; private SphereCollisionShape bulletCollisionShape; @@ -76,276 +84,162 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi app.start(); } - public void simpleInitApp() { - initCrossHairs(); - initMaterial(); - - cam.setLocation(new Vector3f(0.26924422f, 6.646658f, 22.265987f)); - cam.setRotation(new Quaternion(-2.302544E-4f, 0.99302495f, -0.117888905f, -0.0019395084f)); + public void onStandDone() { + composer.setCurrentAction("IdleTop"); + } + @Override + public void onAction(String name, boolean isPressed, float tpf) { + if (name.equals("boom") && !isPressed) { + Geometry bulletg = new Geometry("bullet", bullet); + bulletg.setMaterial(matBullet); + bulletg.setLocalTranslation(cam.getLocation()); + bulletg.setLocalScale(bulletSize); + bulletCollisionShape = new SphereCollisionShape(bulletSize); + BombControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1f); + bulletNode.setForceFactor(8f); + bulletNode.setExplosionRadius(20f); + bulletNode.setCcdMotionThreshold(0.001f); + bulletNode.setLinearVelocity(cam.getDirection().mult(180f)); + bulletg.addControl(bulletNode); + rootNode.attachChild(bulletg); + physicsSpace.add(bulletNode); + } + if (name.equals("bullet+") && isPressed) { + bulletSize += 0.1f; + } + if (name.equals("bullet-") && isPressed) { + bulletSize -= 0.1f; + } + if (name.equals("shoot") && !isPressed) { + Geometry bulletg = new Geometry("bullet", bullet); + bulletg.setMaterial(matBullet); + bulletg.setLocalTranslation(cam.getLocation()); + bulletg.setLocalScale(bulletSize); + bulletCollisionShape = new SphereCollisionShape(bulletSize); + RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10f); + bulletNode.setCcdMotionThreshold(0.001f); + bulletNode.setLinearVelocity(cam.getDirection().mult(80f)); + bulletg.addControl(bulletNode); + rootNode.attachChild(bulletg); + physicsSpace.add(bulletNode); + } + if (name.equals("stop") && isPressed) { + ragdoll.setEnabled(!ragdoll.isEnabled()); + ragdoll.setRagdollMode(); + } + if (name.equals("toggle") && isPressed) { + Vector3f v = new Vector3f(model.getLocalTranslation()); + v.y = 0f; + model.setLocalTranslation(v); + Quaternion q = new Quaternion(); + float[] angles = new float[3]; + model.getLocalRotation().toAngles(angles); + q.fromAngleAxis(angles[1], Vector3f.UNIT_Y); + Transform endModelTransform + = new Transform(v, q, new Vector3f(1f, 1f, 1f)); + if (angles[0] < 0f) { + composer.setCurrentAction("BackOnce"); + ragdoll.blendToKinematicMode(0.5f, endModelTransform); + } else { + composer.setCurrentAction("FrontOnce"); + ragdoll.blendToKinematicMode(0.5f, endModelTransform); + } + } + } - bulletAppState = new BulletAppState(); - bulletAppState.setEnabled(true); - stateManager.attach(bulletAppState); - bullet = new Sphere(32, 32, 1.0f, true, false); - bullet.setTextureMode(TextureMode.Projected); - bulletCollisionShape = new SphereCollisionShape(1.0f); + @Override + public void simpleInitApp() { + flyCam.setMoveSpeed(50f); + cam.setLocation(new Vector3f(0.3f, 6.7f, 22.3f)); + cam.setRotation(new Quaternion(-2E-4f, 0.993025f, -0.1179f, -0.0019f)); -// bulletAppState.getPhysicsSpace().enableDebug(assetManager); - PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace()); + initCrossHairs(); + initMaterial(); + setupKeys(); setupLight(); - model = (Node) assetManager.loadModel("Models/Sinbad/SinbadOldAnim.j3o"); - - // model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X)); - - //debug view - AnimControl control = model.getControl(AnimControl.class); - SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton()); - Material mat2 = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); - mat2.getAdditionalRenderState().setWireframe(true); - mat2.setColor("Color", ColorRGBA.Green); - mat2.getAdditionalRenderState().setDepthTest(false); - skeletonDebug.setMaterial(mat2); - skeletonDebug.setLocalTranslation(model.getLocalTranslation()); - - //Note: PhysicsRagdollControl is still TODO, constructor will change - ragdoll = new KinematicRagdollControl(0.5f); - setupSinbad(ragdoll); - ragdoll.addCollisionListener(this); - model.addControl(ragdoll); - - float eighth_pi = FastMath.PI * 0.125f; - ragdoll.setJointLimit("Waist", eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi); - ragdoll.setJointLimit("Chest", eighth_pi, eighth_pi, 0, 0, eighth_pi, eighth_pi); - + BulletAppState bulletAppState = new BulletAppState(); + stateManager.attach(bulletAppState); + //bulletAppState.setDebugEnabled(true); + physicsSpace = bulletAppState.getPhysicsSpace(); - //Oto's head is almost rigid - // ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0); + bullet = new Sphere(32, 32, 1f, true, false); + bullet.setTextureMode(TextureMode.Projected); + bulletCollisionShape = new SphereCollisionShape(1f); - getPhysicsSpace().add(ragdoll); - speed = 1.3f; + PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, + physicsSpace); + model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml"); rootNode.attachChild(model); - // rootNode.attachChild(skeletonDebug); - flyCam.setMoveSpeed(50); - - - animChannel = control.createChannel(); - animChannel.setAnim("Dance"); - control.addListener(this); - - inputManager.addListener(new ActionListener() { - - public void onAction(String name, boolean isPressed, float tpf) { - if (name.equals("toggle") && isPressed) { - - Vector3f v = new Vector3f(); - v.set(model.getLocalTranslation()); - v.y = 0; - model.setLocalTranslation(v); - Quaternion q = new Quaternion(); - float[] angles = new float[3]; - model.getLocalRotation().toAngles(angles); - q.fromAngleAxis(angles[1], Vector3f.UNIT_Y); - model.setLocalRotation(q); - if (angles[0] < 0) { - animChannel.setAnim("StandUpBack"); - ragdoll.blendToKinematicMode(0.5f); - } else { - animChannel.setAnim("StandUpFront"); - ragdoll.blendToKinematicMode(0.5f); - } - } - if (name.equals("bullet+") && isPressed) { - bulletSize += 0.1f; - - } - if (name.equals("bullet-") && isPressed) { - bulletSize -= 0.1f; - - } - - if (name.equals("stop") && isPressed) { - ragdoll.setEnabled(!ragdoll.isEnabled()); - ragdoll.setRagdollMode(); - } - - if (name.equals("shoot") && !isPressed) { - Geometry bulletg = new Geometry("bullet", bullet); - bulletg.setMaterial(matBullet); - bulletg.setLocalTranslation(cam.getLocation()); - bulletg.setLocalScale(bulletSize); - bulletCollisionShape = new SphereCollisionShape(bulletSize); - RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10); - bulletNode.setCcdMotionThreshold(0.001f); - bulletNode.setLinearVelocity(cam.getDirection().mult(80)); - bulletg.addControl(bulletNode); - rootNode.attachChild(bulletg); - getPhysicsSpace().add(bulletNode); - } - if (name.equals("boom") && !isPressed) { - Geometry bulletg = new Geometry("bullet", bullet); - bulletg.setMaterial(matBullet); - bulletg.setLocalTranslation(cam.getLocation()); - bulletg.setLocalScale(bulletSize); - bulletCollisionShape = new SphereCollisionShape(bulletSize); - BombControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1); - bulletNode.setForceFactor(8); - bulletNode.setExplosionRadius(20); - bulletNode.setCcdMotionThreshold(0.001f); - bulletNode.setLinearVelocity(cam.getDirection().mult(180)); - bulletg.addControl(bulletNode); - rootNode.attachChild(bulletg); - getPhysicsSpace().add(bulletNode); - } - } - }, "toggle", "shoot", "stop", "bullet+", "bullet-", "boom"); - inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE)); - inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); - inputManager.addMapping("boom", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT)); - inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_H)); - inputManager.addMapping("bullet-", new KeyTrigger(KeyInput.KEY_COMMA)); - inputManager.addMapping("bullet+", new KeyTrigger(KeyInput.KEY_PERIOD)); + composer = model.getControl(AnimComposer.class); + composer.setCurrentAction("Dance"); + Action standUpFront = composer.action("StandUpFront"); + composer.actionSequence("FrontOnce", + standUpFront, Tweens.callMethod(this, "onStandDone")); + Action standUpBack = composer.action("StandUpBack"); + composer.actionSequence("BackOnce", + standUpBack, Tweens.callMethod(this, "onStandDone")); + ragdoll = new DynamicAnimControl(); + TestRagdollCharacter.setupSinbad(ragdoll); + model.addControl(ragdoll); + physicsSpace.add(ragdoll); + ragdoll.addCollisionListener(this); } - private void setupLight() { - // AmbientLight al = new AmbientLight(); - // al.setColor(ColorRGBA.White.mult(1)); - // rootNode.addLight(al); - - DirectionalLight dl = new DirectionalLight(); - dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); - dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f)); - rootNode.addLight(dl); - } - - private PhysicsSpace getPhysicsSpace() { - return bulletAppState.getPhysicsSpace(); - } - - public void initMaterial() { - - matBullet = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); - TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG"); - key2.setGenerateMips(true); - Texture tex2 = assetManager.loadTexture(key2); - matBullet.setTexture("ColorMap", tex2); + @Override + public void collide(PhysicsLink bone, PhysicsCollisionObject object, + PhysicsCollisionEvent event) { + if (object.getUserObject() != null + && object.getUserObject() instanceof Geometry) { + Geometry geom = (Geometry) object.getUserObject(); + if ("bullet".equals(geom.getName())) { + ragdoll.setRagdollMode(); + } + } } - protected void initCrossHairs() { + private void initCrossHairs() { guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); BitmapText ch = new BitmapText(guiFont, false); - ch.setSize(guiFont.getCharSet().getRenderedSize() * 2); + ch.setSize(guiFont.getCharSet().getRenderedSize() * 2f); ch.setText("+"); // crosshairs ch.setLocalTranslation( // center - settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2, - settings.getHeight() / 2 + ch.getLineHeight() / 2, 0); + settings.getWidth() / 2f - guiFont.getCharSet().getRenderedSize() / 3f * 2f, + settings.getHeight() / 2f + ch.getLineHeight() / 2f, 0f); guiNode.attachChild(ch); } - public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event) { - - if (object.getUserObject() != null && object.getUserObject() instanceof Geometry) { - Geometry geom = (Geometry) object.getUserObject(); - if ("Floor".equals(geom.getName())) { - return; - } - } - - ragdoll.setRagdollMode(); - - } - - private void setupSinbad(KinematicRagdollControl ragdoll) { - ragdoll.addBoneName("Ulna.L"); - ragdoll.addBoneName("Ulna.R"); - ragdoll.addBoneName("Chest"); - ragdoll.addBoneName("Foot.L"); - ragdoll.addBoneName("Foot.R"); - ragdoll.addBoneName("Hand.R"); - ragdoll.addBoneName("Hand.L"); - ragdoll.addBoneName("Neck"); - ragdoll.addBoneName("Root"); - ragdoll.addBoneName("Stomach"); - ragdoll.addBoneName("Waist"); - ragdoll.addBoneName("Humerus.L"); - ragdoll.addBoneName("Humerus.R"); - ragdoll.addBoneName("Thigh.L"); - ragdoll.addBoneName("Thigh.R"); - ragdoll.addBoneName("Calf.L"); - ragdoll.addBoneName("Calf.R"); - ragdoll.addBoneName("Clavicle.L"); - ragdoll.addBoneName("Clavicle.R"); - - } - float elTime = 0; - boolean forward = true; - AnimControl animControl; - AnimChannel animChannel; - Vector3f direction = new Vector3f(0, 0, 1); - Quaternion rotate = new Quaternion().fromAngleAxis(FastMath.PI / 8, Vector3f.UNIT_Y); - boolean dance = true; - - @Override - public void simpleUpdate(float tpf) { - // System.out.println(((BoundingBox) model.getWorldBound()).getYExtent()); -// elTime += tpf; -// if (elTime > 3) { -// elTime = 0; -// if (dance) { -// rotate.multLocal(direction); -// } -// if (Math.random() > 0.80) { -// dance = true; -// animChannel.setAnim("Dance"); -// } else { -// dance = false; -// animChannel.setAnim("RunBase"); -// rotate.fromAngleAxis(FastMath.QUARTER_PI * ((float) Math.random() - 0.5f), Vector3f.UNIT_Y); -// rotate.multLocal(direction); -// } -// } -// if (!ragdoll.hasControl() && !dance) { -// if (model.getLocalTranslation().getZ() < -10) { -// direction.z = 1; -// direction.normalizeLocal(); -// } else if (model.getLocalTranslation().getZ() > 10) { -// direction.z = -1; -// direction.normalizeLocal(); -// } -// if (model.getLocalTranslation().getX() < -10) { -// direction.x = 1; -// direction.normalizeLocal(); -// } else if (model.getLocalTranslation().getX() > 10) { -// direction.x = -1; -// direction.normalizeLocal(); -// } -// model.move(direction.multLocal(tpf * 8)); -// direction.normalizeLocal(); -// model.lookAt(model.getLocalTranslation().add(direction), Vector3f.UNIT_Y); -// } + private void initMaterial() { + matBullet = new Material(assetManager, + "Common/MatDefs/Misc/Unshaded.j3md"); + TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG"); + key2.setGenerateMips(true); + Texture tex2 = assetManager.loadTexture(key2); + matBullet.setTexture("ColorMap", tex2); } - public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) { -// if(channel.getAnimationName().equals("StandUpFront")){ -// channel.setAnim("Dance"); -// } + private void setupKeys() { + inputManager.addMapping("boom", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT)); + inputManager.addMapping("bullet+", new KeyTrigger(KeyInput.KEY_PERIOD)); + inputManager.addMapping("bullet-", new KeyTrigger(KeyInput.KEY_COMMA)); + inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); + inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_H)); + inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE)); - if (channel.getAnimationName().equals("StandUpBack") || channel.getAnimationName().equals("StandUpFront")) { - channel.setLoopMode(LoopMode.DontLoop); - channel.setAnim("IdleTop", 5); - channel.setLoopMode(LoopMode.Loop); - } -// if(channel.getAnimationName().equals("IdleTop")){ -// channel.setAnim("StandUpFront"); -// } + inputManager.addListener(this, + "boom", "bullet-", "bullet+", "shoot", "stop", "toggle"); } - public void onAnimChange(AnimControl control, AnimChannel channel, String animName) { + private void setupLight() { + DirectionalLight dl = new DirectionalLight(); + dl.setDirection(new Vector3f(-0.1f, -0.7f, -1f).normalizeLocal()); + dl.setColor(new ColorRGBA(1f, 1f, 1f, 1f)); + rootNode.addLight(dl); } } diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestRagdollCharacter.java b/jme3-examples/src/main/java/jme3test/bullet/TestRagdollCharacter.java index f94307d6e..e84d3b9a3 100644 --- a/jme3-examples/src/main/java/jme3test/bullet/TestRagdollCharacter.java +++ b/jme3-examples/src/main/java/jme3test/bullet/TestRagdollCharacter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 jMonkeyEngine + * Copyright (c) 2009-2019 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,19 +31,25 @@ */ package jme3test.bullet; -import com.jme3.animation.*; +import com.jme3.anim.AnimComposer; +import com.jme3.anim.tween.Tweens; +import com.jme3.anim.tween.action.Action; import com.jme3.app.SimpleApplication; import com.jme3.asset.TextureKey; import com.jme3.bullet.BulletAppState; import com.jme3.bullet.PhysicsSpace; -import com.jme3.bullet.control.KinematicRagdollControl; +import com.jme3.bullet.animation.DynamicAnimControl; +import com.jme3.bullet.animation.RangeOfMotion; import com.jme3.bullet.control.RigidBodyControl; import com.jme3.input.KeyInput; import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.KeyTrigger; import com.jme3.light.DirectionalLight; import com.jme3.material.Material; -import com.jme3.math.*; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.scene.Geometry; import com.jme3.scene.Node; @@ -53,101 +59,153 @@ import com.jme3.texture.Texture; /** * @author normenhansen */ -//TODO rework this Test when the new animation system is done. -public class TestRagdollCharacter extends SimpleApplication implements AnimEventListener, ActionListener { +public class TestRagdollCharacter + extends SimpleApplication + implements ActionListener { - BulletAppState bulletAppState; - Node model; - KinematicRagdollControl ragdoll; - boolean leftStrafe = false, rightStrafe = false, forward = false, backward = false, + private AnimComposer composer; + private boolean forward = false, backward = false, leftRotate = false, rightRotate = false; - AnimControl animControl; - AnimChannel animChannel; + private DynamicAnimControl ragdoll; + private Node model; + private PhysicsSpace physicsSpace; public static void main(String[] args) { TestRagdollCharacter app = new TestRagdollCharacter(); app.start(); } - public void simpleInitApp() { - setupKeys(); - - bulletAppState = new BulletAppState(); - bulletAppState.setEnabled(true); - stateManager.attach(bulletAppState); + public void onSliceDone() { + composer.setCurrentAction("IdleTop"); + } + static void setupSinbad(DynamicAnimControl ragdoll) { + ragdoll.link("Waist", 1f, + new RangeOfMotion(1f, -0.4f, 0.8f, -0.8f, 0.4f, -0.4f)); + ragdoll.link("Chest", 1f, new RangeOfMotion(0.4f, 0f, 0.4f)); + ragdoll.link("Neck", 1f, new RangeOfMotion(0.5f, 1f, 0.7f)); + + ragdoll.link("Clavicle.R", 1f, + new RangeOfMotion(0.3f, -0.6f, 0f, 0f, 0.4f, -0.4f)); + ragdoll.link("Humerus.R", 1f, + new RangeOfMotion(1.6f, -0.8f, 1f, -1f, 1.6f, -1f)); + ragdoll.link("Ulna.R", 1f, new RangeOfMotion(0f, 0f, 1f, -1f, 0f, -2f)); + ragdoll.link("Hand.R", 1f, new RangeOfMotion(0.8f, 0f, 0.2f)); + + ragdoll.link("Clavicle.L", 1f, + new RangeOfMotion(0.6f, -0.3f, 0f, 0f, 0.4f, -0.4f)); + ragdoll.link("Humerus.L", + 1f, new RangeOfMotion(0.8f, -1.6f, 1f, -1f, 1f, -1.6f)); + ragdoll.link("Ulna.L", 1f, new RangeOfMotion(0f, 0f, 1f, -1f, 2f, 0f)); + ragdoll.link("Hand.L", 1f, new RangeOfMotion(0.8f, 0f, 0.2f)); + + ragdoll.link("Thigh.R", 1f, + new RangeOfMotion(0.4f, -1f, 0.4f, -0.4f, 1f, -0.5f)); + ragdoll.link("Calf.R", 1f, new RangeOfMotion(2f, 0f, 0f, 0f, 0f, 0f)); + ragdoll.link("Foot.R", 1f, new RangeOfMotion(0.3f, 0.5f, 0f)); + + ragdoll.link("Thigh.L", 1f, + new RangeOfMotion(0.4f, -1f, 0.4f, -0.4f, 0.5f, -1f)); + ragdoll.link("Calf.L", 1f, new RangeOfMotion(2f, 0f, 0f, 0f, 0f, 0f)); + ragdoll.link("Foot.L", 1f, new RangeOfMotion(0.3f, 0.5f, 0f)); + } -// bulletAppState.getPhysicsSpace().enableDebug(assetManager); - PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace()); - initWall(2,1,1); - setupLight(); + @Override + public void onAction(String binding, boolean isPressed, float tpf) { + if (binding.equals("Rotate Left")) { + if (isPressed) { + leftRotate = true; + } else { + leftRotate = false; + } + } else if (binding.equals("Rotate Right")) { + if (isPressed) { + rightRotate = true; + } else { + rightRotate = false; + } + } else if (binding.equals("Slice")) { + if (isPressed) { + composer.setCurrentAction("SliceOnce"); + } + } else if (binding.equals("Walk Forward")) { + if (isPressed) { + forward = true; + } else { + forward = false; + } + } else if (binding.equals("Walk Backward")) { + if (isPressed) { + backward = true; + } else { + backward = false; + } + } + } - cam.setLocation(new Vector3f(-8,0,-4)); - cam.lookAt(new Vector3f(4,0,-7), Vector3f.UNIT_Y); + @Override + public void simpleInitApp() { + flyCam.setMoveSpeed(50f); + cam.setLocation(new Vector3f(-16f, 4.7f, -1.6f)); + cam.setRotation(new Quaternion(0.0484f, 0.804337f, -0.066f, 0.5885f)); - model = (Node) assetManager.loadModel("Models/Sinbad/SinbadOldAnim.j3o"); - model.lookAt(new Vector3f(0,0,-1), Vector3f.UNIT_Y); - model.setLocalTranslation(4, 0, -7f); + setupKeys(); + setupLight(); - ragdoll = new KinematicRagdollControl(0.5f); - model.addControl(ragdoll); + BulletAppState bulletAppState = new BulletAppState(); + stateManager.attach(bulletAppState); + //bulletAppState.setDebugEnabled(true); + physicsSpace = bulletAppState.getPhysicsSpace(); - getPhysicsSpace().add(ragdoll); - speed = 1.3f; + PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, + physicsSpace); + initWall(2f, 1f, 1f); + model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml"); rootNode.attachChild(model); + model.lookAt(new Vector3f(0f, 0f, -1f), Vector3f.UNIT_Y); + model.setLocalTranslation(4f, 0f, -7f); + composer = model.getControl(AnimComposer.class); + composer.setCurrentAction("IdleTop"); - AnimControl control = model.getControl(AnimControl.class); - animChannel = control.createChannel(); - animChannel.setAnim("IdleTop"); - control.addListener(this); + Action slice = composer.action("SliceHorizontal"); + composer.actionSequence("SliceOnce", + slice, Tweens.callMethod(this, "onSliceDone")); + ragdoll = new DynamicAnimControl(); + setupSinbad(ragdoll); + model.addControl(ragdoll); + physicsSpace.add(ragdoll); } - private void setupLight() { - DirectionalLight dl = new DirectionalLight(); - dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); - dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f)); - rootNode.addLight(dl); - } - - private PhysicsSpace getPhysicsSpace() { - return bulletAppState.getPhysicsSpace(); - } - - private void setupKeys() { - inputManager.addMapping("Rotate Left", - new KeyTrigger(KeyInput.KEY_H)); - inputManager.addMapping("Rotate Right", - new KeyTrigger(KeyInput.KEY_K)); - inputManager.addMapping("Walk Forward", - new KeyTrigger(KeyInput.KEY_U)); - inputManager.addMapping("Walk Backward", - new KeyTrigger(KeyInput.KEY_J)); - inputManager.addMapping("Slice", - new KeyTrigger(KeyInput.KEY_SPACE), - new KeyTrigger(KeyInput.KEY_RETURN)); - inputManager.addListener(this, "Strafe Left", "Strafe Right"); - inputManager.addListener(this, "Rotate Left", "Rotate Right"); - inputManager.addListener(this, "Walk Forward", "Walk Backward"); - inputManager.addListener(this, "Slice"); + @Override + public void simpleUpdate(float tpf) { + if (forward) { + model.move(model.getLocalRotation().multLocal(new Vector3f(0f, 0f, tpf))); + } else if (backward) { + model.move(model.getLocalRotation().multLocal(new Vector3f(0f, 0f, -tpf))); + } else if (leftRotate) { + model.rotate(0f, tpf, 0f); + } else if (rightRotate) { + model.rotate(0f, -tpf, 0f); + } } - public void initWall(float bLength, float bWidth, float bHeight) { + private void initWall(float bLength, float bWidth, float bHeight) { Box brick = new Box(bLength, bHeight, bWidth); - brick.scaleTextureCoordinates(new Vector2f(1f, .5f)); + brick.scaleTextureCoordinates(new Vector2f(1f, 0.5f)); Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg"); key.setGenerateMips(true); Texture tex = assetManager.loadTexture(key); mat2.setTexture("ColorMap", tex); - - float startpt = bLength / 4; - float height = -5; + + float startpt = bLength / 4f; + float height = -5f; for (int j = 0; j < 15; j++) { for (int i = 0; i < 4; i++) { - Vector3f ori = new Vector3f(i * bLength * 2 + startpt, bHeight + height, -10); + Vector3f ori = new Vector3f(i * bLength * 2f + startpt, bHeight + height, -10f); Geometry reBoxg = new Geometry("brick", brick); reBoxg.setMaterial(mat2); reBoxg.setLocalTranslation(ori); @@ -156,71 +214,34 @@ public class TestRagdollCharacter extends SimpleApplication implements AnimEvent reBoxg.setShadowMode(ShadowMode.CastAndReceive); reBoxg.getControl(RigidBodyControl.class).setFriction(0.6f); this.rootNode.attachChild(reBoxg); - this.getPhysicsSpace().add(reBoxg); + physicsSpace.add(reBoxg); } startpt = -startpt; - height += 2 * bHeight; + height += 2f * bHeight; } } - public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) { - - if (channel.getAnimationName().equals("SliceHorizontal")) { - channel.setLoopMode(LoopMode.DontLoop); - channel.setAnim("IdleTop", 5); - channel.setLoopMode(LoopMode.Loop); - } - - } + private void setupKeys() { + inputManager.addMapping("Rotate Left", + new KeyTrigger(KeyInput.KEY_H)); + inputManager.addMapping("Rotate Right", + new KeyTrigger(KeyInput.KEY_K)); + inputManager.addMapping("Walk Backward", + new KeyTrigger(KeyInput.KEY_J)); + inputManager.addMapping("Walk Forward", + new KeyTrigger(KeyInput.KEY_U)); + inputManager.addMapping("Slice", + new KeyTrigger(KeyInput.KEY_SPACE), + new KeyTrigger(KeyInput.KEY_RETURN)); - public void onAnimChange(AnimControl control, AnimChannel channel, String animName) { - } - - public void onAction(String binding, boolean value, float tpf) { - if (binding.equals("Rotate Left")) { - if (value) { - leftRotate = true; - } else { - leftRotate = false; - } - } else if (binding.equals("Rotate Right")) { - if (value) { - rightRotate = true; - } else { - rightRotate = false; - } - } else if (binding.equals("Walk Forward")) { - if (value) { - forward = true; - } else { - forward = false; - } - } else if (binding.equals("Walk Backward")) { - if (value) { - backward = true; - } else { - backward = false; - } - } else if (binding.equals("Slice")) { - if (value) { - animChannel.setAnim("SliceHorizontal"); - animChannel.setSpeed(0.3f); - } - } + inputManager.addListener(this, "Rotate Left", "Rotate Right", "Slice", + "Walk Backward", "Walk Forward"); } - @Override - public void simpleUpdate(float tpf) { - if(forward){ - model.move(model.getLocalRotation().multLocal(new Vector3f(0,0,1)).multLocal(tpf)); - }else if(backward){ - model.move(model.getLocalRotation().multLocal(new Vector3f(0,0,1)).multLocal(-tpf)); - }else if(leftRotate){ - model.rotate(0, tpf, 0); - }else if(rightRotate){ - model.rotate(0, -tpf, 0); - } - fpsText.setText(cam.getLocation() + "/" + cam.getRotation()); + private void setupLight() { + DirectionalLight dl = new DirectionalLight(); + dl.setDirection(new Vector3f(-0.1f, -0.7f, -1f).normalizeLocal()); + dl.setColor(new ColorRGBA(1f, 1f, 1f, 1f)); + rootNode.addLight(dl); } - }