diff --git a/engine/src/jbullet/com/jme3/bullet/collision/RagdollCollisionListener.java b/engine/src/jbullet/com/jme3/bullet/collision/RagdollCollisionListener.java index a19cc2f8f..44805a428 100644 --- a/engine/src/jbullet/com/jme3/bullet/collision/RagdollCollisionListener.java +++ b/engine/src/jbullet/com/jme3/bullet/collision/RagdollCollisionListener.java @@ -12,6 +12,6 @@ import com.jme3.animation.Bone; */ public interface RagdollCollisionListener { - public void collide(Bone bone, PhysicsCollisionObject object); + public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event); } diff --git a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java index b4ae34473..aef81be78 100644 --- a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java +++ b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java @@ -83,8 +83,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener protected Skeleton skeleton; protected PhysicsSpace space; protected boolean enabled = true; - protected boolean debug = false; - protected Quaternion tmp_jointRotation = new Quaternion(); + protected boolean debug = false; protected PhysicsRigidBody baseRigidBody; protected float weightThreshold = 1.0f; protected Spatial targetModel; @@ -95,7 +94,9 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener protected float eventDiscardImpulseThreshold = 3; protected RagdollPreset preset = new HumanoidRagdollPreset(); protected List boneList = new LinkedList(); - protected Vector3f initPosition = new Vector3f(); + protected Vector3f modelPosition = new Vector3f(); + protected float rootMass = 15; + private float totalMass = 0; public RagdollControl() { } @@ -104,6 +105,15 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener this.weightThreshold = weightThreshold; } + public RagdollControl(RagdollPreset preset, float weightThreshold) { + this.preset = preset; + this.weightThreshold = weightThreshold; + } + + public RagdollControl(RagdollPreset preset) { + this.preset = preset; + } + public void update(float tpf) { if (!enabled) { return; @@ -114,7 +124,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener Quaternion q2 = vars.quat1; Quaternion q3 = vars.quat2; - + for (PhysicsBoneLink link : boneLinks.values()) { Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); @@ -128,12 +138,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener q3.set(targetModel.getWorldRotation()).inverseLocal().mult(q2, q2); q2.normalize(); if (link.bone.getParent() == null) { - initPosition.set(p).subtractLocal(link.bone.getInitialPos()); - targetModel.setLocalTranslation(initPosition); + modelPosition.set(p).subtractLocal(link.bone.getInitialPos()); + targetModel.setLocalTranslation(modelPosition); link.bone.setUserControl(true); link.bone.setUserTransformsWorld(position, q2); - } else { + } else { if (boneList.isEmpty()) { link.bone.setUserControl(true); link.bone.setUserTransformsWorld(position, q2); @@ -151,7 +161,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener } Vector3f position = vars.vect1; - Quaternion rotation = vars.quat1; + Quaternion rotation = vars.quat1; //computing position from rotation and scale targetModel.getWorldTransform().transformVector(link.bone.getModelSpacePosition(), position); @@ -161,7 +171,6 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener targetModel.getWorldRotation().mult(rotation, rotation); rotation.normalize(); - // scale.set(link.bone.getModelSpaceScale()); link.rigidBody.setPhysicsLocation(position); link.rigidBody.setPhysicsRotation(rotation); } @@ -240,34 +249,30 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener skeleton = animControl.getSkeleton(); skeleton.resetAndUpdate(); for (int i = 0; i < skeleton.getRoots().length; i++) { - Bone childBone = skeleton.getRoots()[i]; + Bone childBone = skeleton.getRoots()[i]; if (childBone.getParent() == null) { - // Quaternion parentRot= childBone.getModelSpaceRotation().mult(initRotation); logger.log(Level.INFO, "Found root bone in skeleton {0}", skeleton); - baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(.1f)), 1); - // baseRigidBody.setPhysicsRotation(parentRot); + baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(0.1f)), 1); boneRecursion(model, childBone, baseRigidBody, 1); - return; } - } + + } private void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount) { PhysicsRigidBody parentShape = parent; if (boneList.isEmpty() || boneList.contains(bone.getName())) { - //creating the collision shape from the bone's associated vertices - PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(bone, model), 10.0f / (float) reccount); - PhysicsBoneLink link = new PhysicsBoneLink(); link.bone = bone; - link.rigidBody = shapeNode; + //creating the collision shape from the bone's associated vertices + PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(link, model), rootMass / (float) reccount); + totalMass += rootMass / (float) reccount; + link.rigidBody = shapeNode; link.initalWorldRotation = bone.getModelSpaceRotation().clone(); - // link.mass = 10.0f / (float) reccount; - //TODO: ragdoll mass 1 if (parent != null) { //get joint position for parent Vector3f posToParent = new Vector3f(); @@ -281,11 +286,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener link.pivotB = new Vector3f(0, 0, 0f); SixDofJoint joint = new SixDofJoint(parent, shapeNode, link.pivotA, link.pivotB, true); - joint.getTranslationalLimitMotor().setUpperLimit(new Vector3f(0, 0, 0)); - joint.getTranslationalLimitMotor().setLowerLimit(new Vector3f(0, 0, 0)); - //TODO find a way to correctly compute/import joints (maybe based on their names) preset.setupJointForBone(bone.getName(), joint); - //setJointLimit(joint, 0, 0, 0, 0, 0, 0); link.joint = joint; joint.setCollisionBetweenLinkedBodys(false); @@ -297,7 +298,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener for (Iterator it = bone.getChildren().iterator(); it.hasNext();) { Bone childBone = it.next(); - boneRecursion(model, childBone, parentShape, reccount++); + boneRecursion(model, childBone, parentShape, reccount + 1); } @@ -372,8 +373,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener } } - private HullCollisionShape makeShape(Bone bone, Spatial model) { - + private HullCollisionShape makeShape(PhysicsBoneLink link, Spatial model) { + Bone bone = link.bone; List boneIndices = null; if (boneList.isEmpty()) { boneIndices = new LinkedList(); @@ -387,7 +388,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener if (model instanceof Geometry) { Geometry g = (Geometry) model; for (Integer index : boneIndices) { - points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition())); + points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition(), link)); } } else if (model instanceof Node) { Node node = (Node) model; @@ -395,7 +396,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener if (s instanceof Geometry) { Geometry g = (Geometry) s; for (Integer index : boneIndices) { - points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition())); + points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition(), link)); } } @@ -420,7 +421,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener return list; } - protected List getPoints(Mesh mesh, int boneIndex, Vector3f offset) { + protected List getPoints(Mesh mesh, int boneIndex, Vector3f offset, PhysicsBoneLink link) { FloatBuffer vertices = mesh.getFloatBuffer(Type.Position); ByteBuffer boneIndices = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData(); @@ -433,6 +434,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener ArrayList results = new ArrayList(); int vertexComponents = mesh.getVertexCount() * 3; + for (int i = 0; i < vertexComponents; i += 3) { int k; boolean add = false; @@ -444,6 +446,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener } } if (add) { + Vector3f pos = new Vector3f(); pos.x = vertices.get(i); pos.y = vertices.get(i + 1); @@ -452,8 +455,10 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener results.add(pos.x); results.add(pos.y); results.add(pos.z); + } } + return results; } @@ -566,7 +571,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener boolean hit = false; Bone hitBone = null; PhysicsCollisionObject hitObject = null; - + if (objA.getUserObject() instanceof PhysicsBoneLink) { PhysicsBoneLink link = (PhysicsBoneLink) objA.getUserObject(); @@ -585,15 +590,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener hitObject = objA; } - } + } - if (hit && event.getAppliedImpulse() > eventDispatchImpulseThreshold) { - // System.out.println("trigger impact " + event.getNodeA() + " " + event.getNodeB() + " " + event.getAppliedImpulse()); - //setControl(true); + if (hit && event.getAppliedImpulse() > eventDispatchImpulseThreshold) { for (RagdollCollisionListener listener : listeners) { - listener.collide(hitBone, hitObject); + listener.collide(hitBone, hitObject, event); } - } } @@ -629,10 +631,6 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener } - public boolean collide(PhysicsCollisionObject nodeA, PhysicsCollisionObject nodeB) { - throw new UnsupportedOperationException("Not supported yet."); - } - public void addCollisionListener(RagdollCollisionListener listener) { if (listeners == null) { listeners = new ArrayList(); @@ -648,6 +646,40 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener PhysicsRigidBody rigidBody; Vector3f pivotA; Vector3f pivotB; - // float mass; + float volume = 0; + } + + public void setRootMass(float rootMass) { + this.rootMass = rootMass; + } + + public float getTotalMass() { + return totalMass; + } + + public float getWeightThreshold() { + return weightThreshold; + } + + public void setWeightThreshold(float weightThreshold) { + this.weightThreshold = weightThreshold; + } + + public float getEventDiscardImpulseThreshold() { + return eventDiscardImpulseThreshold; + } + + public void setEventDiscardImpulseThreshold(float eventDiscardImpulseThreshold) { + this.eventDiscardImpulseThreshold = eventDiscardImpulseThreshold; + } + + public float getEventDispatchImpulseThreshold() { + return eventDispatchImpulseThreshold; + } + + public void setEventDispatchImpulseThreshold(float eventDispatchImpulseThreshold) { + this.eventDispatchImpulseThreshold = eventDispatchImpulseThreshold; } + + } diff --git a/engine/src/jbullet/com/jme3/bullet/control/ragdoll/HumanoidRagdollPreset.java b/engine/src/jbullet/com/jme3/bullet/control/ragdoll/HumanoidRagdollPreset.java index 24e8b90b5..b32d013b0 100644 --- a/engine/src/jbullet/com/jme3/bullet/control/ragdoll/HumanoidRagdollPreset.java +++ b/engine/src/jbullet/com/jme3/bullet/control/ragdoll/HumanoidRagdollPreset.java @@ -18,15 +18,15 @@ public class HumanoidRagdollPreset extends RagdollPreset { boneMap.put("torso", new JointPreset(FastMath.QUARTER_PI, -FastMath.QUARTER_PI, 0, 0, FastMath.QUARTER_PI, -FastMath.QUARTER_PI)); - boneMap.put("upperleg", new JointPreset(FastMath.PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI)); + boneMap.put("upperleg", new JointPreset(FastMath.PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI/2, -FastMath.QUARTER_PI/2, FastMath.QUARTER_PI, -FastMath.QUARTER_PI)); boneMap.put("lowerleg", new JointPreset(0, -FastMath.PI, 0, 0, 0, 0)); boneMap.put("foot", new JointPreset(0, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI)); - boneMap.put("upperarm", new JointPreset(FastMath.HALF_PI, -FastMath.QUARTER_PI, 0, 0, FastMath.QUARTER_PI, -FastMath.HALF_PI)); + boneMap.put("upperarm", new JointPreset(FastMath.HALF_PI, -FastMath.QUARTER_PI, 0, 0, FastMath.PI, -FastMath.QUARTER_PI)); - boneMap.put("lowerarm", new JointPreset(FastMath.PI, 0, 0, 0, 0, 0)); + boneMap.put("lowerarm", new JointPreset(FastMath.HALF_PI, 0, 0, 0, 0, 0)); boneMap.put("hand", new JointPreset(FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI)); diff --git a/engine/src/jbullet/com/jme3/bullet/control/ragdoll/RagdollPreset.java b/engine/src/jbullet/com/jme3/bullet/control/ragdoll/RagdollPreset.java index ad332ac1b..51bf4babf 100644 --- a/engine/src/jbullet/com/jme3/bullet/control/ragdoll/RagdollPreset.java +++ b/engine/src/jbullet/com/jme3/bullet/control/ragdoll/RagdollPreset.java @@ -35,18 +35,16 @@ public abstract class RagdollPreset { String resultName = ""; int resultScore = 0; - System.out.println("-------------- " +boneName); for (String key : lexicon.keySet()) { - int score = lexicon.get(key).getScore(boneName); - System.out.println(key+" " +score); + int score = lexicon.get(key).getScore(boneName); if (score > resultScore) { resultScore = score; resultName = key; } } - System.out.println("-------------- "); + JointPreset preset = boneMap.get(resultName); if (preset != null && resultScore >= 50) { diff --git a/engine/src/test/jme3test/bullet/BombControl.java b/engine/src/test/jme3test/bullet/BombControl.java index 1e2205769..c75c7079a 100644 --- a/engine/src/test/jme3test/bullet/BombControl.java +++ b/engine/src/test/jme3test/bullet/BombControl.java @@ -105,14 +105,14 @@ public class BombControl extends RigidBodyControl implements PhysicsCollisionLis spatial.removeFromParent(); } } - + public void prePhysicsTick(PhysicsSpace space, float f) { space.removeCollisionListener(this); } public void physicsTick(PhysicsSpace space, float f) { //get all overlapping objects and apply impulse to them - for (Iterator it = ghostObject.getOverlappingObjects().iterator(); it.hasNext();) { + for (Iterator it = ghostObject.getOverlappingObjects().iterator(); it.hasNext();) { PhysicsCollisionObject physicsCollisionObject = it.next(); if (physicsCollisionObject instanceof PhysicsRigidBody) { PhysicsRigidBody rBody = (PhysicsRigidBody) physicsCollisionObject; @@ -157,6 +157,15 @@ public class BombControl extends RigidBodyControl implements PhysicsCollisionLis createGhostObject(); } + public float getForceFactor() { + return forceFactor; + } + + public void setForceFactor(float forceFactor) { + this.forceFactor = forceFactor; + } + + @Override public void read(JmeImporter im) throws IOException { throw new UnsupportedOperationException("Reading not supported."); diff --git a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java index 97e891c53..03fcd8fce 100644 --- a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java +++ b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java @@ -38,11 +38,13 @@ import com.jme3.bullet.BulletAppState; import com.jme3.app.SimpleApplication; import com.jme3.asset.TextureKey; import com.jme3.bullet.PhysicsSpace; +import com.jme3.bullet.collision.PhysicsCollisionEvent; import com.jme3.bullet.collision.PhysicsCollisionObject; import com.jme3.bullet.collision.RagdollCollisionListener; import com.jme3.bullet.collision.shapes.SphereCollisionShape; import com.jme3.bullet.control.RagdollControl; import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.joints.SixDofJoint; import com.jme3.font.BitmapText; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; @@ -92,7 +94,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi bulletAppState = new BulletAppState(); bulletAppState.setEnabled(true); stateManager.attach(bulletAppState); - //bulletAppState.getPhysicsSpace().enableDebug(assetManager); +// bulletAppState.getPhysicsSpace().enableDebug(assetManager); PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace()); setupLight(); @@ -110,13 +112,16 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi skeletonDebug.setLocalTranslation(model.getLocalTranslation()); //Note: PhysicsRagdollControl is still TODO, constructor will change - ragdoll = new RagdollControl(0.7f); + ragdoll = new RagdollControl(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); + + //Oto's head is almost rigid // ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0); @@ -128,8 +133,8 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi flyCam.setMoveSpeed(50); - final AnimChannel channel = control.createChannel(); - channel.setAnim("Dance"); + animChannel = control.createChannel(); + animChannel.setAnim("Dance"); inputManager.addListener(new ActionListener() { @@ -158,21 +163,34 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi bulletg.setMaterial(matBullet); bulletg.setLocalTranslation(cam.getLocation()); bulletg.setLocalScale(bulletSize); - bulletCollisionShape = new SphereCollisionShape(bulletSize); - // RigidBodyControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1); + bulletCollisionShape = new SphereCollisionShape(bulletSize); RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10); bulletNode.setCcdMotionThreshold(0.001f); - bulletNode.setLinearVelocity(cam.getDirection().mult(80)); + bulletNode.setLinearVelocity(cam.getDirection().mult(180)); + 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(10); + bulletNode.setExplosionRadius(30); + bulletNode.setCcdMotionThreshold(0.001f); + bulletNode.setLinearVelocity(cam.getDirection().mult(180)); bulletg.addControl(bulletNode); rootNode.attachChild(bulletg); getPhysicsSpace().add(bulletNode); - - } } - }, "toggle", "shoot", "stop", "bullet+", "bullet-"); + }, "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)); @@ -181,7 +199,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi } private void setupLight() { - AmbientLight al = new AmbientLight(); + // AmbientLight al = new AmbientLight(); // al.setColor(ColorRGBA.White.mult(1)); // rootNode.addLight(al); @@ -225,7 +243,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi guiNode.attachChild(ch); } - public void collide(Bone bone, PhysicsCollisionObject object) { + public void collide(Bone bone, PhysicsCollisionObject object,PhysicsCollisionEvent event) { if (object.getUserObject() != null && object.getUserObject() instanceof Geometry) { Geometry geom = (Geometry) object.getUserObject(); @@ -237,7 +255,6 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi if (!ragdoll.hasControl()) { - //bulletTime(); ragdoll.setControl(true); } @@ -252,7 +269,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi ragdoll.addBoneName("Hand.R"); ragdoll.addBoneName("Hand.L"); ragdoll.addBoneName("Neck"); - ragdoll.addBoneName("Head"); + // ragdoll.addBoneName("Head"); ragdoll.addBoneName("Root"); ragdoll.addBoneName("Stomach"); ragdoll.addBoneName("Waist"); @@ -265,104 +282,53 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi ragdoll.addBoneName("Clavicle.L"); ragdoll.addBoneName("Clavicle.R"); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// - } - private void bulletTime() { - speed = 0.1f; - elTime = 0; - } 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(model.getLocalTranslation()); -// elTime += tpf; -// if (elTime > 0.05f && speed < 1.0f) { -// speed += tpf * 8; -// } -// timer += tpf; - fpsText.setText("Bullet Size: " + bulletSize); - if (!ragdoll.hasControl()) { + 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) { - forward = true; + direction.z = 1; + direction.normalizeLocal(); } else if (model.getLocalTranslation().getZ() > 10) { - forward = false; + direction.z = -1; + direction.normalizeLocal(); } - if (forward) { - model.move(-tpf, 0, tpf); - } else { - model.move(tpf, 0, -tpf); + 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); } } }