RagdollControl ---WIP----

- Automatic creation of the ragdoll collisions shapes
- Changed TestBoneRagdoll (press space to activate physics, left click to shoot bombs)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7151 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 14 years ago
parent 4877b17cab
commit 50d55b7e59
  1. 14
      engine/src/core/com/jme3/animation/AnimControl.java
  2. 26
      engine/src/jbullet/com/jme3/bullet/collision/shapes/HullCollisionShape.java
  3. 232
      engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
  4. 113
      engine/src/test/jme3test/bullet/TestBoneRagdoll.java

@ -32,6 +32,7 @@
package com.jme3.animation; package com.jme3.animation;
import com.jme3.bullet.control.RagdollControl;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
@ -372,6 +373,13 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
return a.getLength(); return a.getLength();
} }
private RagdollControl ragdoll=null;
public void setRagdoll(RagdollControl ragdoll) {
this.ragdoll = ragdoll;
}
@Override @Override
protected void controlUpdate(float tpf) { protected void controlUpdate(float tpf) {
@ -383,8 +391,12 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
} }
skeleton.updateWorldVectors(); skeleton.updateWorldVectors();
// here update the targets verticles if no hardware skinning supported // here update the targets vertices if no hardware skinning supported
if(ragdoll!=null){
ragdoll.update(tpf);
}
Matrix4f[] offsetMatrices = skeleton.computeSkinningMatrices(); Matrix4f[] offsetMatrices = skeleton.computeSkinningMatrices();
// if hardware skinning is supported, the matrices and weight buffer // if hardware skinning is supported, the matrices and weight buffer

@ -27,10 +27,15 @@ public class HullCollisionShape extends CollisionShape {
createShape(this.points); createShape(this.points);
} }
public HullCollisionShape(float[] points) {
this.points = points;
createShape(this.points);
}
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
super.write(ex); super.write(ex);
OutputCapsule capsule = ex.getCapsule(this); OutputCapsule capsule = ex.getCapsule(this);
capsule.write(points, "points", null); capsule.write(points, "points", null);
} }
@ -41,37 +46,36 @@ public class HullCollisionShape extends CollisionShape {
InputCapsule capsule = im.getCapsule(this); InputCapsule capsule = im.getCapsule(this);
// for backwards compatability // for backwards compatability
Mesh mesh = (Mesh)capsule.readSavable("hullMesh", null); Mesh mesh = (Mesh) capsule.readSavable("hullMesh", null);
if (mesh != null){ if (mesh != null) {
this.points = getPoints(mesh); this.points = getPoints(mesh);
}else{ } else {
this.points = capsule.readFloatArray("points", null); this.points = capsule.readFloatArray("points", null);
} }
createShape(this.points); createShape(this.points);
} }
protected void createShape(float[] points){ protected void createShape(float[] points) {
ObjectArrayList<Vector3f> pointList = new ObjectArrayList<Vector3f>(); ObjectArrayList<Vector3f> pointList = new ObjectArrayList<Vector3f>();
for (int i = 0; i < points.length; i += 3) { for (int i = 0; i < points.length; i += 3) {
pointList.add(new Vector3f(points[i], points[i+1], points[i+2])); pointList.add(new Vector3f(points[i], points[i + 1], points[i + 2]));
} }
cShape = new ConvexHullShape(pointList); cShape = new ConvexHullShape(pointList);
cShape.setLocalScaling(Converter.convert(getScale())); cShape.setLocalScaling(Converter.convert(getScale()));
cShape.setMargin(margin); cShape.setMargin(margin);
} }
protected float[] getPoints(Mesh mesh){ protected float[] getPoints(Mesh mesh) {
FloatBuffer vertices = mesh.getFloatBuffer(Type.Position); FloatBuffer vertices = mesh.getFloatBuffer(Type.Position);
vertices.rewind(); vertices.rewind();
int components = mesh.getVertexCount() * 3; int components = mesh.getVertexCount() * 3;
float[] pointsArray = new float[components]; float[] pointsArray = new float[components];
for (int i = 0; i < components; i += 3) { for (int i = 0; i < components; i += 3) {
pointsArray[i] = vertices.get(); pointsArray[i] = vertices.get();
pointsArray[i+1] = vertices.get(); pointsArray[i + 1] = vertices.get();
pointsArray[i+2] = vertices.get(); pointsArray[i + 2] = vertices.get();
} }
return pointsArray; return pointsArray;
} }
} }

