You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
9.8 KiB
290 lines
9.8 KiB
/*
|
|
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
package com.jme3.bullet.objects;
|
|
|
|
import com.bulletphysics.collision.dispatch.CollisionFlags;
|
|
import com.bulletphysics.collision.dispatch.PairCachingGhostObject;
|
|
import com.bulletphysics.collision.shapes.ConvexShape;
|
|
import com.bulletphysics.dynamics.character.KinematicCharacterController;
|
|
import com.bulletphysics.linearmath.Transform;
|
|
import com.jme3.bullet.collision.PhysicsCollisionObject;
|
|
import com.jme3.bullet.collision.shapes.CollisionShape;
|
|
import com.jme3.bullet.util.Converter;
|
|
import com.jme3.export.InputCapsule;
|
|
import com.jme3.export.JmeExporter;
|
|
import com.jme3.export.JmeImporter;
|
|
import com.jme3.export.OutputCapsule;
|
|
import com.jme3.math.Matrix3f;
|
|
import com.jme3.math.Quaternion;
|
|
import com.jme3.math.Vector3f;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* Basic Bullet Character
|
|
* @author normenhansen
|
|
*/
|
|
public class PhysicsCharacter extends PhysicsCollisionObject {
|
|
|
|
protected KinematicCharacterController character;
|
|
protected float stepHeight;
|
|
protected Vector3f walkDirection = new Vector3f();
|
|
protected float fallSpeed = 55.0f;
|
|
protected float jumpSpeed = 10.0f;
|
|
protected int upAxis = 1;
|
|
protected PairCachingGhostObject gObject;
|
|
protected boolean locationDirty = false;
|
|
//TEMP VARIABLES
|
|
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
|
private Transform tempTrans = new Transform(Converter.convert(new Matrix3f()));
|
|
private com.jme3.math.Transform physicsLocation = new com.jme3.math.Transform();
|
|
private javax.vecmath.Vector3f tempVec = new javax.vecmath.Vector3f();
|
|
|
|
public PhysicsCharacter() {
|
|
}
|
|
|
|
/**
|
|
* @param shape The CollisionShape (no Mesh or CompoundCollisionShapes)
|
|
* @param stepHeight The quantization size for vertical movement
|
|
*/
|
|
public PhysicsCharacter(CollisionShape shape, float stepHeight) {
|
|
this.collisionShape = shape;
|
|
if (!(shape.getCShape() instanceof ConvexShape)) {
|
|
throw (new UnsupportedOperationException("Kinematic character nodes cannot have mesh collision shapes"));
|
|
}
|
|
this.stepHeight = stepHeight;
|
|
buildObject();
|
|
}
|
|
|
|
protected void buildObject() {
|
|
if (gObject == null) {
|
|
gObject = new PairCachingGhostObject();
|
|
}
|
|
gObject.setCollisionFlags(CollisionFlags.CHARACTER_OBJECT);
|
|
gObject.setCollisionFlags(gObject.getCollisionFlags() & ~CollisionFlags.NO_CONTACT_RESPONSE);
|
|
gObject.setCollisionShape(collisionShape.getCShape());
|
|
gObject.setUserPointer(this);
|
|
character = new KinematicCharacterController(gObject, (ConvexShape) collisionShape.getCShape(), stepHeight);
|
|
}
|
|
|
|
/**
|
|
* Sets the location of this physics character
|
|
* @param location
|
|
*/
|
|
public void warp(Vector3f location) {
|
|
character.warp(Converter.convert(location, tempVec));
|
|
}
|
|
|
|
/**
|
|
* Set the walk direction, works continuously.
|
|
* This should probably be called setPositionIncrementPerSimulatorStep.
|
|
* This is neither a direction nor a velocity, but the amount to
|
|
* increment the position each physics tick. So vector length = accuracy*speed in m/s
|
|
* @param vec the walk direction to set
|
|
*/
|
|
public void setWalkDirection(Vector3f vec) {
|
|
walkDirection.set(vec);
|
|
character.setWalkDirection(Converter.convert(walkDirection, tempVec));
|
|
}
|
|
|
|
/**
|
|
* @return the currently set walkDirection
|
|
*/
|
|
public Vector3f getWalkDirection() {
|
|
return walkDirection;
|
|
}
|
|
|
|
public void setUpAxis(int axis) {
|
|
upAxis = axis;
|
|
character.setUpAxis(axis);
|
|
}
|
|
|
|
public int getUpAxis() {
|
|
return upAxis;
|
|
}
|
|
|
|
public void setFallSpeed(float fallSpeed) {
|
|
this.fallSpeed = fallSpeed;
|
|
character.setFallSpeed(fallSpeed);
|
|
}
|
|
|
|
public float getFallSpeed() {
|
|
return fallSpeed;
|
|
}
|
|
|
|
public void setJumpSpeed(float jumpSpeed) {
|
|
this.jumpSpeed = jumpSpeed;
|
|
character.setJumpSpeed(jumpSpeed);
|
|
}
|
|
|
|
public float getJumpSpeed() {
|
|
return jumpSpeed;
|
|
}
|
|
|
|
//does nothing..
|
|
// public void setMaxJumpHeight(float height) {
|
|
// character.setMaxJumpHeight(height);
|
|
// }
|
|
public void setGravity(float value) {
|
|
character.setGravity(value);
|
|
}
|
|
|
|
public float getGravity() {
|
|
return character.getGravity();
|
|
}
|
|
|
|
public void setMaxSlope(float slopeRadians) {
|
|
character.setMaxSlope(slopeRadians);
|
|
}
|
|
|
|
public float getMaxSlope() {
|
|
return character.getMaxSlope();
|
|
}
|
|
|
|
public boolean onGround() {
|
|
return character.onGround();
|
|
}
|
|
|
|
public void jump() {
|
|
character.jump();
|
|
}
|
|
|
|
@Override
|
|
public void setCollisionShape(CollisionShape collisionShape) {
|
|
if (!(collisionShape.getCShape() instanceof ConvexShape)) {
|
|
throw (new UnsupportedOperationException("Kinematic character nodes cannot have mesh collision shapes"));
|
|
}
|
|
super.setCollisionShape(collisionShape);
|
|
if (gObject == null) {
|
|
buildObject();
|
|
}else{
|
|
gObject.setCollisionShape(collisionShape.getCShape());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the physics location (same as warp())
|
|
* @param location the location of the actual physics object
|
|
*/
|
|
public void setPhysicsLocation(Vector3f location) {
|
|
warp(location);
|
|
}
|
|
|
|
/**
|
|
* @return the physicsLocation
|
|
*/
|
|
public Vector3f getPhysicsLocation(Vector3f trans) {
|
|
if (trans == null) {
|
|
trans = new Vector3f();
|
|
}
|
|
gObject.getWorldTransform(tempTrans);
|
|
Converter.convert(tempTrans.origin, physicsLocation.getTranslation());
|
|
return trans.set(physicsLocation.getTranslation());
|
|
}
|
|
|
|
/**
|
|
* @return the physicsLocation
|
|
*/
|
|
public Vector3f getPhysicsLocation() {
|
|
gObject.getWorldTransform(tempTrans);
|
|
Converter.convert(tempTrans.origin, physicsLocation.getTranslation());
|
|
return physicsLocation.getTranslation();
|
|
}
|
|
|
|
public void setCcdSweptSphereRadius(float radius) {
|
|
gObject.setCcdSweptSphereRadius(radius);
|
|
}
|
|
|
|
public void setCcdMotionThreshold(float threshold) {
|
|
gObject.setCcdMotionThreshold(threshold);
|
|
}
|
|
|
|
public float getCcdSweptSphereRadius() {
|
|
return gObject.getCcdSweptSphereRadius();
|
|
}
|
|
|
|
public float getCcdMotionThreshold() {
|
|
return gObject.getCcdMotionThreshold();
|
|
}
|
|
|
|
public float getCcdSquareMotionThreshold() {
|
|
return gObject.getCcdSquareMotionThreshold();
|
|
}
|
|
|
|
/**
|
|
* used internally
|
|
*/
|
|
public KinematicCharacterController getControllerId() {
|
|
return character;
|
|
}
|
|
|
|
/**
|
|
* used internally
|
|
*/
|
|
public PairCachingGhostObject getObjectId() {
|
|
return gObject;
|
|
}
|
|
|
|
public void destroy() {
|
|
}
|
|
|
|
@Override
|
|
public void write(JmeExporter e) throws IOException {
|
|
super.write(e);
|
|
OutputCapsule capsule = e.getCapsule(this);
|
|
capsule.write(stepHeight, "stepHeight", 1.0f);
|
|
capsule.write(getGravity(), "gravity", 9.8f * 3);
|
|
capsule.write(getMaxSlope(), "maxSlope", 1.0f);
|
|
capsule.write(fallSpeed, "fallSpeed", 55.0f);
|
|
capsule.write(jumpSpeed, "jumpSpeed", 10.0f);
|
|
capsule.write(upAxis, "upAxis", 1);
|
|
capsule.write(getCcdMotionThreshold(), "ccdMotionThreshold", 0);
|
|
capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0);
|
|
capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f());
|
|
}
|
|
|
|
@Override
|
|
public void read(JmeImporter e) throws IOException {
|
|
super.read(e);
|
|
InputCapsule capsule = e.getCapsule(this);
|
|
stepHeight = capsule.readFloat("stepHeight", 1.0f);
|
|
buildObject();
|
|
character = new KinematicCharacterController(gObject, (ConvexShape) collisionShape.getCShape(), stepHeight);
|
|
setGravity(capsule.readFloat("gravity", 9.8f * 3));
|
|
setMaxSlope(capsule.readFloat("maxSlope", 1.0f));
|
|
setFallSpeed(capsule.readFloat("fallSpeed", 55.0f));
|
|
setJumpSpeed(capsule.readFloat("jumpSpeed", 10.0f));
|
|
setUpAxis(capsule.readInt("upAxis", 1));
|
|
setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0));
|
|
setCcdSweptSphereRadius(capsule.readFloat("ccdSweptSphereRadius", 0));
|
|
setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f()));
|
|
}
|
|
}
|
|
|