@ -6,21 +6,28 @@ import com.jme3.animation.Skeleton;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.BoxCollisionShape; import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; import com.jme3.bullet.collision.shapes.HullCollisionShape;
import com.jme3.bullet.joints.ConeJoint; import com.jme3.bullet.joints.ConeJoint;
import com.jme3.bullet.joints.PhysicsJoint; import com.jme3.bullet.joints.PhysicsJoint;
import com.jme3.bullet.objects.PhysicsRigidBody; import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.control.Control; import com.jme3.scene.control.Control;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@ -38,42 +45,60 @@ public class RagdollControl implements PhysicsControl {
protected boolean debug = false; protected boolean debug = false;
protected Quaternion tmp_jointRotation = new Quaternion(); protected Quaternion tmp_jointRotation = new Quaternion();
protected PhysicsRigidBody baseRigidBody; protected PhysicsRigidBody baseRigidBody;
protected float weightThreshold = 1.0f;
protected Spatial targetModel;
protected Vector3f initPosition;
protected Quaternion initRotation;
protected Vector3f initScale;
//Normen: Think you have the system you want, with movement
//Normen: but the rootBone movement and translation is also accessible like getRootBoneLocation()
//Normen: and you can disable the applying of it
//Normen: setApplyRootBoneMovement(false)
//Normen: when you add a RigidBodyControl..
//Normen: it does this in setSpatial:
//Normen: if (spatial.getcontrol(AnimControl.class)){animControl.setApplyRootBoneMovement(false)
//Normen: and instead reads the current location and sets it to the RigidBody
//Normen: simply said
//Normen: update(){setPhysicsLocation(animControl.getRootBoneLocation())
public RagdollControl() { public RagdollControl() {
} }
public RagdollControl(float weightThreshold) {
this.weightThreshold = weightThreshold;
}
public void update(float tpf) { public void update(float tpf) {
if (!enabled) { if (!enabled) {
return; return;
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock(); assert vars.lock();
Quaternion q2 = vars.quat1;
skeleton.reset(); // skeleton.reset();
for (PhysicsBoneLink link : boneLinks) { for (PhysicsBoneLink link : boneLinks) {
// if(link.bone==skeleton.getRoots()[0]){
// Vector3f loc=vars.vect1;
// loc.set(baseRigidBody.getMotionState().getWorldLocation());//.subtractLocal(rootBoneInit);
// ((Geometry)targetModel).setLocalTranslation(loc);
//
// }
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat(); Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
q.toAxes(vars.tri); q2.set(q).multLocal(link.initalWorldRotation).normalize();
Vector3f dir = vars.tri[2]; link.bone.setUserTransformsWorld(p, q2);
float len = link.length;
Vector3f parentPos = new Vector3f(p).subtractLocal(dir.mult(len / 2f)); }
Vector3f childPos = new Vector3f(p).addLocal(dir.mult(len / 2f));
Quaternion q2 = q.clone();
Quaternion rot = new Quaternion();
rot.fromAngles(FastMath.HALF_PI, 0, 0);
q2.multLocal(rot);
q2.normalize();
link.parentBone.setUserTransformsWorld(parentPos, q2);
if (link.childBone.getChildren().size() == 0) {
link.childBone.setUserTransformsWorld(childPos, q2.clone());
}
}
assert vars.unlock(); assert vars.unlock();
//baseRigidBody.getMotionState().applyTransform(targetModel);
} }
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
@ -81,6 +106,7 @@ public class RagdollControl implements PhysicsControl {
} }
public void setSpatial(Spatial model) { public void setSpatial(Spatial model) {
targetModel = model;
removeFromPhysicsSpace(); removeFromPhysicsSpace();
clearData(); clearData();
// put into bind pose and compute bone transforms in model space // put into bind pose and compute bone transforms in model space
@ -95,23 +121,30 @@ public class RagdollControl implements PhysicsControl {
} }
private void scanSpatial(Spatial model) { private void scanSpatial(Spatial model) {
AnimControl animControl = model.getControl(AnimControl.class); AnimControl animControl = model.getControl(AnimControl.class);
initPosition = model.getLocalTranslation();
initRotation = model.getLocalRotation();
initScale = model.getLocalScale();
skeleton = animControl.getSkeleton(); skeleton = animControl.getSkeleton();
skeleton.resetAndUpdate(); skeleton.resetAndUpdate();
for (int i = 0; i < skeleton.getBoneCount(); i++) { for (int i = 0; i < skeleton.getRoots().length; i++) {
Bone childBone = skeleton.getBone(i); Bone childBone = skeleton.getRoots()[i];
childBone.setUserControl(true); childBone.setUserControl(true);
if (childBone.getParent() == null) { if (childBone.getParent() == null) {
Vector3f parentPos = childBone.getModelSpacePosition().add(model.getWorldTranslation()); Vector3f parentPos = childBone.getModelSpacePosition().add(initPosition);
// Quaternion parentRot= childBone.getModelSpaceRotation().mult(initRotation);
logger.log(Level.INFO, "Found root bone in skeleton {0}", skeleton); logger.log(Level.INFO, "Found root bone in skeleton {0}", skeleton);
baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(.1f)), 1); baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(.1f)), 1);
baseRigidBody.setPhysicsLocation(parentPos); baseRigidBody.setPhysicsLocation(parentPos);
// baseRigidBody.setPhysicsRotation(parentRot);
boneLinks = boneRecursion(model, childBone, baseRigidBody, boneLinks, 1); boneLinks = boneRecursion(model, childBone, baseRigidBody, boneLinks, 1);
return; return;
} }
} }
// BoneAnimation myAnimation = new BoneAnimation("boneAnimation", 1000000); // BoneAnimation myAnimation = new BoneAnimation("boneAnimation", 1000000);
// myAnimation.setTracks(new BoneTrack[0]); // myAnimation.setTracks(new BoneTrack[0]);
// animControl.addAnim(myAnimation); // animControl.addAnim(myAnimation);
@ -120,52 +153,47 @@ public class RagdollControl implements PhysicsControl {
} }
private List<PhysicsBoneLink> boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, List<PhysicsBoneLink> list, int reccount) { private List<PhysicsBoneLink> boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, List<PhysicsBoneLink> list, int reccount) {
ArrayList<Bone> children = bone.getChildren(); //Allow bone's transformation change outside of animation
bone.setUserControl(true); bone.setUserControl(true);
for (Iterator<Bone> it = children.iterator(); it.hasNext();) {
Bone childBone = it.next();
Bone parentBone = bone;
Vector3f parentPos = parentBone.getModelSpacePosition().add(model.getWorldTranslation());
Vector3f childPos = childBone.getModelSpacePosition().add(model.getWorldTranslation());
//get location between the two bones (physicscapsule center)
Vector3f jointCenter = parentPos.add(childPos).multLocal(0.5f);
tmp_jointRotation.lookAt(childPos.subtract(parentPos), Vector3f.UNIT_Y);
// length of the joint
float height = parentPos.distance(childPos);
// TODO: joints act funny when bone is too thin??
float radius = height > 2f ? 0.4f : height * .2f;
CapsuleCollisionShape shape = new CapsuleCollisionShape(radius, height - (radius), 2);
PhysicsRigidBody shapeNode = new PhysicsRigidBody(shape, 10.0f / (float) reccount);
shapeNode.setPhysicsLocation(jointCenter);
shapeNode.setPhysicsRotation(tmp_jointRotation.toRotationMatrix());
PhysicsBoneLink link = new PhysicsBoneLink();
link.parentBone = parentBone;
link.childBone = childBone;
link.rigidBody = shapeNode;
link.length = height;
//TODO: ragdoll mass 1
if (parent != null) {
//get length of parent
float parentHeight = 0.0f;
if (bone.getParent() != null) {
parentHeight = bone.getParent().getModelSpacePosition().add(model.getWorldTranslation()).distance(parentPos);
}
//local position from parent
link.pivotA = new Vector3f(0, 0, (parentHeight * .5f));
//local position from child
link.pivotB = new Vector3f(0, 0, -(height * .5f));
ConeJoint joint = new ConeJoint(parent, shapeNode, link.pivotA, link.pivotB); //get world space position of the bone
joint.setLimit(FastMath.HALF_PI, FastMath.HALF_PI, 0.01f); Vector3f pos = bone.getModelSpacePosition().add(model.getLocalTranslation());
Quaternion rot= bone.getModelSpaceRotation().mult(initRotation);
link.joint = joint;
joint.setCollisionBetweenLinkedBodys(false); //creating the collision shape from the bone's associated vertices
PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(bone, model), 10.0f / (float) reccount);
shapeNode.setPhysicsLocation(pos);
// shapeNode.setPhysicsRotation(rot);
PhysicsBoneLink link = new PhysicsBoneLink();
link.bone = bone;
link.rigidBody = shapeNode;
link.initalWorldRotation = bone.getModelSpaceRotation().clone();
//TODO: ragdoll mass 1
if (parent != null) {
//get joint position for parent
Vector3f posToParent = new Vector3f();
if (bone.getParent() != null) {
bone.getModelSpacePosition().subtract(bone.getParent().getModelSpacePosition(), posToParent);
} }
list.add(link);
//Joint local position from parent
link.pivotA = posToParent;
//joint local position from current bone
link.pivotB = new Vector3f(0, 0, 0f);
ConeJoint joint = new ConeJoint(parent, shapeNode, link.pivotA, link.pivotB);
//TODO make joints editable by user or find a way to correctly compute/import them
joint.setLimit(FastMath.HALF_PI, FastMath.HALF_PI, 0.01f);
link.joint = joint;
joint.setCollisionBetweenLinkedBodys(false);
}
list.add(link);
for (Iterator<Bone> it = bone.getChildren().iterator(); it.hasNext();) {
Bone childBone = it.next();
boneRecursion(model, childBone, shapeNode, list, reccount++); boneRecursion(model, childBone, shapeNode, list, reccount++);
} }
return list; return list;
@ -194,6 +222,67 @@ public class RagdollControl implements PhysicsControl {
} }
} }
private HullCollisionShape makeShape(Bone bone, Spatial model) {
int boneIndex = skeleton.getBoneIndex(bone);
System.out.println(boneIndex);
ArrayList<Float> points = new ArrayList<Float>();
if (model instanceof Geometry) {
Geometry g = (Geometry) model;
points.addAll(getPoints(g.getMesh(), boneIndex, bone.getModelSpacePosition()));
} else if (model instanceof Node) {
Node node = (Node) model;
for (Spatial s : node.getChildren()) {
if (s instanceof Geometry) {
Geometry g = (Geometry) s;
points.addAll(getPoints(g.getMesh(), boneIndex, bone.getModelSpacePosition()));
}
}
}
float[] p = new float[points.size()];
for (int i = 0; i < points.size(); i++) {
p[i] = points.get(i);
}
return new HullCollisionShape(p);
}
protected List<Float> getPoints(Mesh mesh, int boneIndex, Vector3f offset) {
FloatBuffer vertices = mesh.getFloatBuffer(Type.Position);
ByteBuffer boneIndices = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData();
FloatBuffer boneWeight = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
vertices.rewind();
boneIndices.rewind();
boneWeight.rewind();
ArrayList<Float> results = new ArrayList<Float>();
int vertexComponents = mesh.getVertexCount() * 3;
for (int i = 0; i < vertexComponents; i += 3) {
int k;
boolean add = false;
int start = i / 3 * 4;
for (k = start; k < start + 4; k++) {
if (boneIndices.get(k) == boneIndex && boneWeight.get(k) >= weightThreshold) {
add = true;
break;
}
}
if (add) {
Vector3f pos = new Vector3f();
pos.x = vertices.get(i);
pos.y = vertices.get(i + 1);
pos.z = vertices.get(i + 2);
pos.subtractLocal(offset);
results.add(pos.x);
results.add(pos.y);
results.add(pos.z);
}
}
return results;
}
private void removeFromPhysicsSpace() { private void removeFromPhysicsSpace() {
if (baseRigidBody != null) { if (baseRigidBody != null) {
space.remove(baseRigidBody); space.remove(baseRigidBody);
@ -214,9 +303,9 @@ public class RagdollControl implements PhysicsControl {
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
this.enabled = enabled; this.enabled = enabled;
if(!enabled&&space!=null){ if (!enabled && space != null) {
removeFromPhysicsSpace(); removeFromPhysicsSpace();
}else if(enabled && space!=null){ } else if (enabled && space != null) {
addToPhysicsSpace(); addToPhysicsSpace();
} }
} }
@ -284,14 +373,13 @@ public class RagdollControl implements PhysicsControl {
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
} }
private static class PhysicsBoneLink { protected static class PhysicsBoneLink {
Bone childBone; Bone bone;
Bone parentBone; Quaternion initalWorldRotation;
PhysicsJoint joint; PhysicsJoint joint;
PhysicsRigidBody rigidBody; PhysicsRigidBody rigidBody;
Vector3f pivotA; Vector3f pivotA;
Vector3f pivotB; Vector3f pivotB;
float length;
} }
} }

@ -35,14 +35,31 @@ package jme3test.bullet;
import com.jme3.animation.AnimControl; import com.jme3.animation.AnimControl;
import com.jme3.bullet.BulletAppState; import com.jme3.bullet.BulletAppState;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.RagdollControl; import com.jme3.bullet.control.RagdollControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.font.BitmapText;
import com.jme3.input.ChaseCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
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.light.DirectionalLight;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.debug.SkeletonDebugger; 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! * PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET!
@ -51,6 +68,8 @@ import com.jme3.scene.debug.SkeletonDebugger;
public class TestBoneRagdoll extends SimpleApplication { public class TestBoneRagdoll extends SimpleApplication {
private BulletAppState bulletAppState; private BulletAppState bulletAppState;
Material matBullet;
Node model;
public static void main(String[] args){ public static void main(String[] args){
TestBoneRagdoll app = new TestBoneRagdoll(); TestBoneRagdoll app = new TestBoneRagdoll();
@ -58,13 +77,18 @@ public class TestBoneRagdoll extends SimpleApplication {
} }
public void simpleInitApp() { public void simpleInitApp() {
initCrossHairs();
initMaterial();
bulletAppState = new BulletAppState(); bulletAppState = new BulletAppState();
bulletAppState.setEnabled(false);
stateManager.attach(bulletAppState); stateManager.attach(bulletAppState);
bulletAppState.getPhysicsSpace().enableDebug(assetManager); bulletAppState.getPhysicsSpace().enableDebug(assetManager);
PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace()); PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
setupLight(); setupLight();
Node model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml"); model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
// model.setLocalTranslation(5,5,5);
// model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X));
//debug view //debug view
AnimControl control= model.getControl(AnimControl.class); AnimControl control= model.getControl(AnimControl.class);
@ -73,18 +97,62 @@ public class TestBoneRagdoll extends SimpleApplication {
mat2.setColor("Color", ColorRGBA.Green); mat2.setColor("Color", ColorRGBA.Green);
mat2.getAdditionalRenderState().setDepthTest(false); mat2.getAdditionalRenderState().setDepthTest(false);
skeletonDebug.setMaterial(mat2); skeletonDebug.setMaterial(mat2);
skeletonDebug.setLocalTranslation(model.getLocalTranslation());
control.createChannel().setAnim("Dodge");
//Note: PhysicsRagdollControl is still TODO, constructor will change //Note: PhysicsRagdollControl is still TODO, constructor will change
RagdollControl ragdoll = new RagdollControl(); RagdollControl ragdoll = new RagdollControl();
// ragdoll.setEnabled(true);
// ragdoll.attachDebugShape(assetManager);
model.addControl(ragdoll); ragdoll.setSpatial(model);
getPhysicsSpace().add(ragdoll); ragdoll.setPhysicsSpace(getPhysicsSpace());
speed = .2f; control.setRagdoll(ragdoll);
// model.addControl(ragdoll);
// getPhysicsSpace().add(ragdoll);
speed = 1f;
rootNode.attachChild(model); rootNode.attachChild(model);
rootNode.attachChild(skeletonDebug); rootNode.attachChild(skeletonDebug);
flyCam.setEnabled(false);
// flyCam.setMoveSpeed(10);
ChaseCamera chaseCamera=new ChaseCamera(cam, inputManager);
model.addControl(chaseCamera);
inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) {
if(name.equals("toggle") && isPressed){
bulletAppState.setEnabled(!bulletAppState.isEnabled());
}
if (name.equals("shoot") && !isPressed) {
Geometry bulletg = new Geometry("bullet", bullet);
bulletg.setMaterial(matBullet);
bulletg.setLocalTranslation(cam.getLocation());
RigidBodyControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1);
// RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, 1);
bulletNode.setLinearVelocity(cam.getDirection().mult(60));
bulletg.addControl(bulletNode);
rootNode.attachChild(bulletg);
getPhysicsSpace().add(bulletNode);
}
}
}, "toggle", "shoot");
inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
} }
@Override
public void simpleUpdate(float tpf) {
}
private void setupLight() { private void setupLight() {
DirectionalLight dl = new DirectionalLight(); DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
@ -96,4 +164,41 @@ public class TestBoneRagdoll extends SimpleApplication {
return bulletAppState.getPhysicsSpace(); return bulletAppState.getPhysicsSpace();
} }
Material mat;
Material mat3;
private static final Sphere bullet;
private static final SphereCollisionShape bulletCollisionShape;
static {
bullet = new Sphere(32, 32, 0.4f, true, false);
bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f);
}
public void initMaterial() {
matBullet = new Material(assetManager, "Common/MatDefs/Misc/SimpleTextured.j3md");
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
matBullet.setTexture("ColorMap", tex2);
}
protected void initCrossHairs() {
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // crosshairs
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}
} }

Loading…
Cancel
Save