jme3-bullet: add and improve comments, mostly JavaDoc
This commit is contained in:
parent
025b27c96d
commit
6e96ee5bf2
@ -43,66 +43,136 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>BulletAppState</code> allows using bullet physics in an Application.
|
* An app state to manage a single Bullet physics space.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletAppState implements AppState, PhysicsTickListener {
|
public class BulletAppState implements AppState, PhysicsTickListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true if-and-only-if the physics simulation is running (started but not
|
||||||
|
* yet stopped)
|
||||||
|
*/
|
||||||
protected boolean initialized = false;
|
protected boolean initialized = false;
|
||||||
protected Application app;
|
protected Application app;
|
||||||
|
/**
|
||||||
|
* manager that manages this state, set during attach
|
||||||
|
*/
|
||||||
protected AppStateManager stateManager;
|
protected AppStateManager stateManager;
|
||||||
|
/**
|
||||||
|
* executor service for physics tasks, or null if parallel simulation is not
|
||||||
|
* running
|
||||||
|
*/
|
||||||
protected ScheduledThreadPoolExecutor executor;
|
protected ScheduledThreadPoolExecutor executor;
|
||||||
|
/**
|
||||||
|
* physics space managed by this state, or null if no simulation running
|
||||||
|
*/
|
||||||
protected PhysicsSpace pSpace;
|
protected PhysicsSpace pSpace;
|
||||||
|
/**
|
||||||
|
* threading mode to use (not null)
|
||||||
|
*/
|
||||||
protected ThreadingType threadingType = ThreadingType.SEQUENTIAL;
|
protected ThreadingType threadingType = ThreadingType.SEQUENTIAL;
|
||||||
|
/**
|
||||||
|
* broadphase collision-detection algorithm for the physics space to use
|
||||||
|
* (not null)
|
||||||
|
*/
|
||||||
protected BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
protected BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
||||||
|
/**
|
||||||
|
* minimum coordinate values for the physics space when using AXIS_SWEEP
|
||||||
|
* broadphase algorithms (not null)
|
||||||
|
*/
|
||||||
protected Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
protected Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
||||||
|
/**
|
||||||
|
* maximum coordinate values for the physics space when using AXIS_SWEEP
|
||||||
|
* broadphase algorithms (not null)
|
||||||
|
*/
|
||||||
protected Vector3f worldMax = new Vector3f(10000f, 10000f, 10000f);
|
protected Vector3f worldMax = new Vector3f(10000f, 10000f, 10000f);
|
||||||
|
/**
|
||||||
|
* simulation speed multiplier (default=1, paused=0)
|
||||||
|
*/
|
||||||
protected float speed = 1;
|
protected float speed = 1;
|
||||||
|
/**
|
||||||
|
* true if-and-only-if this state is enabled
|
||||||
|
*/
|
||||||
protected boolean active = true;
|
protected boolean active = true;
|
||||||
|
/**
|
||||||
|
* true if-and-only-if debug visualization is enabled
|
||||||
|
*/
|
||||||
protected boolean debugEnabled = false;
|
protected boolean debugEnabled = false;
|
||||||
|
/**
|
||||||
|
* app state to manage the debug visualization, or null if none
|
||||||
|
*/
|
||||||
protected BulletDebugAppState debugAppState;
|
protected BulletDebugAppState debugAppState;
|
||||||
|
/**
|
||||||
|
* time interval between frames (in seconds) from the most recent update
|
||||||
|
*/
|
||||||
protected float tpf;
|
protected float tpf;
|
||||||
|
/**
|
||||||
|
* current physics task, or null if none
|
||||||
|
*/
|
||||||
protected Future physicsFuture;
|
protected Future physicsFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new BulletAppState running a PhysicsSpace for physics
|
* Instantiate an app state to manage a new PhysicsSpace with DBVT collision
|
||||||
* simulation, use getStateManager().attach(bulletAppState) to enable
|
* detection.
|
||||||
* physics for an Application.
|
* <p>
|
||||||
|
* Use getStateManager().addState(bulletAppState) to start physics.
|
||||||
*/
|
*/
|
||||||
public BulletAppState() {
|
public BulletAppState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new BulletAppState running a PhysicsSpace for physics
|
* Instantiate an app state to manage a new PhysicsSpace.
|
||||||
* simulation, use getStateManager().attach(bulletAppState) to enable
|
* <p>
|
||||||
* physics for an Application.
|
* Use getStateManager().addState(bulletAppState) to start physics.
|
||||||
*
|
*
|
||||||
* @param broadphaseType The type of broadphase collision detection,
|
* @param broadphaseType which broadphase collision-detection algorithm to
|
||||||
* BroadphaseType.DVBT is the default
|
* use (not null)
|
||||||
*/
|
*/
|
||||||
public BulletAppState(BroadphaseType broadphaseType) {
|
public BulletAppState(BroadphaseType broadphaseType) {
|
||||||
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new BulletAppState running a PhysicsSpace for physics
|
* Instantiate an app state to manage a new PhysicsSpace with AXIS_SWEEP_3
|
||||||
* simulation, use getStateManager().attach(bulletAppState) to enable
|
* collision detection.
|
||||||
* physics for an Application. An AxisSweep broadphase is used.
|
* <p>
|
||||||
|
* Use getStateManager().addState(bulletAppState) to start physics.
|
||||||
*
|
*
|
||||||
* @param worldMin The minimum world extent
|
* @param worldMin the desired minimum coordinate values (not null,
|
||||||
* @param worldMax The maximum world extent
|
* unaffected, default=-10k,-10k,-10k)
|
||||||
|
* @param worldMax the desired maximum coordinate values (not null,
|
||||||
|
* unaffected, default=10k,10k,10k)
|
||||||
*/
|
*/
|
||||||
public BulletAppState(Vector3f worldMin, Vector3f worldMax) {
|
public BulletAppState(Vector3f worldMin, Vector3f worldMax) {
|
||||||
this(worldMin, worldMax, BroadphaseType.AXIS_SWEEP_3);
|
this(worldMin, worldMax, BroadphaseType.AXIS_SWEEP_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an app state to manage a new PhysicsSpace.
|
||||||
|
* <p>
|
||||||
|
* Use getStateManager().addState(bulletAppState) to enable physics.
|
||||||
|
*
|
||||||
|
* @param worldMin the desired minimum coordinate values (not null,
|
||||||
|
* unaffected, default=-10k,-10k,-10k)
|
||||||
|
* @param worldMax the desired maximum coordinate values (not null,
|
||||||
|
* unaffected, default=10k,10k,10k)
|
||||||
|
* @param broadphaseType which broadphase collision-detection algorithm to
|
||||||
|
* use (not null)
|
||||||
|
*/
|
||||||
public BulletAppState(Vector3f worldMin, Vector3f worldMax, BroadphaseType broadphaseType) {
|
public BulletAppState(Vector3f worldMin, Vector3f worldMax, BroadphaseType broadphaseType) {
|
||||||
this.worldMin.set(worldMin);
|
this.worldMin.set(worldMin);
|
||||||
this.worldMax.set(worldMax);
|
this.worldMax.set(worldMax);
|
||||||
this.broadphaseType = broadphaseType;
|
this.broadphaseType = broadphaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate the physics space and start physics for ThreadingType.PARALLEL.
|
||||||
|
*
|
||||||
|
* @return true if successful, otherwise false
|
||||||
|
*/
|
||||||
private boolean startPhysicsOnExecutor() {
|
private boolean startPhysicsOnExecutor() {
|
||||||
if (executor != null) {
|
if (executor != null) {
|
||||||
executor.shutdown();
|
executor.shutdown();
|
||||||
@ -145,6 +215,12 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the PhysicsSpace managed by this state. Normally there is none
|
||||||
|
* until the state is attached.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance, or null if no simulation running
|
||||||
|
*/
|
||||||
public PhysicsSpace getPhysicsSpace() {
|
public PhysicsSpace getPhysicsSpace() {
|
||||||
return pSpace;
|
return pSpace;
|
||||||
}
|
}
|
||||||
@ -179,6 +255,9 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop physics after this state is detached.
|
||||||
|
*/
|
||||||
public void stopPhysics() {
|
public void stopPhysics() {
|
||||||
if(!initialized){
|
if(!initialized){
|
||||||
return;
|
return;
|
||||||
@ -192,32 +271,72 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this state prior to its 1st update. Should be invoked only by
|
||||||
|
* a subclass or by the AppStateManager.
|
||||||
|
*
|
||||||
|
* @param stateManager the manager for this state (not null)
|
||||||
|
* @param app the application which owns this state (not null)
|
||||||
|
*/
|
||||||
public void initialize(AppStateManager stateManager, Application app) {
|
public void initialize(AppStateManager stateManager, Application app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.stateManager = stateManager;
|
this.stateManager = stateManager;
|
||||||
startPhysics();
|
startPhysics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the physics simulation is running (started but not yet
|
||||||
|
* stopped).
|
||||||
|
*
|
||||||
|
* @return true if running, otherwise false
|
||||||
|
*/
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return initialized;
|
return initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable this state.
|
||||||
|
*
|
||||||
|
* @param enabled true → enable, false → disable
|
||||||
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.active = enabled;
|
this.active = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this state is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether debug visualization is enabled.
|
||||||
|
*
|
||||||
|
* @param debugEnabled true → enable, false → disable
|
||||||
|
*/
|
||||||
public void setDebugEnabled(boolean debugEnabled) {
|
public void setDebugEnabled(boolean debugEnabled) {
|
||||||
this.debugEnabled = debugEnabled;
|
this.debugEnabled = debugEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether debug visualization is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isDebugEnabled() {
|
public boolean isDebugEnabled() {
|
||||||
return debugEnabled;
|
return debugEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition this state from detached to initializing. Should be invoked
|
||||||
|
* only by a subclass or by the AppStateManager.
|
||||||
|
*
|
||||||
|
* @param stateManager (not null)
|
||||||
|
*/
|
||||||
public void stateAttached(AppStateManager stateManager) {
|
public void stateAttached(AppStateManager stateManager) {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
startPhysics();
|
startPhysics();
|
||||||
@ -231,9 +350,22 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition this state from running to terminating. Should be invoked only
|
||||||
|
* by a subclass or by the AppStateManager.
|
||||||
|
*
|
||||||
|
* @param stateManager (not null)
|
||||||
|
*/
|
||||||
public void stateDetached(AppStateManager stateManager) {
|
public void stateDetached(AppStateManager stateManager) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this state prior to rendering. Should be invoked only by a
|
||||||
|
* subclass or by the AppStateManager. Invoked once per frame, provided the
|
||||||
|
* state is attached and enabled.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
if (debugEnabled && debugAppState == null && pSpace != null) {
|
if (debugEnabled && debugAppState == null && pSpace != null) {
|
||||||
debugAppState = new BulletDebugAppState(pSpace);
|
debugAppState = new BulletDebugAppState(pSpace);
|
||||||
@ -249,6 +381,13 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
this.tpf = tpf;
|
this.tpf = tpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this state. Should be invoked only by a subclass or by the
|
||||||
|
* AppStateManager. Invoked once per frame, provided the state is attached
|
||||||
|
* and enabled.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
*/
|
||||||
public void render(RenderManager rm) {
|
public void render(RenderManager rm) {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return;
|
return;
|
||||||
@ -261,6 +400,11 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this state after all rendering commands are flushed. Should be
|
||||||
|
* invoked only by a subclass or by the AppStateManager. Invoked once per
|
||||||
|
* frame, provided the state is attached and enabled.
|
||||||
|
*/
|
||||||
public void postRender() {
|
public void postRender() {
|
||||||
if (physicsFuture != null) {
|
if (physicsFuture != null) {
|
||||||
try {
|
try {
|
||||||
@ -274,6 +418,12 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition this state from terminating to detached. Should be invoked
|
||||||
|
* only by a subclass or by the AppStateManager. Invoked once for each time
|
||||||
|
* {@link #initialize(com.jme3.app.state.AppStateManager, com.jme3.app.Application)}
|
||||||
|
* is invoked.
|
||||||
|
*/
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
if (debugAppState != null) {
|
if (debugAppState != null) {
|
||||||
stateManager.detach(debugAppState);
|
stateManager.detach(debugAppState);
|
||||||
@ -283,67 +433,106 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the threadingType
|
* Read which type of threading this app state uses.
|
||||||
|
*
|
||||||
|
* @return the threadingType (not null)
|
||||||
*/
|
*/
|
||||||
public ThreadingType getThreadingType() {
|
public ThreadingType getThreadingType() {
|
||||||
return threadingType;
|
return threadingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before attaching state
|
* Alter which type of threading this app state uses. Not allowed after
|
||||||
|
* attaching the app state.
|
||||||
*
|
*
|
||||||
* @param threadingType the threadingType to set
|
* @param threadingType the desired type (not null, default=SEQUENTIAL)
|
||||||
*/
|
*/
|
||||||
public void setThreadingType(ThreadingType threadingType) {
|
public void setThreadingType(ThreadingType threadingType) {
|
||||||
this.threadingType = threadingType;
|
this.threadingType = threadingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before attaching state
|
* Alter the broadphase type the physics space will use. Not allowed after
|
||||||
|
* attaching the app state.
|
||||||
|
*
|
||||||
|
* @param broadphaseType an enum value (not null, default=DBVT)
|
||||||
*/
|
*/
|
||||||
public void setBroadphaseType(BroadphaseType broadphaseType) {
|
public void setBroadphaseType(BroadphaseType broadphaseType) {
|
||||||
this.broadphaseType = broadphaseType;
|
this.broadphaseType = broadphaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before attaching state
|
* Alter the coordinate range. Not allowed after attaching the app state.
|
||||||
|
*
|
||||||
|
* @param worldMin the desired minimum coordinate values when using
|
||||||
|
* AXIS_SWEEP broadphase algorithms (not null, alias created,
|
||||||
|
* default=-10k,-10k,-10k)
|
||||||
*/
|
*/
|
||||||
public void setWorldMin(Vector3f worldMin) {
|
public void setWorldMin(Vector3f worldMin) {
|
||||||
this.worldMin = worldMin;
|
this.worldMin = worldMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before attaching state
|
* Alter the coordinate range. Not allowed after attaching the app state.
|
||||||
|
*
|
||||||
|
* @param worldMax the desired maximum coordinate values when using
|
||||||
|
* AXIS_SWEEP broadphase algorithms (not null, alias created,
|
||||||
|
* default=10k,10k,10k)
|
||||||
*/
|
*/
|
||||||
public void setWorldMax(Vector3f worldMax) {
|
public void setWorldMax(Vector3f worldMax) {
|
||||||
this.worldMax = worldMax;
|
this.worldMax = worldMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the simulation speed.
|
||||||
|
*
|
||||||
|
* @return speed (≥0, default=1)
|
||||||
|
*/
|
||||||
public float getSpeed() {
|
public float getSpeed() {
|
||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the simulation speed.
|
||||||
|
*
|
||||||
|
* @param speed the desired speed (≥0, default=1)
|
||||||
|
*/
|
||||||
public void setSpeed(float speed) {
|
public void setSpeed(float speed) {
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Callback from Bullet, invoked just before the physics is stepped. A good
|
||||||
|
* time to clear/apply forces.
|
||||||
|
*
|
||||||
|
* @param space the space that is about to be stepped (not null)
|
||||||
|
* @param f the time per physics step (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void prePhysicsTick(PhysicsSpace space, float f) {
|
public void prePhysicsTick(PhysicsSpace space, float f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback from Bullet, invoked just after the physics is stepped. A good
|
||||||
|
* time to clear/apply forces.
|
||||||
|
*
|
||||||
|
* @param space the space that is about to be stepped (not null)
|
||||||
|
* @param f the time per physics step (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void physicsTick(PhysicsSpace space, float f) {
|
public void physicsTick(PhysicsSpace space, float f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerate threading modes.
|
||||||
|
*/
|
||||||
public enum ThreadingType {
|
public enum ThreadingType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default mode; user update, physics update and rendering happen
|
* Default mode: user update, physics update, and rendering happen
|
||||||
* sequentially (single threaded)
|
* sequentially. (single threaded)
|
||||||
*/
|
*/
|
||||||
SEQUENTIAL,
|
SEQUENTIAL,
|
||||||
/**
|
/**
|
||||||
* Parallel threaded mode; physics update and rendering are executed in
|
* Parallel threaded mode: physics update and rendering are executed in
|
||||||
* parallel, update order is kept.<br/> Multiple BulletAppStates will
|
* parallel, update order is maintained.
|
||||||
* execute in parallel in this mode.
|
|
||||||
*/
|
*/
|
||||||
PARALLEL,
|
PARALLEL,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,22 +32,29 @@
|
|||||||
package com.jme3.bullet;
|
package com.jme3.bullet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this interface to be called from the physics thread on a physics update.
|
* Callback interface from the physics thread, used to clear/apply forces.
|
||||||
|
* <p>
|
||||||
|
* This interface is shared between JBullet and Native Bullet.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public interface PhysicsTickListener {
|
public interface PhysicsTickListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before the physics is actually stepped, use to apply forces etc.
|
* Callback from Bullet, invoked just before the physics is stepped. A good
|
||||||
* @param space the physics space
|
* time to clear/apply forces.
|
||||||
* @param tpf the time per frame in seconds
|
*
|
||||||
|
* @param space the space that is about to be stepped (not null)
|
||||||
|
* @param tpf the time per physics step (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
public void prePhysicsTick(PhysicsSpace space, float tpf);
|
public void prePhysicsTick(PhysicsSpace space, float tpf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after the physics has been stepped, use to check for forces etc.
|
* Callback from Bullet, invoked just after the physics has been stepped,
|
||||||
* @param space the physics space
|
* use to check for forces etc.
|
||||||
* @param tpf the time per frame in seconds
|
*
|
||||||
|
* @param space the space that was just stepped (not null)
|
||||||
|
* @param tpf the time per physics step (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
public void physicsTick(PhysicsSpace space, float tpf);
|
public void physicsTick(PhysicsSpace space, float tpf);
|
||||||
|
|
||||||
|
@ -32,18 +32,25 @@
|
|||||||
package com.jme3.bullet.collision;
|
package com.jme3.bullet.collision;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Interface to receive notifications whenever an object in a particular
|
||||||
|
* collision group is about to collide.
|
||||||
|
* <p>
|
||||||
|
* This interface is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public interface PhysicsCollisionGroupListener {
|
public interface PhysicsCollisionGroupListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when two physics objects of the registered group are about to collide, <i>called from physics thread</i>.<br>
|
* Invoked when two physics objects of the registered group are about to
|
||||||
* This is only called when the collision will happen based on the collisionGroup and collideWithGroups
|
* collide. <i>invoked on the physics thread</i>.<br>
|
||||||
* settings in the PhysicsCollisionObject. That is the case when <b>one</b> of the parties has the
|
* This is only invoked when the collision will happen based on the
|
||||||
* collisionGroup of the other in its collideWithGroups set.<br>
|
* collisionGroup and collideWithGroups settings in the
|
||||||
* @param nodeA CollisionObject #1
|
* PhysicsCollisionObject. That is the case when <b>one</b> of the parties
|
||||||
* @param nodeB CollisionObject #2
|
* has the collisionGroup of the other in its collideWithGroups set.
|
||||||
|
*
|
||||||
|
* @param nodeA collision object #1
|
||||||
|
* @param nodeB collision object #2
|
||||||
* @return true if the collision should happen, false otherwise
|
* @return true if the collision should happen, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean collide(PhysicsCollisionObject nodeA, PhysicsCollisionObject nodeB);
|
public boolean collide(PhysicsCollisionObject nodeA, PhysicsCollisionObject nodeB);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,16 +32,24 @@
|
|||||||
package com.jme3.bullet.collision;
|
package com.jme3.bullet.collision;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for Objects that want to be informed about collision events in the physics space
|
* Interface to receive notifications whenever an object in a particular physics
|
||||||
|
* space collides.
|
||||||
|
* <p>
|
||||||
|
* This interface is shared between JBullet and Native Bullet.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public interface PhysicsCollisionListener {
|
public interface PhysicsCollisionListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a collision happened in the PhysicsSpace, <i>called from render thread</i>.
|
* Invoked when a collision happened in the PhysicsSpace. <i>Invoked on the
|
||||||
*
|
* render thread.</i>
|
||||||
* Do not store the event object as it will be cleared after the method has finished.
|
* <p>
|
||||||
* @param event the CollisionEvent
|
* Do not retain the event object, as it will be reused after the
|
||||||
|
* collision() method returns. Copy any data you need during the collide()
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* @param event the event that occurred (not null, reusable)
|
||||||
*/
|
*/
|
||||||
public void collision(PhysicsCollisionEvent event);
|
public void collision(PhysicsCollisionEvent event);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,11 +34,22 @@ package com.jme3.bullet.collision;
|
|||||||
import com.jme3.animation.Bone;
|
import com.jme3.animation.Bone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Interface to receive notifications whenever a KinematicRagdollControl
|
||||||
|
* collides with another physics object.
|
||||||
|
* <p>
|
||||||
|
* This interface is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public interface RagdollCollisionListener {
|
public interface RagdollCollisionListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a collision involving a KinematicRagdollControl occurs.
|
||||||
|
*
|
||||||
|
* @param bone the ragdoll bone that collided (not null)
|
||||||
|
* @param object the collision object that collided with the bone (not null)
|
||||||
|
* @param event other event details (not null)
|
||||||
|
*/
|
||||||
public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event);
|
public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -39,24 +39,56 @@ import com.jme3.math.Vector3f;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* An element of a CompoundCollisionShape, consisting of a (non-compound) child
|
||||||
|
* shape, offset and rotated with respect to its parent.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class ChildCollisionShape implements Savable {
|
public class ChildCollisionShape implements Savable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translation relative to parent shape (not null)
|
||||||
|
*/
|
||||||
public Vector3f location;
|
public Vector3f location;
|
||||||
|
/**
|
||||||
|
* rotation relative to parent shape (not null)
|
||||||
|
*/
|
||||||
public Matrix3f rotation;
|
public Matrix3f rotation;
|
||||||
|
/**
|
||||||
|
* base shape (not null, not a compound shape)
|
||||||
|
*/
|
||||||
public CollisionShape shape;
|
public CollisionShape shape;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public ChildCollisionShape() {
|
public ChildCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a child shape for use in a compound shape.
|
||||||
|
*
|
||||||
|
* @param location translation relative to the parent (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param rotation rotation relative to the parent (not null, alias created)
|
||||||
|
* @param shape the base shape (not null, not a compound shape, alias
|
||||||
|
* created)
|
||||||
|
*/
|
||||||
public ChildCollisionShape(Vector3f location, Matrix3f rotation, CollisionShape shape) {
|
public ChildCollisionShape(Vector3f location, Matrix3f rotation, CollisionShape shape) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
this.shape = shape;
|
this.shape = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule capsule = ex.getCapsule(this);
|
OutputCapsule capsule = ex.getCapsule(this);
|
||||||
capsule.write(location, "location", new Vector3f());
|
capsule.write(location, "location", new Vector3f());
|
||||||
@ -64,6 +96,12 @@ public class ChildCollisionShape implements Savable {
|
|||||||
capsule.write(shape, "shape", new BoxCollisionShape(new Vector3f(1, 1, 1)));
|
capsule.write(shape, "shape", new BoxCollisionShape(new Vector3f(1, 1, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
location = (Vector3f) capsule.readSavable("location", new Vector3f());
|
location = (Vector3f) capsule.readSavable("location", new Vector3f());
|
||||||
|
@ -47,82 +47,113 @@ import com.jme3.util.clone.JmeCloneable;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractPhysicsControl manages the lifecycle of a physics object that is
|
* Manage the life cycle of a physics object linked to a spatial in a scene
|
||||||
* attached to a spatial in the SceneGraph.
|
* graph.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPhysicsControl implements PhysicsControl, JmeCloneable {
|
public abstract class AbstractPhysicsControl implements PhysicsControl, JmeCloneable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* temporary storage during calculations
|
||||||
|
*/
|
||||||
private final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
private final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* spatial to which this control is added, or null if none
|
||||||
|
*/
|
||||||
protected Spatial spatial;
|
protected Spatial spatial;
|
||||||
|
/**
|
||||||
|
* true→control is enabled, false→control is disabled
|
||||||
|
*/
|
||||||
protected boolean enabled = true;
|
protected boolean enabled = true;
|
||||||
|
/**
|
||||||
|
* true→body is added to the physics space, false→not added
|
||||||
|
*/
|
||||||
protected boolean added = false;
|
protected boolean added = false;
|
||||||
|
/**
|
||||||
|
* space to which the physics object is (or would be) added
|
||||||
|
*/
|
||||||
protected PhysicsSpace space = null;
|
protected PhysicsSpace space = null;
|
||||||
|
/**
|
||||||
|
* true → physics coordinates match local transform, false →
|
||||||
|
* physics coordinates match world transform
|
||||||
|
*/
|
||||||
protected boolean applyLocal = false;
|
protected boolean applyLocal = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the control is added to a new spatial, create any
|
* Create spatial-dependent data. Invoked when this control is added to a
|
||||||
* spatial-dependent data here.
|
* spatial.
|
||||||
*
|
*
|
||||||
* @param spat The new spatial, guaranteed not to be null
|
* @param spat the controlled spatial (not null)
|
||||||
*/
|
*/
|
||||||
protected abstract void createSpatialData(Spatial spat);
|
protected abstract void createSpatialData(Spatial spat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the control is removed from a spatial, remove any
|
* Destroy spatial-dependent data. Invoked when this control is removed from
|
||||||
* spatial-dependent data here.
|
* a spatial.
|
||||||
*
|
*
|
||||||
* @param spat The old spatial, guaranteed not to be null
|
* @param spat the previously controlled spatial (not null)
|
||||||
*/
|
*/
|
||||||
protected abstract void removeSpatialData(Spatial spat);
|
protected abstract void removeSpatialData(Spatial spat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the physics object is supposed to move to the spatial
|
* Translate the physics object to the specified location.
|
||||||
* position.
|
|
||||||
*
|
*
|
||||||
* @param vec
|
* @param vec desired location (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
protected abstract void setPhysicsLocation(Vector3f vec);
|
protected abstract void setPhysicsLocation(Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the physics object is supposed to move to the spatial
|
* Rotate the physics object to the specified orientation.
|
||||||
* rotation.
|
|
||||||
*
|
*
|
||||||
* @param quat
|
* @param quat desired orientation (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
protected abstract void setPhysicsRotation(Quaternion quat);
|
protected abstract void setPhysicsRotation(Quaternion quat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the physics object is supposed to add all objects it needs to
|
* Add all managed physics objects to the specified space.
|
||||||
* manage to the physics space.
|
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space which physics space to add to (not null)
|
||||||
*/
|
*/
|
||||||
protected abstract void addPhysics(PhysicsSpace space);
|
protected abstract void addPhysics(PhysicsSpace space);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the physics object is supposed to remove all objects added to
|
* Remove all managed physics objects from the specified space.
|
||||||
* the physics space.
|
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space which physics space to remove from (not null)
|
||||||
*/
|
*/
|
||||||
protected abstract void removePhysics(PhysicsSpace space);
|
protected abstract void removePhysics(PhysicsSpace space);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether physics-space coordinates should match the spatial's local
|
||||||
|
* coordinates.
|
||||||
|
*
|
||||||
|
* @return true if matching local coordinates, false if matching world
|
||||||
|
* coordinates
|
||||||
|
*/
|
||||||
public boolean isApplyPhysicsLocal() {
|
public boolean isApplyPhysicsLocal() {
|
||||||
return applyLocal;
|
return applyLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to true, the physics coordinates will be applied to the local
|
* Alter whether physics-space coordinates should match the spatial's local
|
||||||
* translation of the Spatial
|
* coordinates.
|
||||||
*
|
*
|
||||||
* @param applyPhysicsLocal
|
* @param applyPhysicsLocal true→match local coordinates,
|
||||||
|
* false→match world coordinates (default=false)
|
||||||
*/
|
*/
|
||||||
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
||||||
applyLocal = applyPhysicsLocal;
|
applyLocal = applyPhysicsLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access whichever spatial translation corresponds to the physics location.
|
||||||
|
*
|
||||||
|
* @return the pre-existing location vector (in physics-space coordinates,
|
||||||
|
* not null)
|
||||||
|
*/
|
||||||
protected Vector3f getSpatialTranslation() {
|
protected Vector3f getSpatialTranslation() {
|
||||||
if (applyLocal) {
|
if (applyLocal) {
|
||||||
return spatial.getLocalTranslation();
|
return spatial.getLocalTranslation();
|
||||||
@ -130,6 +161,12 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
return spatial.getWorldTranslation();
|
return spatial.getWorldTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access whichever spatial rotation corresponds to the physics rotation.
|
||||||
|
*
|
||||||
|
* @return the pre-existing quaternion (in physics-space coordinates, not
|
||||||
|
* null)
|
||||||
|
*/
|
||||||
protected Quaternion getSpatialRotation() {
|
protected Quaternion getSpatialRotation() {
|
||||||
if (applyLocal) {
|
if (applyLocal) {
|
||||||
return spatial.getLocalRotation();
|
return spatial.getLocalRotation();
|
||||||
@ -138,10 +175,12 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a physics transform to the spatial
|
* Apply a physics transform to the spatial.
|
||||||
*
|
*
|
||||||
* @param worldLocation
|
* @param worldLocation location vector (in physics-space coordinates, not
|
||||||
* @param worldRotation
|
* null, unaffected)
|
||||||
|
* @param worldRotation orientation (in physics-space coordinates, not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation) {
|
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation) {
|
||||||
if (enabled && spatial != null) {
|
if (enabled && spatial != null) {
|
||||||
@ -170,12 +209,28 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
|
||||||
|
* shallow-cloned control into a deep-cloned one, using the specified cloner
|
||||||
|
* and original to resolve copied fields.
|
||||||
|
*
|
||||||
|
* @param cloner the cloner currently cloning this control (not null)
|
||||||
|
* @param original the control from which this control was shallow-cloned
|
||||||
|
* (unused)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void cloneFields( Cloner cloner, Object original ) {
|
public void cloneFields( Cloner cloner, Object original ) {
|
||||||
this.spatial = cloner.clone(spatial);
|
this.spatial = cloner.clone(spatial);
|
||||||
createSpatialData(this.spatial);
|
createSpatialData(this.spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (this.spatial != null && this.spatial != spatial) {
|
if (this.spatial != null && this.spatial != spatial) {
|
||||||
removeSpatialData(this.spatial);
|
removeSpatialData(this.spatial);
|
||||||
@ -191,6 +246,15 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
setPhysicsRotation(getSpatialRotation());
|
setPhysicsRotation(getSpatialRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable this control.
|
||||||
|
* <p>
|
||||||
|
* When the control is disabled, the physics object is removed from physics
|
||||||
|
* space. When the control is enabled again, the physics object is moved to
|
||||||
|
* the spatial's location and then added to the physics space.
|
||||||
|
*
|
||||||
|
* @param enabled true→enable the control, false→disable it
|
||||||
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
if (space != null) {
|
if (space != null) {
|
||||||
@ -208,6 +272,11 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this control is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
@ -221,7 +290,7 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
/**
|
/**
|
||||||
* If enabled, add this control's physics object to the specified physics
|
* If enabled, add this control's physics object to the specified physics
|
||||||
* space. If not enabled, alter where the object would be added. The object
|
* space. If not enabled, alter where the object would be added. The object
|
||||||
* is removed from any other space it's currently in.
|
* is removed from any other space it's in.
|
||||||
*
|
*
|
||||||
* @param newSpace where to add, or null to simply remove
|
* @param newSpace where to add, or null to simply remove
|
||||||
*/
|
*/
|
||||||
@ -245,10 +314,21 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
space = newSpace;
|
space = newSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the physics space to which the object is (or would be) added.
|
||||||
|
*
|
||||||
|
* @return the pre-existing space, or null for none
|
||||||
|
*/
|
||||||
public PhysicsSpace getPhysicsSpace() {
|
public PhysicsSpace getPhysicsSpace() {
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this object, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
@ -257,6 +337,13 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
|
|||||||
oc.write(spatial, "spatial", null);
|
oc.write(spatial, "spatial", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this control from the specified importer, for example when
|
||||||
|
* loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
|
@ -56,15 +56,18 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is intended to be a replacement for the internal bullet character class.
|
* This class is intended to replace the CharacterControl class.
|
||||||
* A RigidBody with cylinder collision shape is used and its velocity is set
|
* <p>
|
||||||
* continuously, a ray test is used to check if the character is on the ground.
|
* A rigid body with cylinder collision shape is used and its velocity is set
|
||||||
*
|
* continuously. A ray test is used to test whether the character is on the
|
||||||
* The character keeps his own local coordinate system which adapts based on the
|
* ground.
|
||||||
* gravity working on the character so the character will always stand upright.
|
* <p>
|
||||||
*
|
* The character keeps their own local coordinate system which adapts based on
|
||||||
* Forces in the local x/z plane are dampened while those in the local y
|
* the gravity working on the character so they will always stand upright.
|
||||||
* direction are applied fully (e.g. jumping, falling).
|
* <p>
|
||||||
|
* Motion in the local X-Z plane is damped.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
@ -74,10 +77,16 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
protected PhysicsRigidBody rigidBody;
|
protected PhysicsRigidBody rigidBody;
|
||||||
protected float radius;
|
protected float radius;
|
||||||
protected float height;
|
protected float height;
|
||||||
|
/**
|
||||||
|
* mass of this character (>0)
|
||||||
|
*/
|
||||||
protected float mass;
|
protected float mass;
|
||||||
|
/**
|
||||||
|
* relative height when ducked (1=full height)
|
||||||
|
*/
|
||||||
protected float duckedFactor = 0.6f;
|
protected float duckedFactor = 0.6f;
|
||||||
/**
|
/**
|
||||||
* Local up direction, derived from gravity.
|
* local up direction, derived from gravity
|
||||||
*/
|
*/
|
||||||
protected final Vector3f localUp = new Vector3f(0, 1, 0);
|
protected final Vector3f localUp = new Vector3f(0, 1, 0);
|
||||||
/**
|
/**
|
||||||
@ -94,22 +103,27 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
*/
|
*/
|
||||||
protected final Quaternion localForwardRotation = new Quaternion(Quaternion.DIRECTION_Z);
|
protected final Quaternion localForwardRotation = new Quaternion(Quaternion.DIRECTION_Z);
|
||||||
/**
|
/**
|
||||||
* Is a z-forward vector based on the view direction and the current local
|
* a Z-forward vector based on the view direction and the local X-Z plane.
|
||||||
* x/z plane.
|
|
||||||
*/
|
*/
|
||||||
protected final Vector3f viewDirection = new Vector3f(0, 0, 1);
|
protected final Vector3f viewDirection = new Vector3f(0, 0, 1);
|
||||||
/**
|
/**
|
||||||
* Stores final spatial location, corresponds to RigidBody location.
|
* spatial location, corresponds to RigidBody location.
|
||||||
*/
|
*/
|
||||||
protected final Vector3f location = new Vector3f();
|
protected final Vector3f location = new Vector3f();
|
||||||
/**
|
/**
|
||||||
* Stores final spatial rotation, is a z-forward rotation based on the view
|
* spatial rotation, a Z-forward rotation based on the view direction and
|
||||||
* direction and the current local x/z plane. See also rotatedViewDirection.
|
* local X-Z plane.
|
||||||
|
*
|
||||||
|
* @see #rotatedViewDirection
|
||||||
*/
|
*/
|
||||||
protected final Quaternion rotation = new Quaternion(Quaternion.DIRECTION_Z);
|
protected final Quaternion rotation = new Quaternion(Quaternion.DIRECTION_Z);
|
||||||
protected final Vector3f rotatedViewDirection = new Vector3f(0, 0, 1);
|
protected final Vector3f rotatedViewDirection = new Vector3f(0, 0, 1);
|
||||||
protected final Vector3f walkDirection = new Vector3f();
|
protected final Vector3f walkDirection = new Vector3f();
|
||||||
protected final Vector3f jumpForce;
|
protected final Vector3f jumpForce;
|
||||||
|
/**
|
||||||
|
* X-Z motion damping factor (0→no damping, 1=no external forces,
|
||||||
|
* default=0.9)
|
||||||
|
*/
|
||||||
protected float physicsDamping = 0.9f;
|
protected float physicsDamping = 0.9f;
|
||||||
protected final Vector3f scale = new Vector3f(1, 1, 1);
|
protected final Vector3f scale = new Vector3f(1, 1, 1);
|
||||||
protected final Vector3f velocity = new Vector3f();
|
protected final Vector3f velocity = new Vector3f();
|
||||||
@ -119,20 +133,23 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
protected boolean wantToUnDuck = false;
|
protected boolean wantToUnDuck = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only used for serialization, do not use this constructor.
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
*/
|
*/
|
||||||
public BetterCharacterControl() {
|
public BetterCharacterControl() {
|
||||||
jumpForce = new Vector3f();
|
jumpForce = new Vector3f();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new character with the given properties. Note that to avoid
|
* Instantiate an enabled control with the specified properties.
|
||||||
* issues the final height when ducking should be larger than 2x radius. The
|
* <p>
|
||||||
* jumpForce will be set to an upwards force of 5x mass.
|
* The final height when ducking must be larger than 2x radius. The
|
||||||
|
* jumpForce will be set to an upward force of 5x mass.
|
||||||
*
|
*
|
||||||
* @param radius
|
* @param radius the radius of the character's collision shape (>0)
|
||||||
* @param height
|
* @param height the height of the character's collision shape
|
||||||
* @param mass
|
* (>2*radius)
|
||||||
|
* @param mass the character's mass (≥0)
|
||||||
*/
|
*/
|
||||||
public BetterCharacterControl(float radius, float height, float mass) {
|
public BetterCharacterControl(float radius, float height, float mass) {
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
@ -143,6 +160,13 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
rigidBody.setAngularFactor(0);
|
rigidBody.setAngularFactor(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is added to a scene graph. Do not invoke
|
||||||
|
* directly from user code.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
super.update(tpf);
|
super.update(tpf);
|
||||||
@ -151,16 +175,24 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
applyPhysicsTransform(location, rotation);
|
applyPhysicsTransform(location, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per view port per frame, provided the
|
||||||
|
* control is added to a scene. Should be invoked only by a subclass or by
|
||||||
|
* the RenderManager.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(RenderManager rm, ViewPort vp) {
|
public void render(RenderManager rm, ViewPort vp) {
|
||||||
super.render(rm, vp);
|
super.render(rm, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally, don't call manually
|
* Callback from Bullet, invoked just before the physics is stepped.
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space the space that is about to be stepped (not null)
|
||||||
* @param tpf
|
* @param tpf the time per physics step (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
public void prePhysicsTick(PhysicsSpace space, float tpf) {
|
public void prePhysicsTick(PhysicsSpace space, float tpf) {
|
||||||
checkOnGround();
|
checkOnGround();
|
||||||
@ -172,8 +204,8 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
|
|
||||||
Vector3f currentVelocity = vars.vect2.set(velocity);
|
Vector3f currentVelocity = vars.vect2.set(velocity);
|
||||||
|
|
||||||
// dampen existing x/z forces
|
// Attenuate any existing X-Z motion.
|
||||||
float existingLeftVelocity = velocity.dot(localLeft);
|
float existingLeftVelocity = velocity.dot(localLeft);
|
||||||
float existingForwardVelocity = velocity.dot(localForward);
|
float existingForwardVelocity = velocity.dot(localForward);
|
||||||
Vector3f counter = vars.vect1;
|
Vector3f counter = vars.vect1;
|
||||||
@ -208,20 +240,20 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally, don't call manually
|
* Callback from Bullet, invoked just after the physics has been stepped.
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space the space that was just stepped (not null)
|
||||||
* @param tpf
|
* @param tpf the time per physics step (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
public void physicsTick(PhysicsSpace space, float tpf) {
|
public void physicsTick(PhysicsSpace space, float tpf) {
|
||||||
rigidBody.getLinearVelocity(velocity);
|
rigidBody.getLinearVelocity(velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the character somewhere. Note the character also takes the location
|
* Move the character somewhere. Note the character also warps to the
|
||||||
* of any spatial its being attached to in the moment it is attached.
|
* location of the spatial when the control is added.
|
||||||
*
|
*
|
||||||
* @param vec The new character location.
|
* @param vec the desired character location (not null)
|
||||||
*/
|
*/
|
||||||
public void warp(Vector3f vec) {
|
public void warp(Vector3f vec) {
|
||||||
setPhysicsLocation(vec);
|
setPhysicsLocation(vec);
|
||||||
@ -239,21 +271,20 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the jump force as a Vector3f. The jump force is local to the
|
* Alter the jump force. The jump force is local to the character's
|
||||||
* characters coordinate system, which normally is always z-forward (in
|
* coordinate system, which normally is always z-forward (in world
|
||||||
* world coordinates, parent coordinates when set to applyLocalPhysics)
|
* coordinates, parent coordinates when set to applyLocalPhysics)
|
||||||
*
|
*
|
||||||
* @param jumpForce The new jump force
|
* @param jumpForce the desired jump force (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setJumpForce(Vector3f jumpForce) {
|
public void setJumpForce(Vector3f jumpForce) {
|
||||||
this.jumpForce.set(jumpForce);
|
this.jumpForce.set(jumpForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current jump force. The default is 5 * character mass in y
|
* Access the jump force. The default is 5 * character mass in Y direction.
|
||||||
* direction.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return the pre-existing vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getJumpForce() {
|
public Vector3f getJumpForce() {
|
||||||
return jumpForce;
|
return jumpForce;
|
||||||
@ -264,7 +295,7 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
* in the center of the character and might return false even if the
|
* in the center of the character and might return false even if the
|
||||||
* character is not falling yet.
|
* character is not falling yet.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if on the ground, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isOnGround() {
|
public boolean isOnGround() {
|
||||||
return onGround;
|
return onGround;
|
||||||
@ -277,7 +308,7 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
* can in fact unduck and only do so when its possible. You can check the
|
* can in fact unduck and only do so when its possible. You can check the
|
||||||
* state of the unducking by checking isDucked().
|
* state of the unducking by checking isDucked().
|
||||||
*
|
*
|
||||||
* @param enabled
|
* @param enabled true→duck, false→unduck
|
||||||
*/
|
*/
|
||||||
public void setDucked(boolean enabled) {
|
public void setDucked(boolean enabled) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
@ -298,33 +329,33 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
* Check if the character is ducking, either due to user input or due to
|
* Check if the character is ducking, either due to user input or due to
|
||||||
* unducking being impossible at the moment (obstacle above).
|
* unducking being impossible at the moment (obstacle above).
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if ducking, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isDucked() {
|
public boolean isDucked() {
|
||||||
return ducked;
|
return ducked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the height multiplication factor for ducking.
|
* Alter the height multiplier for ducking.
|
||||||
*
|
*
|
||||||
* @param factor The factor by which the height should be multiplied when
|
* @param factor the factor by which the height should be multiplied when
|
||||||
* ducking
|
* ducking (≥0, ≤1)
|
||||||
*/
|
*/
|
||||||
public void setDuckedFactor(float factor) {
|
public void setDuckedFactor(float factor) {
|
||||||
duckedFactor = factor;
|
duckedFactor = factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the height multiplication factor for ducking.
|
* Read the height multiplier for ducking.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the factor (≥0, ≤1)
|
||||||
*/
|
*/
|
||||||
public float getDuckedFactor() {
|
public float getDuckedFactor() {
|
||||||
return duckedFactor;
|
return duckedFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the walk direction of the character. This parameter is framerate
|
* Alter the character's the walk direction. This parameter is framerate
|
||||||
* independent and the character will move continuously in the direction
|
* independent and the character will move continuously in the direction
|
||||||
* given by the vector with the speed given by the vector length in m/s.
|
* given by the vector with the speed given by the vector length in m/s.
|
||||||
*
|
*
|
||||||
@ -335,20 +366,19 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current walk direction and speed of the character. The length of
|
* Read the walk velocity. The length of the vector defines the speed.
|
||||||
* the vector defines the speed.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return the pre-existing vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getWalkDirection() {
|
public Vector3f getWalkDirection() {
|
||||||
return walkDirection;
|
return walkDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the view direction for the character. Note this only defines the
|
* Alter the character's view direction. Note this only defines the
|
||||||
* rotation of the spatial in the local x/z plane of the character.
|
* orientation in the local X-Z plane.
|
||||||
*
|
*
|
||||||
* @param vec
|
* @param vec a direction vector (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setViewDirection(Vector3f vec) {
|
public void setViewDirection(Vector3f vec) {
|
||||||
viewDirection.set(vec);
|
viewDirection.set(vec);
|
||||||
@ -356,10 +386,10 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current view direction, note this doesn't need to correspond
|
* Access the view direction. This need not agree with the spatial's forward
|
||||||
* with the spatials forward direction.
|
* direction.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the pre-existing vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getViewDirection() {
|
public Vector3f getViewDirection() {
|
||||||
return viewDirection;
|
return viewDirection;
|
||||||
@ -367,15 +397,15 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Realign the local forward vector to given direction vector, if null is
|
* Realign the local forward vector to given direction vector, if null is
|
||||||
* supplied Vector3f.UNIT_Z is used. Input vector has to be perpendicular to
|
* supplied Vector3f.UNIT_Z is used. The input vector must be perpendicular
|
||||||
* current gravity vector. This normally only needs to be called when the
|
* to gravity vector. This normally only needs to be invoked when the
|
||||||
* gravity direction changed continuously and the local forward vector is
|
* gravity direction changed continuously and the local forward vector is
|
||||||
* off due to drift. E.g. after walking around on a sphere "planet" for a
|
* off due to drift. E.g. after walking around on a sphere "planet" for a
|
||||||
* while and then going back to a y-up coordinate system the local z-forward
|
* while and then going back to a Y-up coordinate system the local Z-forward
|
||||||
* might not be 100% alinged with Z axis.
|
* might not be 100% aligned with the Z axis.
|
||||||
*
|
*
|
||||||
* @param vec The new forward vector, has to be perpendicular to the current
|
* @param vec the desired forward vector (perpendicular to the gravity
|
||||||
* gravity vector!
|
* vector, may be null, default=0,0,1)
|
||||||
*/
|
*/
|
||||||
public void resetForward(Vector3f vec) {
|
public void resetForward(Vector3f vec) {
|
||||||
if (vec == null) {
|
if (vec == null) {
|
||||||
@ -386,23 +416,21 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current linear velocity along the three axes of the character.
|
* Access the character's linear velocity in physics-space coordinates.
|
||||||
* This is prepresented in world coordinates, parent coordinates when the
|
|
||||||
* control is set to applyLocalPhysics.
|
|
||||||
*
|
*
|
||||||
* @return The current linear velocity of the character
|
* @return the pre-existing vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getVelocity() {
|
public Vector3f getVelocity() {
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the gravity for this character. Note that this also realigns the
|
* Alter the gravity acting on this character. Note that this also realigns
|
||||||
* local coordinate system of the character so that continuous changes in
|
* the local coordinate system of the character so that continuous changes
|
||||||
* gravity direction are possible while maintaining a sensible control over
|
* in gravity direction are possible while maintaining a sensible control
|
||||||
* the character.
|
* over the character.
|
||||||
*
|
*
|
||||||
* @param gravity
|
* @param gravity an acceleration vector (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setGravity(Vector3f gravity) {
|
public void setGravity(Vector3f gravity) {
|
||||||
rigidBody.setGravity(gravity);
|
rigidBody.setGravity(gravity);
|
||||||
@ -411,46 +439,48 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current gravity of the character.
|
* Copy the character's gravity vector.
|
||||||
*
|
*
|
||||||
* @return
|
* @return a new acceleration vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getGravity() {
|
public Vector3f getGravity() {
|
||||||
return rigidBody.getGravity();
|
return rigidBody.getGravity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current gravity of the character.
|
* Copy the character's gravity vector.
|
||||||
*
|
*
|
||||||
* @param store The vector to store the result in
|
* @param store storage for the result (modified if not null)
|
||||||
* @return
|
* @return an acceleration vector (either the provided storage or a new
|
||||||
|
* vector, not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getGravity(Vector3f store) {
|
public Vector3f getGravity(Vector3f store) {
|
||||||
return rigidBody.getGravity(store);
|
return rigidBody.getGravity(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets how much the physics forces in the local x/z plane should be
|
* Alter how much motion in the local X-Z plane is damped.
|
||||||
* dampened.
|
*
|
||||||
* @param physicsDamping The dampening value, 0 = no dampening, 1 = no external force, default = 0.9
|
* @param physicsDamping the desired damping factor (0→no damping, 1=no
|
||||||
|
* external forces, default=0.9)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsDamping(float physicsDamping) {
|
public void setPhysicsDamping(float physicsDamping) {
|
||||||
this.physicsDamping = physicsDamping;
|
this.physicsDamping = physicsDamping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets how much the physics forces in the local x/z plane should be
|
* Read how much motion in the local X-Z plane is damped.
|
||||||
* dampened.
|
*
|
||||||
|
* @return the damping factor (0→no damping, 1=no external forces)
|
||||||
*/
|
*/
|
||||||
public float getPhysicsDamping() {
|
public float getPhysicsDamping() {
|
||||||
return physicsDamping;
|
return physicsDamping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This actually sets a new collision shape to the character to change the
|
* Alter the height of collision shape.
|
||||||
* height of the capsule.
|
|
||||||
*
|
*
|
||||||
* @param percent
|
* @param percent the desired height, as a percentage of the full height
|
||||||
*/
|
*/
|
||||||
protected void setHeightPercent(float percent) {
|
protected void setHeightPercent(float percent) {
|
||||||
scale.setY(percent);
|
scale.setY(percent);
|
||||||
@ -458,7 +488,7 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This checks if the character is on the ground by doing a ray test.
|
* Test whether the character is on the ground, by means of a ray test.
|
||||||
*/
|
*/
|
||||||
protected void checkOnGround() {
|
protected void checkOnGround() {
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
@ -499,12 +529,10 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a new collision shape based on the current scale parameter. The
|
* Create a collision shape based on the scale parameter. The new shape is a
|
||||||
* created collisionshape is a capsule collision shape that is attached to a
|
* compound shape containing an offset capsule.
|
||||||
* compound collision shape with an offset to set the object center at the
|
|
||||||
* bottom of the capsule.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return a new compound shape (not null)
|
||||||
*/
|
*/
|
||||||
protected CollisionShape getShape() {
|
protected CollisionShape getShape() {
|
||||||
//TODO: cleanup size mess..
|
//TODO: cleanup size mess..
|
||||||
@ -516,18 +544,18 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the scaled height.
|
* Calculate the character's scaled height.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the height
|
||||||
*/
|
*/
|
||||||
protected float getFinalHeight() {
|
protected float getFinalHeight() {
|
||||||
return height * scale.getY();
|
return height * scale.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the scaled radius.
|
* Calculate the character's scaled radius.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the radius
|
||||||
*/
|
*/
|
||||||
protected float getFinalRadius() {
|
protected float getFinalRadius() {
|
||||||
return radius * scale.getZ();
|
return radius * scale.getZ();
|
||||||
@ -536,7 +564,7 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
/**
|
/**
|
||||||
* Updates the local coordinate system from the localForward and localUp
|
* Updates the local coordinate system from the localForward and localUp
|
||||||
* vectors, adapts localForward, sets localForwardRotation quaternion to
|
* vectors, adapts localForward, sets localForwardRotation quaternion to
|
||||||
* local z-forward rotation.
|
* local Z-forward rotation.
|
||||||
*/
|
*/
|
||||||
protected void updateLocalCoordinateSystem() {
|
protected void updateLocalCoordinateSystem() {
|
||||||
//gravity vector has possibly changed, calculate new world forward (UNIT_Z)
|
//gravity vector has possibly changed, calculate new world forward (UNIT_Z)
|
||||||
@ -547,8 +575,8 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the local x/z-flattened view direction and the corresponding
|
* Updates the local X-Z view direction and the corresponding rotation
|
||||||
* rotation quaternion for the spatial.
|
* quaternion for the spatial.
|
||||||
*/
|
*/
|
||||||
protected void updateLocalViewDirection() {
|
protected void updateLocalViewDirection() {
|
||||||
//update local rotation quaternion to use for view rotation
|
//update local rotation quaternion to use for view rotation
|
||||||
@ -568,7 +596,6 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
* set to the new direction
|
* set to the new direction
|
||||||
* @param worldUpVector The up vector to use, the result direction will be
|
* @param worldUpVector The up vector to use, the result direction will be
|
||||||
* perpendicular to this
|
* perpendicular to this
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
protected final void calculateNewForward(Quaternion rotation, Vector3f direction, Vector3f worldUpVector) {
|
protected final void calculateNewForward(Quaternion rotation, Vector3f direction, Vector3f worldUpVector) {
|
||||||
if (direction == null) {
|
if (direction == null) {
|
||||||
@ -600,10 +627,9 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is implemented from AbstractPhysicsControl and called when the
|
* Translate the character to the specified location.
|
||||||
* spatial is attached for example.
|
|
||||||
*
|
*
|
||||||
* @param vec
|
* @param vec desired location (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void setPhysicsLocation(Vector3f vec) {
|
protected void setPhysicsLocation(Vector3f vec) {
|
||||||
@ -612,12 +638,12 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is implemented from AbstractPhysicsControl and called when the
|
* Rotate the physics object to the specified orientation.
|
||||||
* spatial is attached for example. We don't set the actual physics rotation
|
* <p>
|
||||||
* but the view rotation here. It might actually be altered by the
|
* We don't set the actual physics rotation but the view rotation here. It
|
||||||
* calculateNewForward method.
|
* might actually be altered by the calculateNewForward method.
|
||||||
*
|
*
|
||||||
* @param quat
|
* @param quat desired orientation (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void setPhysicsRotation(Quaternion quat) {
|
protected void setPhysicsRotation(Quaternion quat) {
|
||||||
@ -627,10 +653,9 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is implemented from AbstractPhysicsControl and called when the
|
* Add all managed physics objects to the specified space.
|
||||||
* control is supposed to add all objects to the physics space.
|
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space which physics space to add to (not null)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void addPhysics(PhysicsSpace space) {
|
protected void addPhysics(PhysicsSpace space) {
|
||||||
@ -642,10 +667,9 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is implemented from AbstractPhysicsControl and called when the
|
* Remove all managed physics objects from the specified space.
|
||||||
* control is supposed to remove all objects from the physics space.
|
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space which physics space to remove from (not null)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void removePhysics(PhysicsSpace space) {
|
protected void removePhysics(PhysicsSpace space) {
|
||||||
@ -653,16 +677,33 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
space.removeTickListener(this);
|
space.removeTickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create spatial-dependent data. Invoked when this control is added to a
|
||||||
|
* spatial.
|
||||||
|
*
|
||||||
|
* @param spat the controlled spatial (not null, alias created)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void createSpatialData(Spatial spat) {
|
protected void createSpatialData(Spatial spat) {
|
||||||
rigidBody.setUserObject(spatial);
|
rigidBody.setUserObject(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy spatial-dependent data. Invoked when this control is removed from
|
||||||
|
* a spatial.
|
||||||
|
*
|
||||||
|
* @param spat the previously controlled spatial (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void removeSpatialData(Spatial spat) {
|
protected void removeSpatialData(Spatial spat) {
|
||||||
rigidBody.setUserObject(null);
|
rigidBody.setUserObject(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a shallow clone for the JME cloner.
|
||||||
|
*
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object jmeClone() {
|
public Object jmeClone() {
|
||||||
BetterCharacterControl control = new BetterCharacterControl(radius, height, mass);
|
BetterCharacterControl control = new BetterCharacterControl(radius, height, mass);
|
||||||
@ -671,6 +712,12 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this control, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -682,6 +729,12 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
|
|||||||
oc.write(physicsDamping, "physicsDamping", 0.9f);
|
oc.write(physicsDamping, "physicsDamping", 0.9f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this control, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
|
@ -49,38 +49,82 @@ import com.jme3.util.clone.JmeCloneable;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GhostControl moves with the spatial it is attached to and can be used to check
|
* A physics control to link a PhysicsGhostObject to a spatial.
|
||||||
* overlaps with other physics objects (e.g. aggro radius).
|
* <p>
|
||||||
|
* The ghost object moves with the spatial it is attached to and can be used to
|
||||||
|
* detect overlaps with other physics objects (e.g. aggro radius).
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class GhostControl extends PhysicsGhostObject implements PhysicsControl, JmeCloneable {
|
public class GhostControl extends PhysicsGhostObject implements PhysicsControl, JmeCloneable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spatial to which this control is added, or null if none
|
||||||
|
*/
|
||||||
protected Spatial spatial;
|
protected Spatial spatial;
|
||||||
|
/**
|
||||||
|
* true→control is enabled, false→control is disabled
|
||||||
|
*/
|
||||||
protected boolean enabled = true;
|
protected boolean enabled = true;
|
||||||
|
/**
|
||||||
|
* true→body is added to the physics space, false→not added
|
||||||
|
*/
|
||||||
protected boolean added = false;
|
protected boolean added = false;
|
||||||
|
/**
|
||||||
|
* space to which the ghost object is (or would be) added
|
||||||
|
*/
|
||||||
protected PhysicsSpace space = null;
|
protected PhysicsSpace space = null;
|
||||||
|
/**
|
||||||
|
* true → physics coordinates match local transform, false →
|
||||||
|
* physics coordinates match world transform
|
||||||
|
*/
|
||||||
protected boolean applyLocal = false;
|
protected boolean applyLocal = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public GhostControl() {
|
public GhostControl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control with the specified shape.
|
||||||
|
*
|
||||||
|
* @param shape (not null)
|
||||||
|
*/
|
||||||
public GhostControl(CollisionShape shape) {
|
public GhostControl(CollisionShape shape) {
|
||||||
super(shape);
|
super(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether physics-space coordinates should match the spatial's local
|
||||||
|
* coordinates.
|
||||||
|
*
|
||||||
|
* @return true if matching local coordinates, false if matching world
|
||||||
|
* coordinates
|
||||||
|
*/
|
||||||
public boolean isApplyPhysicsLocal() {
|
public boolean isApplyPhysicsLocal() {
|
||||||
return applyLocal;
|
return applyLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to true, the physics coordinates will be applied to the local
|
* Alter whether physics-space coordinates should match the spatial's local
|
||||||
* translation of the Spatial
|
* coordinates.
|
||||||
* @param applyPhysicsLocal
|
*
|
||||||
|
* @param applyPhysicsLocal true→match local coordinates,
|
||||||
|
* false→match world coordinates (default=false)
|
||||||
*/
|
*/
|
||||||
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
||||||
applyLocal = applyPhysicsLocal;
|
applyLocal = applyPhysicsLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access whichever spatial translation corresponds to the physics location.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null)
|
||||||
|
*/
|
||||||
private Vector3f getSpatialTranslation() {
|
private Vector3f getSpatialTranslation() {
|
||||||
if (applyLocal) {
|
if (applyLocal) {
|
||||||
return spatial.getLocalTranslation();
|
return spatial.getLocalTranslation();
|
||||||
@ -88,6 +132,11 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
return spatial.getWorldTranslation();
|
return spatial.getWorldTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access whichever spatial rotation corresponds to the physics rotation.
|
||||||
|
*
|
||||||
|
* @return the pre-existing quaternion (not null)
|
||||||
|
*/
|
||||||
private Quaternion getSpatialRotation() {
|
private Quaternion getSpatialRotation() {
|
||||||
if (applyLocal) {
|
if (applyLocal) {
|
||||||
return spatial.getLocalRotation();
|
return spatial.getLocalRotation();
|
||||||
@ -95,12 +144,23 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
return spatial.getWorldRotation();
|
return spatial.getWorldRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone this control for a different spatial. No longer used as of JME 3.1.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial for the clone to control (or null)
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public Control cloneForSpatial(Spatial spatial) {
|
public Control cloneForSpatial(Spatial spatial) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a shallow clone for the JME cloner.
|
||||||
|
*
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object jmeClone() {
|
public Object jmeClone() {
|
||||||
GhostControl control = new GhostControl(collisionShape);
|
GhostControl control = new GhostControl(collisionShape);
|
||||||
@ -115,11 +175,27 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
|
||||||
|
* shallow-cloned control into a deep-cloned one, using the specified cloner
|
||||||
|
* and original to resolve copied fields.
|
||||||
|
*
|
||||||
|
* @param cloner the cloner currently cloning this control (not null)
|
||||||
|
* @param original the control from which this control was shallow-cloned
|
||||||
|
* (unused)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void cloneFields( Cloner cloner, Object original ) {
|
public void cloneFields( Cloner cloner, Object original ) {
|
||||||
this.spatial = cloner.clone(spatial);
|
this.spatial = cloner.clone(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
this.spatial = spatial;
|
this.spatial = spatial;
|
||||||
setUserObject(spatial);
|
setUserObject(spatial);
|
||||||
@ -130,6 +206,15 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
setPhysicsRotation(getSpatialRotation());
|
setPhysicsRotation(getSpatialRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable this control.
|
||||||
|
* <p>
|
||||||
|
* When the control is disabled, the ghost object is removed from physics
|
||||||
|
* space. When the control is enabled again, the object is moved to the
|
||||||
|
* current location of the spatial and then added to the physics space.
|
||||||
|
*
|
||||||
|
* @param enabled true→enable the control, false→disable it
|
||||||
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
if (space != null) {
|
if (space != null) {
|
||||||
@ -147,10 +232,22 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this control is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is added to a scene. Do not invoke directly
|
||||||
|
* from user code.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
@ -159,6 +256,14 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
setPhysicsRotation(getSpatialRotation());
|
setPhysicsRotation(getSpatialRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per view port per frame, provided the
|
||||||
|
* control is added to a scene. Should be invoked only by a subclass or by
|
||||||
|
* the RenderManager.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
public void render(RenderManager rm, ViewPort vp) {
|
public void render(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +294,22 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
space = newSpace;
|
space = newSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the physics space to which the ghost object is (or would be)
|
||||||
|
* added.
|
||||||
|
*
|
||||||
|
* @return the pre-existing space, or null for none
|
||||||
|
*/
|
||||||
public PhysicsSpace getPhysicsSpace() {
|
public PhysicsSpace getPhysicsSpace() {
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this control, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -202,6 +319,12 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
|
|||||||
oc.write(spatial, "spatial", null);
|
oc.write(spatial, "spatial", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this control, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
|
@ -58,32 +58,39 @@ import java.util.logging.Logger;
|
|||||||
* use this control you need a model with an AnimControl and a
|
* use this control you need a model with an AnimControl and a
|
||||||
* SkeletonControl.<br> This should be the case if you imported an animated
|
* SkeletonControl.<br> This should be the case if you imported an animated
|
||||||
* model from Ogre or blender.<br> Note enabling/disabling the control
|
* model from Ogre or blender.<br> Note enabling/disabling the control
|
||||||
* add/removes it from the physics space<br> <p> This control creates collision
|
* add/removes it from the physics space<br>
|
||||||
* shapes for each bones of the skeleton when you call
|
* <p>
|
||||||
* spatial.addControl(ragdollControl). <ul> <li>The shape is HullCollision shape
|
* This control creates collision shapes for each bones of the skeleton when you
|
||||||
* based on the vertices associated with each bone and based on a tweakable
|
* invoke spatial.addControl(ragdollControl). <ul> <li>The shape is
|
||||||
* weight threshold (see setWeightThreshold)</li> <li>If you don't want each
|
* HullCollision shape based on the vertices associated with each bone and based
|
||||||
* bone to be a collision shape, you can specify what bone to use by using the
|
* on a tweakable weight threshold (see setWeightThreshold)</li> <li>If you
|
||||||
* addBoneName method<br> By using this method, bone that are not used to create
|
* don't want each bone to be a collision shape, you can specify what bone to
|
||||||
* a shape, are "merged" to their parent to create the collision shape. </li>
|
* use by using the addBoneName method<br> By using this method, bone that are
|
||||||
* </ul> </p> <p> There are 2 modes for this control : <ul> <li><strong>The
|
* not used to create a shape, are "merged" to their parent to create the
|
||||||
* kinematic modes :</strong><br> this is the default behavior, this means that
|
* collision shape. </li>
|
||||||
* the collision shapes of the body are able to interact with physics enabled
|
* </ul>
|
||||||
* objects. in this mode physics shapes follow the motion of the animated
|
* <p>
|
||||||
* skeleton (for example animated by a key framed animation) this mode is
|
* There are 2 modes for this control : <ul> <li><strong>The kinematic modes
|
||||||
* enabled by calling setKinematicMode(); </li> <li><strong>The ragdoll modes
|
* :</strong><br> this is the default behavior, this means that the collision
|
||||||
* :</strong><br> To enable this behavior, you need to call setRagdollMode()
|
* shapes of the body are able to interact with physics enabled objects. in this
|
||||||
* method. In this mode the character is entirely controlled by physics, so it
|
* mode physics shapes follow the motion of the animated skeleton (for example
|
||||||
* will fall under the gravity and move if any force is applied to it. </li>
|
* animated by a key framed animation) this mode is enabled by calling
|
||||||
* </ul> </p>
|
* setKinematicMode(); </li> <li><strong>The ragdoll modes:</strong><br> To
|
||||||
|
* enable this behavior, you need to invoke the setRagdollMode() method. In this
|
||||||
|
* mode the character is entirely controlled by physics, so it will fall under
|
||||||
|
* the gravity and move if any force is applied to it.</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author Normen Hansen and Rémy Bouquet (Nehon)
|
* @author Normen Hansen and Rémy Bouquet (Nehon)
|
||||||
*
|
|
||||||
* TODO this needs to be redone with the new animation system
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class KinematicRagdollControl extends AbstractPhysicsControl implements PhysicsCollisionListener, JmeCloneable {
|
public class KinematicRagdollControl extends AbstractPhysicsControl implements PhysicsCollisionListener, JmeCloneable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of registered collision listeners
|
||||||
|
*/
|
||||||
protected static final Logger logger = Logger.getLogger(KinematicRagdollControl.class.getName());
|
protected static final Logger logger = Logger.getLogger(KinematicRagdollControl.class.getName());
|
||||||
protected List<RagdollCollisionListener> listeners;
|
protected List<RagdollCollisionListener> listeners;
|
||||||
protected final Set<String> boneList = new TreeSet<String>();
|
protected final Set<String> boneList = new TreeSet<String>();
|
||||||
@ -91,7 +98,13 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
protected final Vector3f modelPosition = new Vector3f();
|
protected final Vector3f modelPosition = new Vector3f();
|
||||||
protected final Quaternion modelRotation = new Quaternion();
|
protected final Quaternion modelRotation = new Quaternion();
|
||||||
protected final PhysicsRigidBody baseRigidBody;
|
protected final PhysicsRigidBody baseRigidBody;
|
||||||
|
/**
|
||||||
|
* model being controlled
|
||||||
|
*/
|
||||||
protected Spatial targetModel;
|
protected Spatial targetModel;
|
||||||
|
/**
|
||||||
|
* skeleton being controlled
|
||||||
|
*/
|
||||||
protected Skeleton skeleton;
|
protected Skeleton skeleton;
|
||||||
protected RagdollPreset preset = new HumanoidRagdollPreset();
|
protected RagdollPreset preset = new HumanoidRagdollPreset();
|
||||||
protected Vector3f initScale;
|
protected Vector3f initScale;
|
||||||
@ -100,23 +113,52 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
protected boolean blendedControl = false;
|
protected boolean blendedControl = false;
|
||||||
protected float weightThreshold = -1.0f;
|
protected float weightThreshold = -1.0f;
|
||||||
protected float blendStart = 0.0f;
|
protected float blendStart = 0.0f;
|
||||||
|
/**
|
||||||
|
* blending interval for animations (in seconds, ≥0)
|
||||||
|
*/
|
||||||
protected float blendTime = 1.0f;
|
protected float blendTime = 1.0f;
|
||||||
protected float eventDispatchImpulseThreshold = 10;
|
protected float eventDispatchImpulseThreshold = 10;
|
||||||
protected float rootMass = 15;
|
protected float rootMass = 15;
|
||||||
|
/**
|
||||||
|
* accumulate total mass of ragdoll when control is added to a scene
|
||||||
|
*/
|
||||||
protected float totalMass = 0;
|
protected float totalMass = 0;
|
||||||
private Map<String, Vector3f> ikTargets = new HashMap<String, Vector3f>();
|
private Map<String, Vector3f> ikTargets = new HashMap<String, Vector3f>();
|
||||||
private Map<String, Integer> ikChainDepth = new HashMap<String, Integer>();
|
private Map<String, Integer> ikChainDepth = new HashMap<String, Integer>();
|
||||||
|
/**
|
||||||
|
* rotational speed for inverse kinematics (radians per second, default=7)
|
||||||
|
*/
|
||||||
private float ikRotSpeed = 7f;
|
private float ikRotSpeed = 7f;
|
||||||
|
/**
|
||||||
|
* viscous limb-damping ratio (0→no damping, 1→critically damped,
|
||||||
|
* default=0.6)
|
||||||
|
*/
|
||||||
private float limbDampening = 0.6f;
|
private float limbDampening = 0.6f;
|
||||||
|
/**
|
||||||
|
* distance threshold for inverse kinematics (default=0.1)
|
||||||
|
*/
|
||||||
private float IKThreshold = 0.1f;
|
private float IKThreshold = 0.1f;
|
||||||
|
/**
|
||||||
|
* Enumerate joint-control modes for this control.
|
||||||
|
*/
|
||||||
public static enum Mode {
|
public static enum Mode {
|
||||||
|
/**
|
||||||
|
* collision shapes follow the movements of bones in the skeleton
|
||||||
|
*/
|
||||||
Kinematic,
|
Kinematic,
|
||||||
|
/**
|
||||||
|
* skeleton is controlled by Bullet physics (gravity and collisions)
|
||||||
|
*/
|
||||||
Ragdoll,
|
Ragdoll,
|
||||||
|
/**
|
||||||
|
* skeleton is controlled by inverse-kinematic targets
|
||||||
|
*/
|
||||||
IK
|
IK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link a bone to a jointed rigid body.
|
||||||
|
*/
|
||||||
public class PhysicsBoneLink implements Savable {
|
public class PhysicsBoneLink implements Savable {
|
||||||
|
|
||||||
protected PhysicsRigidBody rigidBody;
|
protected PhysicsRigidBody rigidBody;
|
||||||
@ -126,17 +168,36 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
protected Quaternion startBlendingRot = new Quaternion();
|
protected Quaternion startBlendingRot = new Quaternion();
|
||||||
protected Vector3f startBlendingPos = new Vector3f();
|
protected Vector3f startBlendingPos = new Vector3f();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an uninitialized link.
|
||||||
|
*/
|
||||||
public PhysicsBoneLink() {
|
public PhysicsBoneLink() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the linked bone.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance or null
|
||||||
|
*/
|
||||||
public Bone getBone() {
|
public Bone getBone() {
|
||||||
return bone;
|
return bone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the linked body.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance or null
|
||||||
|
*/
|
||||||
public PhysicsRigidBody getRigidBody() {
|
public PhysicsRigidBody getRigidBody() {
|
||||||
return rigidBody;
|
return rigidBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this bone link, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
oc.write(rigidBody, "rigidBody", null);
|
oc.write(rigidBody, "rigidBody", null);
|
||||||
@ -147,6 +208,13 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
oc.write(startBlendingPos, "startBlendingPos", new Vector3f());
|
oc.write(startBlendingPos, "startBlendingPos", new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this bone link, for example when loading from a J3O
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
rigidBody = (PhysicsRigidBody) ic.readSavable("rigidBody", null);
|
rigidBody = (PhysicsRigidBody) ic.readSavable("rigidBody", null);
|
||||||
@ -159,29 +227,53 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* construct a KinematicRagdollControl
|
* Instantiate an enabled control.
|
||||||
*/
|
*/
|
||||||
public KinematicRagdollControl() {
|
public KinematicRagdollControl() {
|
||||||
baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(0.1f)), 1);
|
baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(0.1f)), 1);
|
||||||
baseRigidBody.setKinematic(mode == Mode.Kinematic);
|
baseRigidBody.setKinematic(mode == Mode.Kinematic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control with the specified weight threshold.
|
||||||
|
*
|
||||||
|
* @param weightThreshold (>0, <1)
|
||||||
|
*/
|
||||||
public KinematicRagdollControl(float weightThreshold) {
|
public KinematicRagdollControl(float weightThreshold) {
|
||||||
this();
|
this();
|
||||||
this.weightThreshold = weightThreshold;
|
this.weightThreshold = weightThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control with the specified preset and weight
|
||||||
|
* threshold.
|
||||||
|
*
|
||||||
|
* @param preset (not null)
|
||||||
|
* @param weightThreshold (>0, <1)
|
||||||
|
*/
|
||||||
public KinematicRagdollControl(RagdollPreset preset, float weightThreshold) {
|
public KinematicRagdollControl(RagdollPreset preset, float weightThreshold) {
|
||||||
this();
|
this();
|
||||||
this.preset = preset;
|
this.preset = preset;
|
||||||
this.weightThreshold = weightThreshold;
|
this.weightThreshold = weightThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control with the specified preset.
|
||||||
|
*
|
||||||
|
* @param preset (not null)
|
||||||
|
*/
|
||||||
public KinematicRagdollControl(RagdollPreset preset) {
|
public KinematicRagdollControl(RagdollPreset preset) {
|
||||||
this();
|
this();
|
||||||
this.preset = preset;
|
this.preset = preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is added to a scene. Do not invoke directly
|
||||||
|
* from user code.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
@ -196,6 +288,11 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control in Ragdoll mode, based on Bullet physics.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
protected void ragDollUpdate(float tpf) {
|
protected void ragDollUpdate(float tpf) {
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
Quaternion tmpRot1 = vars.quat1;
|
Quaternion tmpRot1 = vars.quat1;
|
||||||
@ -213,7 +310,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
//retrieving bone rotation in physics world space
|
//retrieving bone rotation in physics world space
|
||||||
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
|
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
|
||||||
|
|
||||||
//multiplying this rotation by the initialWorld rotation of the bone,
|
//multiplying this rotation by the initialWorld rotation of the bone,
|
||||||
//then transforming it with the inverse world rotation of the model
|
//then transforming it with the inverse world rotation of the model
|
||||||
tmpRot1.set(q).multLocal(link.initalWorldRotation);
|
tmpRot1.set(q).multLocal(link.initalWorldRotation);
|
||||||
tmpRot2.set(targetModel.getWorldRotation()).inverseLocal().mult(tmpRot1, tmpRot1);
|
tmpRot2.set(targetModel.getWorldRotation()).inverseLocal().mult(tmpRot1, tmpRot1);
|
||||||
@ -237,13 +334,13 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//if boneList is empty, this means that every bone in the ragdoll has a collision shape,
|
//If boneList is empty, every bone has a collision shape,
|
||||||
//so we just update the bone position
|
//so we simply update the bone position.
|
||||||
if (boneList.isEmpty()) {
|
if (boneList.isEmpty()) {
|
||||||
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
||||||
} else {
|
} else {
|
||||||
//boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
|
//boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
|
||||||
//So we update them recursively
|
//So we update them recusively
|
||||||
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
|
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,6 +348,11 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
vars.release();
|
vars.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control in Kinematic mode, based on bone animation tracks.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
protected void kinematicUpdate(float tpf) {
|
protected void kinematicUpdate(float tpf) {
|
||||||
//the ragdoll does not have control, so the keyframed animation updates the physics position of the physics bonces
|
//the ragdoll does not have control, so the keyframed animation updates the physics position of the physics bonces
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
@ -261,7 +363,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
// if(link.usedbyIK){
|
// if(link.usedbyIK){
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
//if blended control this means, keyframed animation is updating the skeleton,
|
//if blended control this means, keyframed animation is updating the skeleton,
|
||||||
//but to allow smooth transition, we blend this transformation with the saved position of the ragdoll
|
//but to allow smooth transition, we blend this transformation with the saved position of the ragdoll
|
||||||
if (blendedControl) {
|
if (blendedControl) {
|
||||||
Vector3f position2 = vars.vect2;
|
Vector3f position2 = vars.vect2;
|
||||||
@ -301,6 +403,11 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
vars.release();
|
vars.release();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Update this control in IK mode, based on IK targets.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
private void ikUpdate(float tpf){
|
private void ikUpdate(float tpf){
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
|
|
||||||
@ -337,6 +444,19 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
vars.release();
|
vars.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a bone and its ancestors in IK mode. Note: recursive!
|
||||||
|
*
|
||||||
|
* @param link the bone link for the affected bone (may be null)
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
* @param vars unused
|
||||||
|
* @param tmpRot1 temporary storage used in calculations (not null)
|
||||||
|
* @param tmpRot2 temporary storage used in calculations (not null)
|
||||||
|
* @param tipBone (not null)
|
||||||
|
* @param target the location target in model space (not null, unaffected)
|
||||||
|
* @param depth depth of the recursion (≥0)
|
||||||
|
* @param maxDepth recursion limit (≥0)
|
||||||
|
*/
|
||||||
public void updateBone(PhysicsBoneLink link, float tpf, TempVars vars, Quaternion tmpRot1, Quaternion[] tmpRot2, Bone tipBone, Vector3f target, int depth, int maxDepth) {
|
public void updateBone(PhysicsBoneLink link, float tpf, TempVars vars, Quaternion tmpRot1, Quaternion[] tmpRot2, Bone tipBone, Vector3f target, int depth, int maxDepth) {
|
||||||
if (link == null || link.bone.getParent() == null) {
|
if (link == null || link.bone.getParent() == null) {
|
||||||
return;
|
return;
|
||||||
@ -391,13 +511,12 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the transforms of a rigidBody to match the transforms of a bone. this
|
* Alter the transforms of a rigidBody to match the transforms of a bone.
|
||||||
* is used to make the ragdoll follow the skeleton motion while in Kinematic
|
* This is used to make the ragdoll follow animated motion in Kinematic mode
|
||||||
* mode
|
|
||||||
*
|
*
|
||||||
* @param link the link containing the bone and the rigidBody
|
* @param link the bone link connecting the bone and the rigidBody
|
||||||
* @param position just a temp vector for position
|
* @param position temporary storage used in calculations (not null)
|
||||||
* @param tmpRot1 just a temp quaternion for rotation
|
* @param tmpRot1 temporary storage used in calculations (not null)
|
||||||
*/
|
*/
|
||||||
protected void matchPhysicObjectToBone(PhysicsBoneLink link, Vector3f position, Quaternion tmpRot1) {
|
protected void matchPhysicObjectToBone(PhysicsBoneLink link, Vector3f position, Quaternion tmpRot1) {
|
||||||
//computing position from rotation and scale
|
//computing position from rotation and scale
|
||||||
@ -415,8 +534,8 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rebuild the ragdoll this is useful if you applied scale on the ragdoll
|
* Rebuild the ragdoll. This is useful if you applied scale on the ragdoll
|
||||||
* after it's been initialized, same as reattaching.
|
* after it was initialized. Same as re-attaching.
|
||||||
*/
|
*/
|
||||||
public void reBuild() {
|
public void reBuild() {
|
||||||
if (spatial == null) {
|
if (spatial == null) {
|
||||||
@ -426,6 +545,12 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
createSpatialData(spatial);
|
createSpatialData(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create spatial-dependent data. Invoked when this control is added to a
|
||||||
|
* scene.
|
||||||
|
*
|
||||||
|
* @param model the controlled spatial (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void createSpatialData(Spatial model) {
|
protected void createSpatialData(Spatial model) {
|
||||||
targetModel = model;
|
targetModel = model;
|
||||||
@ -451,7 +576,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
model.addControl(sc);
|
model.addControl(sc);
|
||||||
|
|
||||||
// put into bind pose and compute bone transforms in model space
|
// put into bind pose and compute bone transforms in model space
|
||||||
// maybe dont reset to ragdoll out of animations?
|
// maybe don't reset to ragdoll out of animations?
|
||||||
scanSpatial(model);
|
scanSpatial(model);
|
||||||
|
|
||||||
|
|
||||||
@ -469,6 +594,12 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton);
|
logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy spatial-dependent data. Invoked when this control is removed from
|
||||||
|
* a spatial.
|
||||||
|
*
|
||||||
|
* @param spat the previously controlled spatial (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void removeSpatialData(Spatial spat) {
|
protected void removeSpatialData(Spatial spat) {
|
||||||
if (added) {
|
if (added) {
|
||||||
@ -478,15 +609,22 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a bone name to this control Using this method you can specify which
|
* Add a bone name to this control. Repeated invocations of this method can
|
||||||
* bones of the skeleton will be used to build the collision shapes.
|
* be used to specify which bones to use when generating collision shapes.
|
||||||
|
* <p>
|
||||||
|
* Not allowed after attaching the control.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name the name of the bone to add
|
||||||
*/
|
*/
|
||||||
public void addBoneName(String name) {
|
public void addBoneName(String name) {
|
||||||
boneList.add(name);
|
boneList.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate physics shapes and bone links for the skeleton.
|
||||||
|
*
|
||||||
|
* @param model the spatial with the model's SkeletonControl (not null)
|
||||||
|
*/
|
||||||
protected void scanSpatial(Spatial model) {
|
protected void scanSpatial(Spatial model) {
|
||||||
AnimControl animControl = model.getControl(AnimControl.class);
|
AnimControl animControl = model.getControl(AnimControl.class);
|
||||||
Map<Integer, List<Float>> pointsMap = null;
|
Map<Integer, List<Float>> pointsMap = null;
|
||||||
@ -505,6 +643,16 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a physics shape and bone links for the specified bone. Note:
|
||||||
|
* recursive!
|
||||||
|
*
|
||||||
|
* @param model the spatial with the model's SkeletonControl (not null)
|
||||||
|
* @param bone the bone to be linked (not null)
|
||||||
|
* @param parent the body linked to the parent bone (not null)
|
||||||
|
* @param reccount depth of the recursion (≥1)
|
||||||
|
* @param pointsMap (not null)
|
||||||
|
*/
|
||||||
protected void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount, Map<Integer, List<Float>> pointsMap) {
|
protected void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount, Map<Integer, List<Float>> pointsMap) {
|
||||||
PhysicsRigidBody parentShape = parent;
|
PhysicsRigidBody parentShape = parent;
|
||||||
if (boneList.isEmpty() || boneList.contains(bone.getName())) {
|
if (boneList.isEmpty() || boneList.contains(bone.getName())) {
|
||||||
@ -512,7 +660,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
PhysicsBoneLink link = new PhysicsBoneLink();
|
PhysicsBoneLink link = new PhysicsBoneLink();
|
||||||
link.bone = bone;
|
link.bone = bone;
|
||||||
|
|
||||||
//creating the collision shape
|
//create the collision shape
|
||||||
HullCollisionShape shape = null;
|
HullCollisionShape shape = null;
|
||||||
if (pointsMap != null) {
|
if (pointsMap != null) {
|
||||||
//build a shape for the bone, using the vertices that are most influenced by this bone
|
//build a shape for the bone, using the vertices that are most influenced by this bone
|
||||||
@ -555,16 +703,16 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the joint limits for the joint between the given bone and its parent.
|
* Alter the limits of the joint connecting the specified bone to its
|
||||||
* This method can't work before attaching the control to a spatial
|
* parent. Can only be invoked after adding the control to a spatial.
|
||||||
*
|
*
|
||||||
* @param boneName the name of the bone
|
* @param boneName the name of the bone
|
||||||
* @param maxX the maximum rotation on the x axis (in radians)
|
* @param maxX the maximum rotation on the X axis (in radians)
|
||||||
* @param minX the minimum rotation on the x axis (in radians)
|
* @param minX the minimum rotation on the X axis (in radians)
|
||||||
* @param maxY the maximum rotation on the y axis (in radians)
|
* @param maxY the maximum rotation on the Y axis (in radians)
|
||||||
* @param minY the minimum rotation on the z axis (in radians)
|
* @param minY the minimum rotation on the Y axis (in radians)
|
||||||
* @param maxZ the maximum rotation on the z axis (in radians)
|
* @param maxZ the maximum rotation on the Z axis (in radians)
|
||||||
* @param minZ the minimum rotation on the z axis (in radians)
|
* @param minZ the minimum rotation on the Z axis (in radians)
|
||||||
*/
|
*/
|
||||||
public void setJointLimit(String boneName, float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
|
public void setJointLimit(String boneName, float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
|
||||||
PhysicsBoneLink link = boneLinks.get(boneName);
|
PhysicsBoneLink link = boneLinks.get(boneName);
|
||||||
@ -576,8 +724,8 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the joint between the given bone and its parent. This return null
|
* Return the joint between the specified bone and its parent. This return
|
||||||
* if it's called before attaching the control to a spatial
|
* null if it's invoked before adding the control to a spatial
|
||||||
*
|
*
|
||||||
* @param boneName the name of the bone
|
* @param boneName the name of the bone
|
||||||
* @return the joint between the given bone and its parent
|
* @return the joint between the given bone and its parent
|
||||||
@ -642,9 +790,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For internal use only callback for collisionevent
|
* For internal use only: callback for collision event
|
||||||
*
|
*
|
||||||
* @param event
|
* @param event (not null)
|
||||||
*/
|
*/
|
||||||
public void collision(PhysicsCollisionEvent event) {
|
public void collision(PhysicsCollisionEvent event) {
|
||||||
PhysicsCollisionObject objA = event.getObjectA();
|
PhysicsCollisionObject objA = event.getObjectA();
|
||||||
@ -699,7 +847,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
* be animated by the keyframe animation, but will be able to physically
|
* be animated by the keyframe animation, but will be able to physically
|
||||||
* interact with its physics environment
|
* interact with its physics environment
|
||||||
*
|
*
|
||||||
* @param ragdollEnabled
|
* @param mode an enum value (not null)
|
||||||
*/
|
*/
|
||||||
protected void setMode(Mode mode) {
|
protected void setMode(Mode mode) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
@ -777,9 +925,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the control into Kinematic mode In this mode, the collision shapes
|
* Put the control into Kinematic mode. In this mode, the collision shapes
|
||||||
* follow the movements of the skeleton, and can interact with physical
|
* follow the movements of the skeleton while interacting with the physics
|
||||||
* environment
|
* environment.
|
||||||
*/
|
*/
|
||||||
public void setKinematicMode() {
|
public void setKinematicMode() {
|
||||||
if (mode != Mode.Kinematic) {
|
if (mode != Mode.Kinematic) {
|
||||||
@ -798,8 +946,8 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the control into Inverse Kinematics mode. The affected bones are affected by IK.
|
* Sets the control into Inverse Kinematics mode. The affected bones are
|
||||||
* physics.
|
* affected by IK. physics.
|
||||||
*/
|
*/
|
||||||
public void setIKMode() {
|
public void setIKMode() {
|
||||||
if (mode != Mode.IK) {
|
if (mode != Mode.IK) {
|
||||||
@ -810,16 +958,16 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
/**
|
/**
|
||||||
* returns the mode of this control
|
* returns the mode of this control
|
||||||
*
|
*
|
||||||
* @return
|
* @return an enum value
|
||||||
*/
|
*/
|
||||||
public Mode getMode() {
|
public Mode getMode() {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add a
|
* Add a collision listener to this control.
|
||||||
*
|
*
|
||||||
* @param listener
|
* @param listener (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public void addCollisionListener(RagdollCollisionListener listener) {
|
public void addCollisionListener(RagdollCollisionListener listener) {
|
||||||
if (listeners == null) {
|
if (listeners == null) {
|
||||||
@ -828,35 +976,66 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the ragdoll's root mass.
|
||||||
|
*
|
||||||
|
* @param rootMass the desired mass (≥0)
|
||||||
|
*/
|
||||||
public void setRootMass(float rootMass) {
|
public void setRootMass(float rootMass) {
|
||||||
this.rootMass = rootMass;
|
this.rootMass = rootMass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the ragdoll's total mass.
|
||||||
|
*
|
||||||
|
* @return mass (≥0)
|
||||||
|
*/
|
||||||
public float getTotalMass() {
|
public float getTotalMass() {
|
||||||
return totalMass;
|
return totalMass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the ragdoll's weight threshold.
|
||||||
|
*
|
||||||
|
* @return threshold
|
||||||
|
*/
|
||||||
public float getWeightThreshold() {
|
public float getWeightThreshold() {
|
||||||
return weightThreshold;
|
return weightThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the ragdoll's weight threshold.
|
||||||
|
*
|
||||||
|
* @param weightThreshold the desired threshold
|
||||||
|
*/
|
||||||
public void setWeightThreshold(float weightThreshold) {
|
public void setWeightThreshold(float weightThreshold) {
|
||||||
this.weightThreshold = weightThreshold;
|
this.weightThreshold = weightThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the ragdoll's event-dispatch impulse threshold.
|
||||||
|
*
|
||||||
|
* @return threshold
|
||||||
|
*/
|
||||||
public float getEventDispatchImpulseThreshold() {
|
public float getEventDispatchImpulseThreshold() {
|
||||||
return eventDispatchImpulseThreshold;
|
return eventDispatchImpulseThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the ragdoll's event-dispatch impulse threshold.
|
||||||
|
*
|
||||||
|
* @param eventDispatchImpulseThreshold desired threshold
|
||||||
|
*/
|
||||||
public void setEventDispatchImpulseThreshold(float eventDispatchImpulseThreshold) {
|
public void setEventDispatchImpulseThreshold(float eventDispatchImpulseThreshold) {
|
||||||
this.eventDispatchImpulseThreshold = eventDispatchImpulseThreshold;
|
this.eventDispatchImpulseThreshold = eventDispatchImpulseThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the CcdMotionThreshold of all the bone's rigidBodies of the ragdoll
|
* Alter the CcdMotionThreshold of all rigid bodies in the ragdoll.
|
||||||
*
|
*
|
||||||
* @see PhysicsRigidBody#setCcdMotionThreshold(float)
|
* @see PhysicsRigidBody#setCcdMotionThreshold(float)
|
||||||
* @param value
|
* @param value the desired threshold value (velocity, >0) or zero to
|
||||||
|
* disable CCD (default=0)
|
||||||
*/
|
*/
|
||||||
public void setCcdMotionThreshold(float value) {
|
public void setCcdMotionThreshold(float value) {
|
||||||
for (PhysicsBoneLink link : boneLinks.values()) {
|
for (PhysicsBoneLink link : boneLinks.values()) {
|
||||||
@ -865,10 +1044,11 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the CcdSweptSphereRadius of all the bone's rigidBodies of the ragdoll
|
* Alter the CcdSweptSphereRadius of all rigid bodies in the ragdoll.
|
||||||
*
|
*
|
||||||
* @see PhysicsRigidBody#setCcdSweptSphereRadius(float)
|
* @see PhysicsRigidBody#setCcdSweptSphereRadius(float)
|
||||||
* @param value
|
* @param value the desired radius of the sphere used for continuous
|
||||||
|
* collision detection (≥0)
|
||||||
*/
|
*/
|
||||||
public void setCcdSweptSphereRadius(float value) {
|
public void setCcdSweptSphereRadius(float value) {
|
||||||
for (PhysicsBoneLink link : boneLinks.values()) {
|
for (PhysicsBoneLink link : boneLinks.values()) {
|
||||||
@ -877,7 +1057,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the rigidBody associated to the given bone
|
* Access the rigidBody associated with the named bone.
|
||||||
*
|
*
|
||||||
* @param boneName the name of the bone
|
* @param boneName the name of the bone
|
||||||
* @return the associated rigidBody.
|
* @return the associated rigidBody.
|
||||||
@ -891,15 +1071,22 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For internal use only specific render for the ragdoll (if debugging)
|
* Render this control. Invoked once per view port per frame, provided the
|
||||||
|
* control is added to a scene. Should be invoked only by a subclass or by
|
||||||
|
* the RenderManager.
|
||||||
*
|
*
|
||||||
* @param rm
|
* @param rm the render manager (not null)
|
||||||
* @param vp
|
* @param vp the view port to render (not null)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(RenderManager rm, ViewPort vp) {
|
public void render(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a shallow clone for the JME cloner.
|
||||||
|
*
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object jmeClone() {
|
public Object jmeClone() {
|
||||||
KinematicRagdollControl control = new KinematicRagdollControl(preset, weightThreshold);
|
KinematicRagdollControl control = new KinematicRagdollControl(preset, weightThreshold);
|
||||||
@ -911,6 +1098,14 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a target for inverse kinematics.
|
||||||
|
*
|
||||||
|
* @param bone which bone the IK applies to (not null)
|
||||||
|
* @param worldPos the world coordinates of the goal (not null)
|
||||||
|
* @param chainLength number of bones in the chain
|
||||||
|
* @return a new instance (not null, already added to ikTargets)
|
||||||
|
*/
|
||||||
public Vector3f setIKTarget(Bone bone, Vector3f worldPos, int chainLength) {
|
public Vector3f setIKTarget(Bone bone, Vector3f worldPos, int chainLength) {
|
||||||
Vector3f target = worldPos.subtract(targetModel.getWorldTranslation());
|
Vector3f target = worldPos.subtract(targetModel.getWorldTranslation());
|
||||||
ikTargets.put(bone.getName(), target);
|
ikTargets.put(bone.getName(), target);
|
||||||
@ -929,6 +1124,11 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inverse-kinematics target for the specified bone.
|
||||||
|
*
|
||||||
|
* @param bone which bone has the target (not null, modified)
|
||||||
|
*/
|
||||||
public void removeIKTarget(Bone bone) {
|
public void removeIKTarget(Bone bone) {
|
||||||
int depth = ikChainDepth.remove(bone.getName());
|
int depth = ikChainDepth.remove(bone.getName());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -942,11 +1142,19 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all inverse-kinematics targets.
|
||||||
|
*/
|
||||||
public void removeAllIKTargets(){
|
public void removeAllIKTargets(){
|
||||||
ikTargets.clear();
|
ikTargets.clear();
|
||||||
ikChainDepth.clear();
|
ikChainDepth.clear();
|
||||||
applyUserControl();
|
applyUserControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that user control is enabled for any bones used by inverse
|
||||||
|
* kinematics and disabled for any other bones.
|
||||||
|
*/
|
||||||
public void applyUserControl() {
|
public void applyUserControl() {
|
||||||
for (Bone bone : skeleton.getRoots()) {
|
for (Bone bone : skeleton.getRoots()) {
|
||||||
RagdollUtils.setUserControl(bone, false);
|
RagdollUtils.setUserControl(bone, false);
|
||||||
@ -973,39 +1181,77 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
vars.release();
|
vars.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the rotation speed for inverse kinematics.
|
||||||
|
*
|
||||||
|
* @return speed (≥0)
|
||||||
|
*/
|
||||||
public float getIkRotSpeed() {
|
public float getIkRotSpeed() {
|
||||||
return ikRotSpeed;
|
return ikRotSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the rotation speed for inverse kinematics.
|
||||||
|
*
|
||||||
|
* @param ikRotSpeed the desired speed (≥0, default=7)
|
||||||
|
*/
|
||||||
public void setIkRotSpeed(float ikRotSpeed) {
|
public void setIkRotSpeed(float ikRotSpeed) {
|
||||||
this.ikRotSpeed = ikRotSpeed;
|
this.ikRotSpeed = ikRotSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the distance threshold for inverse kinematics.
|
||||||
|
*
|
||||||
|
* @return distance threshold
|
||||||
|
*/
|
||||||
public float getIKThreshold() {
|
public float getIKThreshold() {
|
||||||
return IKThreshold;
|
return IKThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the distance threshold for inverse kinematics.
|
||||||
|
*
|
||||||
|
* @param IKThreshold the desired distance threshold (default=0.1)
|
||||||
|
*/
|
||||||
public void setIKThreshold(float IKThreshold) {
|
public void setIKThreshold(float IKThreshold) {
|
||||||
this.IKThreshold = IKThreshold;
|
this.IKThreshold = IKThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the limb damping.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getLimbDampening() {
|
public float getLimbDampening() {
|
||||||
return limbDampening;
|
return limbDampening;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the limb damping.
|
||||||
|
*
|
||||||
|
* @param limbDampening the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=0.6)
|
||||||
|
*/
|
||||||
public void setLimbDampening(float limbDampening) {
|
public void setLimbDampening(float limbDampening) {
|
||||||
this.limbDampening = limbDampening;
|
this.limbDampening = limbDampening;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the named bone.
|
||||||
|
*
|
||||||
|
* @param name which bone to access
|
||||||
|
* @return the pre-existing instance, or null if not found
|
||||||
|
*/
|
||||||
public Bone getBone(String name){
|
public Bone getBone(String name){
|
||||||
return skeleton.getBone(name);
|
return skeleton.getBone(name);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* serialize this control
|
* Serialize this control, for example when saving to a J3O file.
|
||||||
*
|
*
|
||||||
* @param ex
|
* @param ex exporter (not null)
|
||||||
* @throws IOException
|
* @throws IOException from exporter
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
@ -1032,10 +1278,10 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* de-serialize this control
|
* De-serialize this control, for example when loading from a J3O file.
|
||||||
*
|
*
|
||||||
* @param im
|
* @param im importer (not null)
|
||||||
* @throws IOException
|
* @throws IOException from importer
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -35,31 +35,47 @@ import com.jme3.bullet.PhysicsSpace;
|
|||||||
import com.jme3.scene.control.Control;
|
import com.jme3.scene.control.Control;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* An interface for a scene-graph control that links a physics object to a
|
||||||
|
* Spatial.
|
||||||
|
* <p>
|
||||||
|
* This interface is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public interface PhysicsControl extends Control {
|
public interface PhysicsControl extends Control {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only used internally, do not call.
|
* If enabled, add this control's physics object to the specified physics
|
||||||
* @param space
|
* space. In not enabled, alter where the object would be added. The object
|
||||||
|
* is removed from any other space it's currently in.
|
||||||
|
*
|
||||||
|
* @param space where to add, or null to simply remove
|
||||||
*/
|
*/
|
||||||
public void setPhysicsSpace(PhysicsSpace space);
|
public void setPhysicsSpace(PhysicsSpace space);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the physics space to which the object is (or would be) added.
|
||||||
|
*
|
||||||
|
* @return the pre-existing space, or null for none
|
||||||
|
*/
|
||||||
public PhysicsSpace getPhysicsSpace();
|
public PhysicsSpace getPhysicsSpace();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The physics object is removed from the physics space when the control
|
* Enable or disable this control.
|
||||||
* is disabled. When the control is enabled again the physics object is
|
* <p>
|
||||||
* moved to the current location of the spatial and then added to the physics
|
* The physics object is removed from its physics space when the control is
|
||||||
* space. This allows disabling/enabling physics to move the spatial freely.
|
* disabled. When the control is enabled again, the physics object is moved
|
||||||
* @param state
|
* to the current location of the spatial and then added to the physics
|
||||||
|
* space.
|
||||||
|
*
|
||||||
|
* @param state true→enable the control, false→disable it
|
||||||
*/
|
*/
|
||||||
public void setEnabled(boolean state);
|
public void setEnabled(boolean state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current enabled state of the physics control
|
* Test whether this control is enabled.
|
||||||
* @return current enabled state
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isEnabled();
|
public boolean isEnabled();
|
||||||
}
|
}
|
||||||
|
@ -56,47 +56,91 @@ import com.jme3.util.clone.JmeCloneable;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics control to link a PhysicsRigidBody to a spatial.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl, JmeCloneable {
|
public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl, JmeCloneable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spatial to which this control is added, or null if none
|
||||||
|
*/
|
||||||
protected Spatial spatial;
|
protected Spatial spatial;
|
||||||
|
/**
|
||||||
|
* true→control is enabled, false→control is disabled
|
||||||
|
*/
|
||||||
protected boolean enabled = true;
|
protected boolean enabled = true;
|
||||||
|
/**
|
||||||
|
* true→body is added to the physics space, false→not added
|
||||||
|
*/
|
||||||
protected boolean added = false;
|
protected boolean added = false;
|
||||||
|
/**
|
||||||
|
* space to which the body is (or would be) added
|
||||||
|
*/
|
||||||
protected PhysicsSpace space = null;
|
protected PhysicsSpace space = null;
|
||||||
|
/**
|
||||||
|
* true→body is kinematic, false→body is static or dynamic
|
||||||
|
*/
|
||||||
protected boolean kinematicSpatial = true;
|
protected boolean kinematicSpatial = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public RigidBodyControl() {
|
public RigidBodyControl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When using this constructor, the CollisionShape for the RigidBody is generated
|
* When using this constructor, the CollisionShape for the RigidBody is
|
||||||
* automatically when the Control is added to a Spatial.
|
* generated automatically when the control is added to a spatial.
|
||||||
* @param mass When not 0, a HullCollisionShape is generated, otherwise a MeshCollisionShape is used. For geometries with box or sphere meshes the proper box or sphere collision shape is used.
|
*
|
||||||
|
* @param mass When not 0, a HullCollisionShape is generated, otherwise a
|
||||||
|
* MeshCollisionShape is used. For geometries with box or sphere meshes the
|
||||||
|
* proper box or sphere collision shape is used.
|
||||||
*/
|
*/
|
||||||
public RigidBodyControl(float mass) {
|
public RigidBodyControl(float mass) {
|
||||||
this.mass = mass;
|
this.mass = mass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PhysicsNode with the supplied collision shape and mass 1
|
* Instantiate an enabled control with mass=1 and the specified collision
|
||||||
* @param shape
|
* shape.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public RigidBodyControl(CollisionShape shape) {
|
public RigidBodyControl(CollisionShape shape) {
|
||||||
super(shape);
|
super(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control with the specified collision shape and
|
||||||
|
* mass.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
* @param mass the desired mass (≥0)
|
||||||
|
*/
|
||||||
public RigidBodyControl(CollisionShape shape, float mass) {
|
public RigidBodyControl(CollisionShape shape, float mass) {
|
||||||
super(shape, mass);
|
super(shape, mass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
/**
|
||||||
|
* Clone this control for a different spatial. No longer used as of JME 3.1.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial for the clone to control (or null)
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Control cloneForSpatial(Spatial spatial) {
|
public Control cloneForSpatial(Spatial spatial) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a shallow clone for the JME cloner.
|
||||||
|
*
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object jmeClone() {
|
public Object jmeClone() {
|
||||||
RigidBodyControl control = new RigidBodyControl(collisionShape, mass);
|
RigidBodyControl control = new RigidBodyControl(collisionShape, mass);
|
||||||
@ -127,11 +171,27 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
|
||||||
|
* shallow-cloned control into a deep-cloned one, using the specified cloner
|
||||||
|
* and original to resolve copied fields.
|
||||||
|
*
|
||||||
|
* @param cloner the cloner currently cloning this control (not null)
|
||||||
|
* @param original the control from which this control was shallow-cloned
|
||||||
|
* (unused)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void cloneFields( Cloner cloner, Object original ) {
|
public void cloneFields( Cloner cloner, Object original ) {
|
||||||
this.spatial = cloner.clone(spatial);
|
this.spatial = cloner.clone(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
this.spatial = spatial;
|
this.spatial = spatial;
|
||||||
setUserObject(spatial);
|
setUserObject(spatial);
|
||||||
@ -146,6 +206,10 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
setPhysicsRotation(getSpatialRotation());
|
setPhysicsRotation(getSpatialRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the collision shape based on the controlled spatial and its
|
||||||
|
* descendents.
|
||||||
|
*/
|
||||||
protected void createCollisionShape() {
|
protected void createCollisionShape() {
|
||||||
if (spatial == null) {
|
if (spatial == null) {
|
||||||
return;
|
return;
|
||||||
@ -168,6 +232,15 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable this control.
|
||||||
|
* <p>
|
||||||
|
* When the control is disabled, the body is removed from physics space.
|
||||||
|
* When the control is enabled again, the body is moved to the current
|
||||||
|
* location of the spatial and then added to the physics space.
|
||||||
|
*
|
||||||
|
* @param enabled true→enable the control, false→disable it
|
||||||
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
if (space != null) {
|
if (space != null) {
|
||||||
@ -185,40 +258,62 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this control is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this control is in kinematic spatial mode.
|
* Test whether this control is in kinematic mode.
|
||||||
* @return true if the spatial location is applied to this kinematic rigidbody
|
*
|
||||||
|
* @return true if the spatial location and rotation are applied to the
|
||||||
|
* rigid body, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isKinematicSpatial() {
|
public boolean isKinematicSpatial() {
|
||||||
return kinematicSpatial;
|
return kinematicSpatial;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this control to kinematic spatial mode so that the spatials transform will
|
* Enable or disable kinematic mode. In kinematic mode, the spatial's
|
||||||
* be applied to the rigidbody in kinematic mode, defaults to true.
|
* location and rotation will be applied to the rigid body.
|
||||||
* @param kinematicSpatial
|
*
|
||||||
|
* @param kinematicSpatial true→kinematic, false→dynamic or static
|
||||||
*/
|
*/
|
||||||
public void setKinematicSpatial(boolean kinematicSpatial) {
|
public void setKinematicSpatial(boolean kinematicSpatial) {
|
||||||
this.kinematicSpatial = kinematicSpatial;
|
this.kinematicSpatial = kinematicSpatial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether physics-space coordinates should match the spatial's local
|
||||||
|
* coordinates.
|
||||||
|
*
|
||||||
|
* @return true if matching local coordinates, false if matching world
|
||||||
|
* coordinates
|
||||||
|
*/
|
||||||
public boolean isApplyPhysicsLocal() {
|
public boolean isApplyPhysicsLocal() {
|
||||||
return motionState.isApplyPhysicsLocal();
|
return motionState.isApplyPhysicsLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to true, the physics coordinates will be applied to the local
|
* Alter whether physics-space coordinates should match the spatial's local
|
||||||
* translation of the Spatial instead of the world translation.
|
* coordinates.
|
||||||
* @param applyPhysicsLocal
|
*
|
||||||
|
* @param applyPhysicsLocal true→match local coordinates,
|
||||||
|
* false→match world coordinates (default=false)
|
||||||
*/
|
*/
|
||||||
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
||||||
motionState.setApplyPhysicsLocal(applyPhysicsLocal);
|
motionState.setApplyPhysicsLocal(applyPhysicsLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access whichever spatial translation corresponds to the physics location.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null)
|
||||||
|
*/
|
||||||
private Vector3f getSpatialTranslation(){
|
private Vector3f getSpatialTranslation(){
|
||||||
if(motionState.isApplyPhysicsLocal()){
|
if(motionState.isApplyPhysicsLocal()){
|
||||||
return spatial.getLocalTranslation();
|
return spatial.getLocalTranslation();
|
||||||
@ -226,6 +321,11 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
return spatial.getWorldTranslation();
|
return spatial.getWorldTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access whichever spatial rotation corresponds to the physics rotation.
|
||||||
|
*
|
||||||
|
* @return the pre-existing quaternion (not null)
|
||||||
|
*/
|
||||||
private Quaternion getSpatialRotation(){
|
private Quaternion getSpatialRotation(){
|
||||||
if(motionState.isApplyPhysicsLocal()){
|
if(motionState.isApplyPhysicsLocal()){
|
||||||
return spatial.getLocalRotation();
|
return spatial.getLocalRotation();
|
||||||
@ -233,6 +333,12 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
return spatial.getWorldRotation();
|
return spatial.getWorldRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame, during the logical-state
|
||||||
|
* update, provided the control is added to a scene.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
if (enabled && spatial != null) {
|
if (enabled && spatial != null) {
|
||||||
if (isKinematic() && kinematicSpatial) {
|
if (isKinematic() && kinematicSpatial) {
|
||||||
@ -244,6 +350,14 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per view port per frame, provided the
|
||||||
|
* control is added to a scene. Should be invoked only by a subclass or by
|
||||||
|
* the RenderManager.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
public void render(RenderManager rm, ViewPort vp) {
|
public void render(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,10 +388,21 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
space = newSpace;
|
space = newSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the physics space to which the body is (or would be) added.
|
||||||
|
*
|
||||||
|
* @return the pre-existing space, or null for none
|
||||||
|
*/
|
||||||
public PhysicsSpace getPhysicsSpace() {
|
public PhysicsSpace getPhysicsSpace() {
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this control, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -288,6 +413,12 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
|
|||||||
oc.write(spatial, "spatial", null);
|
oc.write(spatial, "spatial", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this control, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
|
@ -51,39 +51,75 @@ import java.io.IOException;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics control to link a PhysicsVehicle to a spatial.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class VehicleControl extends PhysicsVehicle implements PhysicsControl, JmeCloneable {
|
public class VehicleControl extends PhysicsVehicle implements PhysicsControl, JmeCloneable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spatial to which this control is added, or null if none
|
||||||
|
*/
|
||||||
protected Spatial spatial;
|
protected Spatial spatial;
|
||||||
|
/**
|
||||||
|
* true→control is enabled, false→control is disabled
|
||||||
|
*/
|
||||||
protected boolean enabled = true;
|
protected boolean enabled = true;
|
||||||
|
/**
|
||||||
|
* space to which the vehicle is (or would be) added
|
||||||
|
*/
|
||||||
protected PhysicsSpace space = null;
|
protected PhysicsSpace space = null;
|
||||||
|
/**
|
||||||
|
* true→vehicle is added to the physics space, false→not added
|
||||||
|
*/
|
||||||
protected boolean added = false;
|
protected boolean added = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public VehicleControl() {
|
public VehicleControl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PhysicsNode with the supplied collision shape
|
* Instantiate an enabled control with mass=1 and the specified collision
|
||||||
* @param shape
|
* shape.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public VehicleControl(CollisionShape shape) {
|
public VehicleControl(CollisionShape shape) {
|
||||||
super(shape);
|
super(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled with the specified collision shape and mass.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
* @param mass (>0)
|
||||||
|
*/
|
||||||
public VehicleControl(CollisionShape shape, float mass) {
|
public VehicleControl(CollisionShape shape, float mass) {
|
||||||
super(shape, mass);
|
super(shape, mass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether physics-space coordinates should match the spatial's local
|
||||||
|
* coordinates.
|
||||||
|
*
|
||||||
|
* @return true if matching local coordinates, false if matching world
|
||||||
|
* coordinates
|
||||||
|
*/
|
||||||
public boolean isApplyPhysicsLocal() {
|
public boolean isApplyPhysicsLocal() {
|
||||||
return motionState.isApplyPhysicsLocal();
|
return motionState.isApplyPhysicsLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to true, the physics coordinates will be applied to the local
|
* Alter whether physics-space coordinates should match the spatial's local
|
||||||
* translation of the Spatial
|
* coordinates.
|
||||||
* @param applyPhysicsLocal
|
*
|
||||||
|
* @param applyPhysicsLocal true→match local coordinates,
|
||||||
|
* false→match world coordinates (default=false)
|
||||||
*/
|
*/
|
||||||
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
||||||
motionState.setApplyPhysicsLocal(applyPhysicsLocal);
|
motionState.setApplyPhysicsLocal(applyPhysicsLocal);
|
||||||
@ -107,13 +143,22 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
return spatial.getWorldRotation();
|
return spatial.getWorldRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
/**
|
||||||
|
* Clone this control for a different spatial. No longer used as of JME 3.1.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial for the clone to control (or null)
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Control cloneForSpatial(Spatial spatial) {
|
public Control cloneForSpatial(Spatial spatial) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Create a shallow clone for the JME cloner.
|
||||||
|
*
|
||||||
|
* @return a new control (not null)
|
||||||
|
*/
|
||||||
public Object jmeClone() {
|
public Object jmeClone() {
|
||||||
VehicleControl control = new VehicleControl(collisionShape, mass);
|
VehicleControl control = new VehicleControl(collisionShape, mass);
|
||||||
control.setAngularFactor(getAngularFactor());
|
control.setAngularFactor(getAngularFactor());
|
||||||
@ -161,6 +206,15 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
|
||||||
|
* shallow-cloned control into a deep-cloned one, using the specified cloner
|
||||||
|
* and original to resolve copied fields.
|
||||||
|
*
|
||||||
|
* @param cloner the cloner currently cloning this control (not null)
|
||||||
|
* @param original the control from which this control was shallow-cloned
|
||||||
|
* (unused)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void cloneFields( Cloner cloner, Object original ) {
|
public void cloneFields( Cloner cloner, Object original ) {
|
||||||
this.spatial = cloner.clone(spatial);
|
this.spatial = cloner.clone(spatial);
|
||||||
@ -171,6 +225,11 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled.
|
||||||
|
*
|
||||||
|
* @param spatial spatial to control (or null)
|
||||||
|
*/
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
this.spatial = spatial;
|
this.spatial = spatial;
|
||||||
setUserObject(spatial);
|
setUserObject(spatial);
|
||||||
@ -181,6 +240,15 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
setPhysicsRotation(getSpatialRotation());
|
setPhysicsRotation(getSpatialRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable this control.
|
||||||
|
* <p>
|
||||||
|
* When the control is disabled, the vehicle is removed from physics space.
|
||||||
|
* When the control is enabled again, the physics object is moved to the
|
||||||
|
* spatial's location and then added to the physics space.
|
||||||
|
*
|
||||||
|
* @param enabled true→enable the control, false→disable it
|
||||||
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
if (space != null) {
|
if (space != null) {
|
||||||
@ -198,10 +266,21 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this control is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame, during the logical-state
|
||||||
|
* update, provided the control is added to a scene.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
if (enabled && spatial != null) {
|
if (enabled && spatial != null) {
|
||||||
if (getMotionState().applyTransform(spatial)) {
|
if (getMotionState().applyTransform(spatial)) {
|
||||||
@ -213,6 +292,14 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per view port per frame, provided the
|
||||||
|
* control is added to a scene. Should be invoked only by a subclass or by
|
||||||
|
* the RenderManager.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
public void render(RenderManager rm, ViewPort vp) {
|
public void render(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,10 +330,21 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
space = newSpace;
|
space = newSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the physics space to which the vehicle is (or would be) added.
|
||||||
|
*
|
||||||
|
* @return the pre-existing space, or null for none
|
||||||
|
*/
|
||||||
public PhysicsSpace getPhysicsSpace() {
|
public PhysicsSpace getPhysicsSpace() {
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this control, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -256,6 +354,12 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
|
|||||||
oc.write(spatial, "spatial", null);
|
oc.write(spatial, "spatial", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this control, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,11 +34,17 @@ package com.jme3.bullet.control.ragdoll;
|
|||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Example ragdoll presets for a typical humanoid skeleton.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public class HumanoidRagdollPreset extends RagdollPreset {
|
public class HumanoidRagdollPreset extends RagdollPreset {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the map from bone names to joint presets.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void initBoneMap() {
|
protected void initBoneMap() {
|
||||||
boneMap.put("head", new JointPreset(FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI));
|
boneMap.put("head", new JointPreset(FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI));
|
||||||
@ -59,6 +65,9 @@ public class HumanoidRagdollPreset extends RagdollPreset {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the lexicon.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void initLexicon() {
|
protected void initLexicon() {
|
||||||
LexiconEntry entry = new LexiconEntry();
|
LexiconEntry entry = new LexiconEntry();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -43,14 +43,35 @@ import java.util.logging.Logger;
|
|||||||
*/
|
*/
|
||||||
public abstract class RagdollPreset {
|
public abstract class RagdollPreset {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message logger for this class
|
||||||
|
*/
|
||||||
protected static final Logger logger = Logger.getLogger(RagdollPreset.class.getName());
|
protected static final Logger logger = Logger.getLogger(RagdollPreset.class.getName());
|
||||||
|
/**
|
||||||
|
* map bone names to joint presets
|
||||||
|
*/
|
||||||
protected Map<String, JointPreset> boneMap = new HashMap<String, JointPreset>();
|
protected Map<String, JointPreset> boneMap = new HashMap<String, JointPreset>();
|
||||||
|
/**
|
||||||
|
* lexicon to map bone names to entries
|
||||||
|
*/
|
||||||
protected Map<String, LexiconEntry> lexicon = new HashMap<String, LexiconEntry>();
|
protected Map<String, LexiconEntry> lexicon = new HashMap<String, LexiconEntry>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the map from bone names to joint presets.
|
||||||
|
*/
|
||||||
protected abstract void initBoneMap();
|
protected abstract void initBoneMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the lexicon.
|
||||||
|
*/
|
||||||
protected abstract void initLexicon();
|
protected abstract void initLexicon();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the preset for the named bone to the specified joint.
|
||||||
|
*
|
||||||
|
* @param boneName name
|
||||||
|
* @param joint where to apply the preset (not null, modified)
|
||||||
|
*/
|
||||||
public void setupJointForBone(String boneName, SixDofJoint joint) {
|
public void setupJointForBone(String boneName, SixDofJoint joint) {
|
||||||
|
|
||||||
if (boneMap.isEmpty()) {
|
if (boneMap.isEmpty()) {
|
||||||
@ -87,14 +108,30 @@ public abstract class RagdollPreset {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range of motion for a joint.
|
||||||
|
*/
|
||||||
protected class JointPreset {
|
protected class JointPreset {
|
||||||
|
|
||||||
private float maxX, minX, maxY, minY, maxZ, minZ;
|
private float maxX, minX, maxY, minY, maxZ, minZ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a preset with no motion allowed.
|
||||||
|
*/
|
||||||
public JointPreset() {
|
public JointPreset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public JointPreset(float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
|
public JointPreset(float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
|
||||||
|
/**
|
||||||
|
* Instantiate a preset with the specified range of motion.
|
||||||
|
*
|
||||||
|
* @param maxX the maximum rotation on the X axis (in radians)
|
||||||
|
* @param minX the minimum rotation on the X axis (in radians)
|
||||||
|
* @param maxY the maximum rotation on the Y axis (in radians)
|
||||||
|
* @param minY the minimum rotation on the Y axis (in radians)
|
||||||
|
* @param maxZ the maximum rotation on the Z axis (in radians)
|
||||||
|
* @param minZ the minimum rotation on the Z axis (in radians)
|
||||||
|
*/
|
||||||
this.maxX = maxX;
|
this.maxX = maxX;
|
||||||
this.minX = minX;
|
this.minX = minX;
|
||||||
this.maxY = maxY;
|
this.maxY = maxY;
|
||||||
@ -103,6 +140,11 @@ public abstract class RagdollPreset {
|
|||||||
this.minZ = minZ;
|
this.minZ = minZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this preset to the specified joint.
|
||||||
|
*
|
||||||
|
* @param joint where to apply (not null, modified)
|
||||||
|
*/
|
||||||
public void setupJoint(SixDofJoint joint) {
|
public void setupJoint(SixDofJoint joint) {
|
||||||
joint.getRotationalLimitMotor(0).setHiLimit(maxX);
|
joint.getRotationalLimitMotor(0).setHiLimit(maxX);
|
||||||
joint.getRotationalLimitMotor(0).setLoLimit(minX);
|
joint.getRotationalLimitMotor(0).setLoLimit(minX);
|
||||||
@ -113,13 +155,28 @@ public abstract class RagdollPreset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One entry in a bone lexicon.
|
||||||
|
*/
|
||||||
protected class LexiconEntry extends HashMap<String, Integer> {
|
protected class LexiconEntry extends HashMap<String, Integer> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a synonym with the specified score.
|
||||||
|
*
|
||||||
|
* @param word a substring that might occur in a bone name (not null)
|
||||||
|
* @param score larger value means more likely to correspond
|
||||||
|
*/
|
||||||
public void addSynonym(String word, int score) {
|
public void addSynonym(String word, int score) {
|
||||||
put(word.toLowerCase(), score);
|
put(word.toLowerCase(), score);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScore(String word) {
|
public int getScore(String word) {
|
||||||
|
/**
|
||||||
|
* Calculate a total score for the specified bone name.
|
||||||
|
*
|
||||||
|
* @param name the name of a bone (not null)
|
||||||
|
* @return total score: larger value means more likely to correspond
|
||||||
|
*/
|
||||||
int score = 0;
|
int score = 0;
|
||||||
String searchWord = word.toLowerCase();
|
String searchWord = word.toLowerCase();
|
||||||
for (String key : this.keySet()) {
|
for (String key : this.keySet()) {
|
||||||
|
@ -48,11 +48,25 @@ import java.nio.FloatBuffer;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Utility methods used by KinematicRagdollControl.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public class RagdollUtils {
|
public class RagdollUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the limits of the specified 6-DOF joint.
|
||||||
|
*
|
||||||
|
* @param joint which joint to alter (not null)
|
||||||
|
* @param maxX the maximum rotation on the X axis (in radians)
|
||||||
|
* @param minX the minimum rotation on the X axis (in radians)
|
||||||
|
* @param maxY the maximum rotation on the Y axis (in radians)
|
||||||
|
* @param minY the minimum rotation on the Y axis (in radians)
|
||||||
|
* @param maxZ the maximum rotation on the Z axis (in radians)
|
||||||
|
* @param minZ the minimum rotation on the Z axis (in radians)
|
||||||
|
*/
|
||||||
public static void setJointLimit(SixDofJoint joint, float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
|
public static void setJointLimit(SixDofJoint joint, float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
|
||||||
|
|
||||||
joint.getRotationalLimitMotor(0).setHiLimit(maxX);
|
joint.getRotationalLimitMotor(0).setHiLimit(maxX);
|
||||||
@ -63,6 +77,12 @@ public class RagdollUtils {
|
|||||||
joint.getRotationalLimitMotor(2).setLoLimit(minZ);
|
joint.getRotationalLimitMotor(2).setLoLimit(minZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a map of mesh vertices in a subtree of the scene graph.
|
||||||
|
*
|
||||||
|
* @param model the root of the subtree (may be null)
|
||||||
|
* @return a new map (not null)
|
||||||
|
*/
|
||||||
public static Map<Integer, List<Float>> buildPointMap(Spatial model) {
|
public static Map<Integer, List<Float>> buildPointMap(Spatial model) {
|
||||||
|
|
||||||
|
|
||||||
@ -122,14 +142,15 @@ public class RagdollUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a hull collision shape from linked vertices to this bone.
|
* Create a hull collision shape from linked vertices to this bone. Vertices
|
||||||
* Vertices have to be previously gathered in a map using buildPointMap method
|
* must have previously been gathered using buildPointMap().
|
||||||
*
|
*
|
||||||
* @param pointsMap
|
* @param pointsMap map from bone indices to coordinates (not null,
|
||||||
* @param boneIndices
|
* unaffected)
|
||||||
* @param initialScale
|
* @param boneIndices (not null, unaffected)
|
||||||
* @param initialPosition
|
* @param initialScale scale factors (not null, unaffected)
|
||||||
* @return
|
* @param initialPosition location (not null, unaffected)
|
||||||
|
* @return a new shape (not null)
|
||||||
*/
|
*/
|
||||||
public static HullCollisionShape makeShapeFromPointMap(Map<Integer, List<Float>> pointsMap, List<Integer> boneIndices, Vector3f initialScale, Vector3f initialPosition) {
|
public static HullCollisionShape makeShapeFromPointMap(Map<Integer, List<Float>> pointsMap, List<Integer> boneIndices, Vector3f initialScale, Vector3f initialPosition) {
|
||||||
|
|
||||||
@ -160,7 +181,15 @@ public class RagdollUtils {
|
|||||||
return new HullCollisionShape(p);
|
return new HullCollisionShape(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns the list of bone indices of the given bone and its child (if they are not in the boneList)
|
/**
|
||||||
|
* Enumerate the bone indices of the specified bone and all its descendents.
|
||||||
|
*
|
||||||
|
* @param bone the input bone (not null)
|
||||||
|
* @param skeleton the skeleton containing the bone (not null)
|
||||||
|
* @param boneList a set of bone names (not null, unaffected)
|
||||||
|
*
|
||||||
|
* @return a new list (not null)
|
||||||
|
*/
|
||||||
public static List<Integer> getBoneIndices(Bone bone, Skeleton skeleton, Set<String> boneList) {
|
public static List<Integer> getBoneIndices(Bone bone, Skeleton skeleton, Set<String> boneList) {
|
||||||
List<Integer> list = new LinkedList<Integer>();
|
List<Integer> list = new LinkedList<Integer>();
|
||||||
if (boneList.isEmpty()) {
|
if (boneList.isEmpty()) {
|
||||||
@ -178,13 +207,13 @@ public class RagdollUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a hull collision shape from linked vertices to this bone.
|
* Create a hull collision shape from linked vertices to this bone.
|
||||||
*
|
*
|
||||||
* @param model
|
* @param model the model on which to base the shape
|
||||||
* @param boneIndices
|
* @param boneIndices indices of relevant bones (not null, unaffected)
|
||||||
* @param initialScale
|
* @param initialScale scale factors
|
||||||
* @param initialPosition
|
* @param initialPosition location
|
||||||
* @param weightThreshold
|
* @param weightThreshold minimum weight for inclusion
|
||||||
* @return
|
* @return a new shape
|
||||||
*/
|
*/
|
||||||
public static HullCollisionShape makeShapeFromVerticeWeights(Spatial model, List<Integer> boneIndices, Vector3f initialScale, Vector3f initialPosition, float weightThreshold) {
|
public static HullCollisionShape makeShapeFromVerticeWeights(Spatial model, List<Integer> boneIndices, Vector3f initialScale, Vector3f initialPosition, float weightThreshold) {
|
||||||
|
|
||||||
@ -216,12 +245,18 @@ public class RagdollUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns a list of points for the given bone
|
* Enumerate vertices that meet the weight threshold for the indexed bone.
|
||||||
* @param mesh
|
*
|
||||||
* @param boneIndex
|
* @param mesh the mesh to analyze (not null)
|
||||||
* @param offset
|
* @param boneIndex the index of the bone (≥0)
|
||||||
* @param link
|
* @param initialScale a scale applied to vertex positions (not null,
|
||||||
* @return
|
* unaffected)
|
||||||
|
* @param offset an offset subtracted from vertex positions (not null,
|
||||||
|
* unaffected)
|
||||||
|
* @param weightThreshold the minimum bone weight for inclusion in the
|
||||||
|
* result (≥0, ≤1)
|
||||||
|
* @return a new list of vertex coordinates (not null, length a multiple of
|
||||||
|
* 3)
|
||||||
*/
|
*/
|
||||||
private static List<Float> getPoints(Mesh mesh, int boneIndex, Vector3f initialScale, Vector3f offset, float weightThreshold) {
|
private static List<Float> getPoints(Mesh mesh, int boneIndex, Vector3f initialScale, Vector3f offset, float weightThreshold) {
|
||||||
|
|
||||||
@ -265,12 +300,16 @@ public class RagdollUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a bone position and rotation.
|
* Updates a bone position and rotation. if the child bones are not in the
|
||||||
* if the child bones are not in the bone list this means, they are not associated with a physics shape.
|
* bone list this means, they are not associated with a physics shape. So
|
||||||
* So they have to be updated
|
* they have to be updated
|
||||||
|
*
|
||||||
* @param bone the bone
|
* @param bone the bone
|
||||||
* @param pos the position
|
* @param pos the position
|
||||||
* @param rot the rotation
|
* @param rot the rotation
|
||||||
|
* @param restoreBoneControl true → user-control flag should be set
|
||||||
|
* @param boneList the names of all bones without collision shapes (not
|
||||||
|
* null, unaffected)
|
||||||
*/
|
*/
|
||||||
public static void setTransform(Bone bone, Vector3f pos, Quaternion rot, boolean restoreBoneControl, Set<String> boneList) {
|
public static void setTransform(Bone bone, Vector3f pos, Quaternion rot, boolean restoreBoneControl, Set<String> boneList) {
|
||||||
//we ensure that we have the control
|
//we ensure that we have the control
|
||||||
@ -292,6 +331,12 @@ public class RagdollUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the user-control flags of a bone and all its descendents.
|
||||||
|
*
|
||||||
|
* @param bone the ancestor bone (not null, modified)
|
||||||
|
* @param bool true to enable user control, false to disable
|
||||||
|
*/
|
||||||
public static void setUserControl(Bone bone, boolean bool) {
|
public static void setUserControl(Bone bone, boolean bool) {
|
||||||
bone.setUserControl(bool);
|
bone.setUserControl(bool);
|
||||||
for (Bone child : bone.getChildren()) {
|
for (Bone child : bone.getChildren()) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -37,14 +37,27 @@ import com.jme3.scene.Spatial;
|
|||||||
import com.jme3.scene.control.AbstractControl;
|
import com.jme3.scene.control.AbstractControl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The abstract base class for physics-debug controls (such as
|
||||||
|
* BulletRigidBodyDebugControl) used to visualize individual collision objects
|
||||||
|
* and joints.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPhysicsDebugControl extends AbstractControl {
|
public abstract class AbstractPhysicsDebugControl extends AbstractControl {
|
||||||
|
|
||||||
private final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
private final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* the app state that this control serves
|
||||||
|
*/
|
||||||
protected final BulletDebugAppState debugAppState;
|
protected final BulletDebugAppState debugAppState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control to serve the specified debug app state.
|
||||||
|
*
|
||||||
|
* @param debugAppState which app state (not null, alias created)
|
||||||
|
*/
|
||||||
public AbstractPhysicsDebugControl(BulletDebugAppState debugAppState) {
|
public AbstractPhysicsDebugControl(BulletDebugAppState debugAppState) {
|
||||||
this.debugAppState = debugAppState;
|
this.debugAppState = debugAppState;
|
||||||
}
|
}
|
||||||
@ -55,10 +68,27 @@ public abstract class AbstractPhysicsDebugControl extends AbstractControl {
|
|||||||
@Override
|
@Override
|
||||||
protected abstract void controlUpdate(float tpf);
|
protected abstract void controlUpdate(float tpf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the specified location and orientation to the controlled spatial.
|
||||||
|
*
|
||||||
|
* @param worldLocation location vector (in physics-space coordinates, not
|
||||||
|
* null, unaffected)
|
||||||
|
* @param worldRotation orientation (in physics-space coordinates, not null,
|
||||||
|
* unaffected)
|
||||||
|
*/
|
||||||
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation) {
|
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation) {
|
||||||
applyPhysicsTransform(worldLocation, worldRotation, this.spatial);
|
applyPhysicsTransform(worldLocation, worldRotation, this.spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the specified location and orientation to the specified spatial.
|
||||||
|
*
|
||||||
|
* @param worldLocation location vector (in physics-space coordinates, not
|
||||||
|
* null, unaffected)
|
||||||
|
* @param worldRotation orientation (in physics-space coordinates, not null,
|
||||||
|
* unaffected)
|
||||||
|
* @param spatial where to apply (may be null)
|
||||||
|
*/
|
||||||
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation, Spatial spatial) {
|
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation, Spatial spatial) {
|
||||||
if (spatial != null) {
|
if (spatial != null) {
|
||||||
Vector3f localLocation = spatial.getLocalTranslation();
|
Vector3f localLocation = spatial.getLocalTranslation();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,16 +42,37 @@ import com.jme3.scene.Node;
|
|||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics-debug control used to visualize a PhysicsCharacter.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletCharacterDebugControl extends AbstractPhysicsDebugControl {
|
public class BulletCharacterDebugControl extends AbstractPhysicsDebugControl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* character to visualize (not null)
|
||||||
|
*/
|
||||||
protected final PhysicsCharacter body;
|
protected final PhysicsCharacter body;
|
||||||
|
/**
|
||||||
|
* temporary storage for physics location
|
||||||
|
*/
|
||||||
protected final Vector3f location = new Vector3f();
|
protected final Vector3f location = new Vector3f();
|
||||||
protected final Quaternion rotation = new Quaternion();
|
protected final Quaternion rotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* shape for which geom was generated
|
||||||
|
*/
|
||||||
protected CollisionShape myShape;
|
protected CollisionShape myShape;
|
||||||
|
/**
|
||||||
|
* geometry to visualize myShape (not null)
|
||||||
|
*/
|
||||||
protected Spatial geom;
|
protected Spatial geom;
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control to visualize the specified character.
|
||||||
|
*
|
||||||
|
* @param debugAppState which app state (not null, alias created)
|
||||||
|
* @param body the character to visualize (not null, alias created)
|
||||||
|
*/
|
||||||
|
|
||||||
public BulletCharacterDebugControl(BulletDebugAppState debugAppState, PhysicsCharacter body) {
|
public BulletCharacterDebugControl(BulletDebugAppState debugAppState, PhysicsCharacter body) {
|
||||||
super(debugAppState);
|
super(debugAppState);
|
||||||
@ -61,6 +82,13 @@ public class BulletCharacterDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geom.setMaterial(debugAppState.DEBUG_PINK);
|
geom.setMaterial(debugAppState.DEBUG_PINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (spatial != null && spatial instanceof Node) {
|
if (spatial != null && spatial instanceof Node) {
|
||||||
@ -73,6 +101,13 @@ public class BulletCharacterDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
super.setSpatial(spatial);
|
super.setSpatial(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is enabled and added to a scene. Should be
|
||||||
|
* invoked only by a subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
if(myShape != body.getCollisionShape()){
|
if(myShape != body.getCollisionShape()){
|
||||||
@ -86,6 +121,14 @@ public class BulletCharacterDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geom.setLocalScale(body.getCollisionShape().getScale());
|
geom.setLocalScale(body.getCollisionShape().getScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once port per frame, provided the
|
||||||
|
* control is enabled and added to a scene. Should be invoked only by a
|
||||||
|
* subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -55,31 +55,84 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* An app state to manage a debug visualization of a physics space.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletDebugAppState extends AbstractAppState {
|
public class BulletDebugAppState extends AbstractAppState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message logger for this class
|
||||||
|
*/
|
||||||
protected static final Logger logger = Logger.getLogger(BulletDebugAppState.class.getName());
|
protected static final Logger logger = Logger.getLogger(BulletDebugAppState.class.getName());
|
||||||
|
/**
|
||||||
|
* limit which objects are visualized, or null to visualize all objects
|
||||||
|
*/
|
||||||
protected DebugAppStateFilter filter;
|
protected DebugAppStateFilter filter;
|
||||||
protected Application app;
|
protected Application app;
|
||||||
protected AssetManager assetManager;
|
protected AssetManager assetManager;
|
||||||
|
/**
|
||||||
|
* physics space to visualize (not null)
|
||||||
|
*/
|
||||||
protected final PhysicsSpace space;
|
protected final PhysicsSpace space;
|
||||||
|
/**
|
||||||
|
* scene-graph node to parent the geometries
|
||||||
|
*/
|
||||||
protected final Node physicsDebugRootNode = new Node("Physics Debug Root Node");
|
protected final Node physicsDebugRootNode = new Node("Physics Debug Root Node");
|
||||||
|
/**
|
||||||
|
* view port in which to render (not null)
|
||||||
|
*/
|
||||||
protected ViewPort viewPort;
|
protected ViewPort viewPort;
|
||||||
protected RenderManager rm;
|
protected RenderManager rm;
|
||||||
|
/**
|
||||||
|
* material for inactive rigid bodies
|
||||||
|
*/
|
||||||
public Material DEBUG_BLUE;
|
public Material DEBUG_BLUE;
|
||||||
public Material DEBUG_RED;
|
public Material DEBUG_RED;
|
||||||
|
/**
|
||||||
|
* material for joints
|
||||||
|
*/
|
||||||
public Material DEBUG_GREEN;
|
public Material DEBUG_GREEN;
|
||||||
|
/**
|
||||||
|
* material for ghosts
|
||||||
|
*/
|
||||||
public Material DEBUG_YELLOW;
|
public Material DEBUG_YELLOW;
|
||||||
|
/**
|
||||||
|
* material for vehicles and active rigid bodies
|
||||||
|
*/
|
||||||
public Material DEBUG_MAGENTA;
|
public Material DEBUG_MAGENTA;
|
||||||
|
/**
|
||||||
|
* material for physics characters
|
||||||
|
*/
|
||||||
public Material DEBUG_PINK;
|
public Material DEBUG_PINK;
|
||||||
|
/**
|
||||||
|
* map rigid bodies to visualizations
|
||||||
|
*/
|
||||||
protected HashMap<PhysicsRigidBody, Spatial> bodies = new HashMap<PhysicsRigidBody, Spatial>();
|
protected HashMap<PhysicsRigidBody, Spatial> bodies = new HashMap<PhysicsRigidBody, Spatial>();
|
||||||
|
/**
|
||||||
|
* map joints to visualizations
|
||||||
|
*/
|
||||||
protected HashMap<PhysicsJoint, Spatial> joints = new HashMap<PhysicsJoint, Spatial>();
|
protected HashMap<PhysicsJoint, Spatial> joints = new HashMap<PhysicsJoint, Spatial>();
|
||||||
|
/**
|
||||||
|
* map ghosts to visualizations
|
||||||
|
*/
|
||||||
protected HashMap<PhysicsGhostObject, Spatial> ghosts = new HashMap<PhysicsGhostObject, Spatial>();
|
protected HashMap<PhysicsGhostObject, Spatial> ghosts = new HashMap<PhysicsGhostObject, Spatial>();
|
||||||
|
/**
|
||||||
|
* map physics characters to visualizations
|
||||||
|
*/
|
||||||
protected HashMap<PhysicsCharacter, Spatial> characters = new HashMap<PhysicsCharacter, Spatial>();
|
protected HashMap<PhysicsCharacter, Spatial> characters = new HashMap<PhysicsCharacter, Spatial>();
|
||||||
|
/**
|
||||||
|
* map vehicles to visualizations
|
||||||
|
*/
|
||||||
protected HashMap<PhysicsVehicle, Spatial> vehicles = new HashMap<PhysicsVehicle, Spatial>();
|
protected HashMap<PhysicsVehicle, Spatial> vehicles = new HashMap<PhysicsVehicle, Spatial>();
|
||||||
|
/**
|
||||||
|
* Instantiate an app state to visualize the specified space. This constructor should be invoked only by
|
||||||
|
* BulletAppState.
|
||||||
|
*
|
||||||
|
* @param space physics space to visualize (not null, alias created)
|
||||||
|
*/
|
||||||
public BulletDebugAppState(PhysicsSpace space) {
|
public BulletDebugAppState(PhysicsSpace space) {
|
||||||
this.space = space;
|
this.space = space;
|
||||||
}
|
}
|
||||||
@ -88,10 +141,22 @@ public class BulletDebugAppState extends AbstractAppState {
|
|||||||
return new DebugTools(assetManager);
|
return new DebugTools(assetManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which objects are visualized.
|
||||||
|
*
|
||||||
|
* @param filter the desired filter, or or null to visualize all objects
|
||||||
|
*/
|
||||||
public void setFilter(DebugAppStateFilter filter) {
|
public void setFilter(DebugAppStateFilter filter) {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this state prior to its 1st update. Should be invoked only by
|
||||||
|
* a subclass or by the AppStateManager.
|
||||||
|
*
|
||||||
|
* @param stateManager the manager for this state (not null)
|
||||||
|
* @param app the application which owns this state (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize(AppStateManager stateManager, Application app) {
|
public void initialize(AppStateManager stateManager, Application app) {
|
||||||
super.initialize(stateManager, app);
|
super.initialize(stateManager, app);
|
||||||
@ -105,12 +170,25 @@ public class BulletDebugAppState extends AbstractAppState {
|
|||||||
viewPort.attachScene(physicsDebugRootNode);
|
viewPort.attachScene(physicsDebugRootNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition this state from terminating to detached. Should be invoked
|
||||||
|
* only by a subclass or by the AppStateManager. Invoked once for each time
|
||||||
|
* {@link #initialize(com.jme3.app.state.AppStateManager, com.jme3.app.Application)}
|
||||||
|
* is invoked.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
rm.removeMainView(viewPort);
|
rm.removeMainView(viewPort);
|
||||||
super.cleanup();
|
super.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this state prior to rendering. Should be invoked only by a
|
||||||
|
* subclass or by the AppStateManager. Invoked once per frame, provided the
|
||||||
|
* state is attached and enabled.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
super.update(tpf);
|
super.update(tpf);
|
||||||
@ -125,6 +203,13 @@ public class BulletDebugAppState extends AbstractAppState {
|
|||||||
physicsDebugRootNode.updateGeometricState();
|
physicsDebugRootNode.updateGeometricState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this state. Should be invoked only by a subclass or by the
|
||||||
|
* AppStateManager. Invoked once per frame, provided the state is attached
|
||||||
|
* and enabled.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(RenderManager rm) {
|
public void render(RenderManager rm) {
|
||||||
super.render(rm);
|
super.render(rm);
|
||||||
@ -133,6 +218,11 @@ public class BulletDebugAppState extends AbstractAppState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the materials.
|
||||||
|
*
|
||||||
|
* @param app the application which owns this state (not null)
|
||||||
|
*/
|
||||||
private void setupMaterials(Application app) {
|
private void setupMaterials(Application app) {
|
||||||
AssetManager manager = app.getAssetManager();
|
AssetManager manager = app.getAssetManager();
|
||||||
DEBUG_BLUE = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
DEBUG_BLUE = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
@ -311,14 +401,14 @@ public class BulletDebugAppState extends AbstractAppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that allows filtering out objects from the debug display
|
* Interface to restrict which physics objects are visualized.
|
||||||
*/
|
*/
|
||||||
public static interface DebugAppStateFilter {
|
public static interface DebugAppStateFilter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries an object to be displayed
|
* Test whether the specified physics object should be displayed.
|
||||||
*
|
*
|
||||||
* @param obj The object to be displayed
|
* @param obj the joint or collision object to test (unaffected)
|
||||||
* @return return true if the object should be displayed, false if not
|
* @return return true if the object should be displayed, false if not
|
||||||
*/
|
*/
|
||||||
public boolean displayObject(Object obj);
|
public boolean displayObject(Object obj);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,17 +42,41 @@ import com.jme3.scene.Node;
|
|||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics-debug control used to visualize a PhysicsGhostObject.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletGhostObjectDebugControl extends AbstractPhysicsDebugControl {
|
public class BulletGhostObjectDebugControl extends AbstractPhysicsDebugControl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ghost object to visualize (not null)
|
||||||
|
*/
|
||||||
protected final PhysicsGhostObject body;
|
protected final PhysicsGhostObject body;
|
||||||
|
/**
|
||||||
|
* temporary storage for physics location
|
||||||
|
*/
|
||||||
protected final Vector3f location = new Vector3f();
|
protected final Vector3f location = new Vector3f();
|
||||||
|
/**
|
||||||
|
* temporary storage for physics rotation
|
||||||
|
*/
|
||||||
protected final Quaternion rotation = new Quaternion();
|
protected final Quaternion rotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* shape for which geom was generated (not null)
|
||||||
|
*/
|
||||||
protected CollisionShape myShape;
|
protected CollisionShape myShape;
|
||||||
|
/**
|
||||||
|
* geometry to visualize myShape (not null)
|
||||||
|
*/
|
||||||
protected Spatial geom;
|
protected Spatial geom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control to visualize the specified ghost object.
|
||||||
|
*
|
||||||
|
* @param debugAppState which app state (not null, alias created)
|
||||||
|
* @param body which object to visualize (not null, alias created)
|
||||||
|
*/
|
||||||
public BulletGhostObjectDebugControl(BulletDebugAppState debugAppState, PhysicsGhostObject body) {
|
public BulletGhostObjectDebugControl(BulletDebugAppState debugAppState, PhysicsGhostObject body) {
|
||||||
super(debugAppState);
|
super(debugAppState);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
@ -63,6 +87,13 @@ public class BulletGhostObjectDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geom.setMaterial(debugAppState.DEBUG_YELLOW);
|
geom.setMaterial(debugAppState.DEBUG_YELLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (spatial != null && spatial instanceof Node) {
|
if (spatial != null && spatial instanceof Node) {
|
||||||
@ -75,6 +106,13 @@ public class BulletGhostObjectDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
super.setSpatial(spatial);
|
super.setSpatial(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is enabled and added to a scene. Should be
|
||||||
|
* invoked only by a subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
if (myShape != body.getCollisionShape()) {
|
if (myShape != body.getCollisionShape()) {
|
||||||
@ -88,6 +126,14 @@ public class BulletGhostObjectDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geom.setLocalScale(body.getCollisionShape().getScale());
|
geom.setLocalScale(body.getCollisionShape().getScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per frame, provided the
|
||||||
|
* control is enabled and added to a scene. Should be invoked only by a
|
||||||
|
* subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -43,6 +43,9 @@ import com.jme3.scene.Spatial;
|
|||||||
import com.jme3.scene.debug.Arrow;
|
import com.jme3.scene.debug.Arrow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics-debug control used to visualize a PhysicsJoint.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
@ -58,6 +61,12 @@ public class BulletJointDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
protected final Vector3f offA = new Vector3f();
|
protected final Vector3f offA = new Vector3f();
|
||||||
protected final Vector3f offB = new Vector3f();
|
protected final Vector3f offB = new Vector3f();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control to visualize the specified joint.
|
||||||
|
*
|
||||||
|
* @param debugAppState which app state (not null, alias created)
|
||||||
|
* @param body the joint to visualize (not null, alias created)
|
||||||
|
*/
|
||||||
public BulletJointDebugControl(BulletDebugAppState debugAppState, PhysicsJoint body) {
|
public BulletJointDebugControl(BulletDebugAppState debugAppState, PhysicsJoint body) {
|
||||||
super(debugAppState);
|
super(debugAppState);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
@ -71,6 +80,13 @@ public class BulletJointDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geomB.setMaterial(debugAppState.DEBUG_GREEN);
|
geomB.setMaterial(debugAppState.DEBUG_GREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (spatial != null && spatial instanceof Node) {
|
if (spatial != null && spatial instanceof Node) {
|
||||||
@ -85,6 +101,13 @@ public class BulletJointDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
super.setSpatial(spatial);
|
super.setSpatial(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is enabled and added to a scene. Should be
|
||||||
|
* invoked only by a subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
body.getBodyA().getPhysicsLocation(a.getTranslation());
|
body.getBodyA().getPhysicsLocation(a.getTranslation());
|
||||||
@ -100,6 +123,14 @@ public class BulletJointDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
arrowB.setArrowExtent(body.getPivotB());
|
arrowB.setArrowExtent(body.getPivotB());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per frame, provided the
|
||||||
|
* control is enabled and added to a scene. Should be invoked only by a
|
||||||
|
* subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,17 +42,41 @@ import com.jme3.scene.Node;
|
|||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics-debug control used to visualize a PhysicsRigidBody.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletRigidBodyDebugControl extends AbstractPhysicsDebugControl {
|
public class BulletRigidBodyDebugControl extends AbstractPhysicsDebugControl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rigid body to visualize (not null)
|
||||||
|
*/
|
||||||
protected final PhysicsRigidBody body;
|
protected final PhysicsRigidBody body;
|
||||||
|
/**
|
||||||
|
* temporary storage for physics location
|
||||||
|
*/
|
||||||
protected final Vector3f location = new Vector3f();
|
protected final Vector3f location = new Vector3f();
|
||||||
|
/**
|
||||||
|
* temporary storage for physics rotation
|
||||||
|
*/
|
||||||
protected final Quaternion rotation = new Quaternion();
|
protected final Quaternion rotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* shape for which geom was generated (not null)
|
||||||
|
*/
|
||||||
protected CollisionShape myShape;
|
protected CollisionShape myShape;
|
||||||
|
/**
|
||||||
|
* geometry to visualize myShape (not null)
|
||||||
|
*/
|
||||||
protected Spatial geom;
|
protected Spatial geom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control to visualize the specified body.
|
||||||
|
*
|
||||||
|
* @param debugAppState which app state (not null, alias created)
|
||||||
|
* @param body which body to visualize (not null, alias created)
|
||||||
|
*/
|
||||||
public BulletRigidBodyDebugControl(BulletDebugAppState debugAppState, PhysicsRigidBody body) {
|
public BulletRigidBodyDebugControl(BulletDebugAppState debugAppState, PhysicsRigidBody body) {
|
||||||
super(debugAppState);
|
super(debugAppState);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
@ -62,6 +86,13 @@ public class BulletRigidBodyDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geom.setMaterial(debugAppState.DEBUG_BLUE);
|
geom.setMaterial(debugAppState.DEBUG_BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (spatial != null && spatial instanceof Node) {
|
if (spatial != null && spatial instanceof Node) {
|
||||||
@ -74,6 +105,13 @@ public class BulletRigidBodyDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
super.setSpatial(spatial);
|
super.setSpatial(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is enabled and added to a scene. Should be
|
||||||
|
* invoked only by a subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
if(myShape != body.getCollisionShape()){
|
if(myShape != body.getCollisionShape()){
|
||||||
@ -91,6 +129,14 @@ public class BulletRigidBodyDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
geom.setLocalScale(body.getCollisionShape().getScale());
|
geom.setLocalScale(body.getCollisionShape().getScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per frame, provided the
|
||||||
|
* control is enabled and added to a scene. Should be invoked only by a
|
||||||
|
* subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -43,6 +43,9 @@ import com.jme3.scene.Spatial;
|
|||||||
import com.jme3.scene.debug.Arrow;
|
import com.jme3.scene.debug.Arrow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A physics-debug control used to visualize a PhysicsVehicle.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
@ -53,6 +56,12 @@ public class BulletVehicleDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
protected final Vector3f location = new Vector3f();
|
protected final Vector3f location = new Vector3f();
|
||||||
protected final Quaternion rotation = new Quaternion();
|
protected final Quaternion rotation = new Quaternion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an enabled control to visualize the specified vehicle.
|
||||||
|
*
|
||||||
|
* @param debugAppState which app state (not null, alias created)
|
||||||
|
* @param body which vehicle to visualize (not null, alias created)
|
||||||
|
*/
|
||||||
public BulletVehicleDebugControl(BulletDebugAppState debugAppState, PhysicsVehicle body) {
|
public BulletVehicleDebugControl(BulletDebugAppState debugAppState, PhysicsVehicle body) {
|
||||||
super(debugAppState);
|
super(debugAppState);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
@ -60,6 +69,13 @@ public class BulletVehicleDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
createVehicle();
|
createVehicle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter which spatial is controlled. Invoked when the control is added to
|
||||||
|
* or removed from a spatial. Should be invoked only by a subclass or from
|
||||||
|
* Spatial. Do not invoke directly from user code.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial to control (or null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (spatial != null && spatial instanceof Node) {
|
if (spatial != null && spatial instanceof Node) {
|
||||||
@ -104,6 +120,13 @@ public class BulletVehicleDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this control. Invoked once per frame during the logical-state
|
||||||
|
* update, provided the control is enabled and added to a scene. Should be
|
||||||
|
* invoked only by a subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
for (int i = 0; i < body.getNumWheels(); i++) {
|
for (int i = 0; i < body.getNumWheels(); i++) {
|
||||||
@ -136,6 +159,14 @@ public class BulletVehicleDebugControl extends AbstractPhysicsDebugControl {
|
|||||||
applyPhysicsTransform(body.getPhysicsLocation(location), body.getPhysicsRotation(rotation));
|
applyPhysicsTransform(body.getPhysicsLocation(location), body.getPhysicsRotation(rotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this control. Invoked once per frame, provided the
|
||||||
|
* control is enabled and added to a scene. Should be invoked only by a
|
||||||
|
* subclass or by AbstractControl.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port to render (not null)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,43 +42,129 @@ import com.jme3.scene.Node;
|
|||||||
import com.jme3.scene.debug.Arrow;
|
import com.jme3.scene.debug.Arrow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Debugging aids.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class DebugTools {
|
public class DebugTools {
|
||||||
|
|
||||||
protected final AssetManager manager;
|
protected final AssetManager manager;
|
||||||
|
/**
|
||||||
|
* unshaded blue material
|
||||||
|
*/
|
||||||
public Material DEBUG_BLUE;
|
public Material DEBUG_BLUE;
|
||||||
|
/**
|
||||||
|
* unshaded red material
|
||||||
|
*/
|
||||||
public Material DEBUG_RED;
|
public Material DEBUG_RED;
|
||||||
|
/**
|
||||||
|
* unshaded green material
|
||||||
|
*/
|
||||||
public Material DEBUG_GREEN;
|
public Material DEBUG_GREEN;
|
||||||
|
/**
|
||||||
|
* unshaded yellow material
|
||||||
|
*/
|
||||||
public Material DEBUG_YELLOW;
|
public Material DEBUG_YELLOW;
|
||||||
|
/**
|
||||||
|
* unshaded magenta material
|
||||||
|
*/
|
||||||
public Material DEBUG_MAGENTA;
|
public Material DEBUG_MAGENTA;
|
||||||
|
/**
|
||||||
|
* unshaded pink material
|
||||||
|
*/
|
||||||
public Material DEBUG_PINK;
|
public Material DEBUG_PINK;
|
||||||
|
/**
|
||||||
|
* node for attaching debug geometries
|
||||||
|
*/
|
||||||
public Node debugNode = new Node("Debug Node");
|
public Node debugNode = new Node("Debug Node");
|
||||||
|
/**
|
||||||
|
* mesh for the blue arrow
|
||||||
|
*/
|
||||||
public Arrow arrowBlue = new Arrow(Vector3f.ZERO);
|
public Arrow arrowBlue = new Arrow(Vector3f.ZERO);
|
||||||
|
/**
|
||||||
|
* geometry for the blue arrow
|
||||||
|
*/
|
||||||
public Geometry arrowBlueGeom = new Geometry("Blue Arrow", arrowBlue);
|
public Geometry arrowBlueGeom = new Geometry("Blue Arrow", arrowBlue);
|
||||||
|
/**
|
||||||
|
* mesh for the green arrow
|
||||||
|
*/
|
||||||
public Arrow arrowGreen = new Arrow(Vector3f.ZERO);
|
public Arrow arrowGreen = new Arrow(Vector3f.ZERO);
|
||||||
|
/**
|
||||||
|
* geometry for the green arrow
|
||||||
|
*/
|
||||||
public Geometry arrowGreenGeom = new Geometry("Green Arrow", arrowGreen);
|
public Geometry arrowGreenGeom = new Geometry("Green Arrow", arrowGreen);
|
||||||
|
/**
|
||||||
|
* mesh for the red arrow
|
||||||
|
*/
|
||||||
public Arrow arrowRed = new Arrow(Vector3f.ZERO);
|
public Arrow arrowRed = new Arrow(Vector3f.ZERO);
|
||||||
|
/**
|
||||||
|
* geometry for the red arrow
|
||||||
|
*/
|
||||||
public Geometry arrowRedGeom = new Geometry("Red Arrow", arrowRed);
|
public Geometry arrowRedGeom = new Geometry("Red Arrow", arrowRed);
|
||||||
|
/**
|
||||||
|
* mesh for the magenta arrow
|
||||||
|
*/
|
||||||
public Arrow arrowMagenta = new Arrow(Vector3f.ZERO);
|
public Arrow arrowMagenta = new Arrow(Vector3f.ZERO);
|
||||||
|
/**
|
||||||
|
* geometry for the magenta arrow
|
||||||
|
*/
|
||||||
public Geometry arrowMagentaGeom = new Geometry("Magenta Arrow", arrowMagenta);
|
public Geometry arrowMagentaGeom = new Geometry("Magenta Arrow", arrowMagenta);
|
||||||
|
/**
|
||||||
|
* mesh for the yellow arrow
|
||||||
|
*/
|
||||||
public Arrow arrowYellow = new Arrow(Vector3f.ZERO);
|
public Arrow arrowYellow = new Arrow(Vector3f.ZERO);
|
||||||
|
/**
|
||||||
|
* geometry for the yellow arrow
|
||||||
|
*/
|
||||||
public Geometry arrowYellowGeom = new Geometry("Yellow Arrow", arrowYellow);
|
public Geometry arrowYellowGeom = new Geometry("Yellow Arrow", arrowYellow);
|
||||||
|
/**
|
||||||
|
* mesh for the pink arrow
|
||||||
|
*/
|
||||||
public Arrow arrowPink = new Arrow(Vector3f.ZERO);
|
public Arrow arrowPink = new Arrow(Vector3f.ZERO);
|
||||||
|
/**
|
||||||
|
* geometry for the pink arrow
|
||||||
|
*/
|
||||||
public Geometry arrowPinkGeom = new Geometry("Pink Arrow", arrowPink);
|
public Geometry arrowPinkGeom = new Geometry("Pink Arrow", arrowPink);
|
||||||
|
/**
|
||||||
|
* local copy of {@link com.jme3.math.Vector3f#UNIT_X}
|
||||||
|
*/
|
||||||
protected static final Vector3f UNIT_X_CHECK = new Vector3f(1, 0, 0);
|
protected static final Vector3f UNIT_X_CHECK = new Vector3f(1, 0, 0);
|
||||||
|
/**
|
||||||
|
* local copy of {@link com.jme3.math.Vector3f#UNIT_Y}
|
||||||
|
*/
|
||||||
protected static final Vector3f UNIT_Y_CHECK = new Vector3f(0, 1, 0);
|
protected static final Vector3f UNIT_Y_CHECK = new Vector3f(0, 1, 0);
|
||||||
|
/**
|
||||||
|
* local copy of {@link com.jme3.math.Vector3f#UNIT_Z}
|
||||||
|
*/
|
||||||
protected static final Vector3f UNIT_Z_CHECK = new Vector3f(0, 0, 1);
|
protected static final Vector3f UNIT_Z_CHECK = new Vector3f(0, 0, 1);
|
||||||
|
/**
|
||||||
|
* local copy of {@link com.jme3.math.Vector3f#UNIT_XYZ}
|
||||||
|
*/
|
||||||
protected static final Vector3f UNIT_XYZ_CHECK = new Vector3f(1, 1, 1);
|
protected static final Vector3f UNIT_XYZ_CHECK = new Vector3f(1, 1, 1);
|
||||||
|
/**
|
||||||
|
* local copy of {@link com.jme3.math.Vector3f#ZERO}
|
||||||
|
*/
|
||||||
protected static final Vector3f ZERO_CHECK = new Vector3f(0, 0, 0);
|
protected static final Vector3f ZERO_CHECK = new Vector3f(0, 0, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a set of debug tools.
|
||||||
|
*
|
||||||
|
* @param manager for loading assets (not null, alias created)
|
||||||
|
*/
|
||||||
public DebugTools(AssetManager manager) {
|
public DebugTools(AssetManager manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
setupMaterials();
|
setupMaterials();
|
||||||
setupDebugNode();
|
setupDebugNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render all the debug geometries to the specified view port.
|
||||||
|
*
|
||||||
|
* @param rm the render manager (not null)
|
||||||
|
* @param vp the view port (not null)
|
||||||
|
*/
|
||||||
public void show(RenderManager rm, ViewPort vp) {
|
public void show(RenderManager rm, ViewPort vp) {
|
||||||
if (!Vector3f.UNIT_X.equals(UNIT_X_CHECK) || !Vector3f.UNIT_Y.equals(UNIT_Y_CHECK) || !Vector3f.UNIT_Z.equals(UNIT_Z_CHECK)
|
if (!Vector3f.UNIT_X.equals(UNIT_X_CHECK) || !Vector3f.UNIT_Y.equals(UNIT_Y_CHECK) || !Vector3f.UNIT_Z.equals(UNIT_Z_CHECK)
|
||||||
|| !Vector3f.UNIT_XYZ.equals(UNIT_XYZ_CHECK) || !Vector3f.ZERO.equals(ZERO_CHECK)) {
|
|| !Vector3f.UNIT_XYZ.equals(UNIT_XYZ_CHECK) || !Vector3f.ZERO.equals(ZERO_CHECK)) {
|
||||||
@ -94,36 +180,75 @@ public class DebugTools {
|
|||||||
rm.renderScene(debugNode, vp);
|
rm.renderScene(debugNode, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the location and extent of the blue arrow.
|
||||||
|
*
|
||||||
|
* @param location the coordinates of the tail (not null, unaffected)
|
||||||
|
* @param extent the offset of the tip from the tail (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setBlueArrow(Vector3f location, Vector3f extent) {
|
public void setBlueArrow(Vector3f location, Vector3f extent) {
|
||||||
arrowBlueGeom.setLocalTranslation(location);
|
arrowBlueGeom.setLocalTranslation(location);
|
||||||
arrowBlue.setArrowExtent(extent);
|
arrowBlue.setArrowExtent(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the location and extent of the green arrow.
|
||||||
|
*
|
||||||
|
* @param location the coordinates of the tail (not null, unaffected)
|
||||||
|
* @param extent the offset of the tip from the tail (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setGreenArrow(Vector3f location, Vector3f extent) {
|
public void setGreenArrow(Vector3f location, Vector3f extent) {
|
||||||
arrowGreenGeom.setLocalTranslation(location);
|
arrowGreenGeom.setLocalTranslation(location);
|
||||||
arrowGreen.setArrowExtent(extent);
|
arrowGreen.setArrowExtent(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the location and extent of the red arrow.
|
||||||
|
*
|
||||||
|
* @param location the coordinates of the tail (not null, unaffected)
|
||||||
|
* @param extent the offset of the tip from the tail (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setRedArrow(Vector3f location, Vector3f extent) {
|
public void setRedArrow(Vector3f location, Vector3f extent) {
|
||||||
arrowRedGeom.setLocalTranslation(location);
|
arrowRedGeom.setLocalTranslation(location);
|
||||||
arrowRed.setArrowExtent(extent);
|
arrowRed.setArrowExtent(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the location and extent of the magenta arrow.
|
||||||
|
*
|
||||||
|
* @param location the coordinates of the tail (not null, unaffected)
|
||||||
|
* @param extent the offset of the tip from the tail (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setMagentaArrow(Vector3f location, Vector3f extent) {
|
public void setMagentaArrow(Vector3f location, Vector3f extent) {
|
||||||
arrowMagentaGeom.setLocalTranslation(location);
|
arrowMagentaGeom.setLocalTranslation(location);
|
||||||
arrowMagenta.setArrowExtent(extent);
|
arrowMagenta.setArrowExtent(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the location and extent of the yellow arrow.
|
||||||
|
*
|
||||||
|
* @param location the coordinates of the tail (not null, unaffected)
|
||||||
|
* @param extent the offset of the tip from the tail (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setYellowArrow(Vector3f location, Vector3f extent) {
|
public void setYellowArrow(Vector3f location, Vector3f extent) {
|
||||||
arrowYellowGeom.setLocalTranslation(location);
|
arrowYellowGeom.setLocalTranslation(location);
|
||||||
arrowYellow.setArrowExtent(extent);
|
arrowYellow.setArrowExtent(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the location and extent of the pink arrow.
|
||||||
|
*
|
||||||
|
* @param location the coordinates of the tail (not null, unaffected)
|
||||||
|
* @param extent the offset of the tip from the tail (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setPinkArrow(Vector3f location, Vector3f extent) {
|
public void setPinkArrow(Vector3f location, Vector3f extent) {
|
||||||
arrowPinkGeom.setLocalTranslation(location);
|
arrowPinkGeom.setLocalTranslation(location);
|
||||||
arrowPink.setArrowExtent(extent);
|
arrowPink.setArrowExtent(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach all the debug geometries to the debug node.
|
||||||
|
*/
|
||||||
protected void setupDebugNode() {
|
protected void setupDebugNode() {
|
||||||
arrowBlueGeom.setMaterial(DEBUG_BLUE);
|
arrowBlueGeom.setMaterial(DEBUG_BLUE);
|
||||||
arrowGreenGeom.setMaterial(DEBUG_GREEN);
|
arrowGreenGeom.setMaterial(DEBUG_GREEN);
|
||||||
@ -139,6 +264,9 @@ public class DebugTools {
|
|||||||
debugNode.attachChild(arrowPinkGeom);
|
debugNode.attachChild(arrowPinkGeom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize all the DebugTools materials.
|
||||||
|
*/
|
||||||
protected void setupMaterials() {
|
protected void setupMaterials() {
|
||||||
DEBUG_BLUE = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
DEBUG_BLUE = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
DEBUG_BLUE.getAdditionalRenderState().setWireframe(true);
|
DEBUG_BLUE.getAdditionalRenderState().setWireframe(true);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -44,17 +44,21 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A utility class for generating collision shapes from Spatials.
|
||||||
|
* <p>
|
||||||
|
* This class is shared between JBullet and Native Bullet.
|
||||||
*
|
*
|
||||||
* @author normenhansen, tim8dev
|
* @author normenhansen, tim8dev
|
||||||
*/
|
*/
|
||||||
public class CollisionShapeFactory {
|
public class CollisionShapeFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the correct transform for a collisionshape in relation
|
* Calculate the correct transform for a collision shape relative to the
|
||||||
* to the ancestor for which the collisionshape is generated
|
* ancestor for which the shape was generated.
|
||||||
|
*
|
||||||
* @param spat
|
* @param spat
|
||||||
* @param parent
|
* @param parent
|
||||||
* @return
|
* @return a new instance (not null)
|
||||||
*/
|
*/
|
||||||
private static Transform getTransform(Spatial spat, Spatial parent) {
|
private static Transform getTransform(Spatial spat, Spatial parent) {
|
||||||
Transform shapeTransform = new Transform();
|
Transform shapeTransform = new Transform();
|
||||||
@ -135,30 +139,48 @@ public class CollisionShapeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type of collision shape is mesh-accurate and meant for immovable "world objects".
|
* This type of collision shape is mesh-accurate and meant for immovable
|
||||||
* Examples include terrain, houses or whole shooter levels.<br>
|
* "world objects". Examples include terrain, houses or whole shooter
|
||||||
* Objects with "mesh" type collision shape will not collide with each other.
|
* levels.
|
||||||
|
* <p>
|
||||||
|
* Objects with "mesh" type collision shape will not collide with each
|
||||||
|
* other.
|
||||||
|
*
|
||||||
|
* @param rootNode the node on which to base the shape (not null)
|
||||||
|
* @return a new shape (not null)
|
||||||
*/
|
*/
|
||||||
private static CompoundCollisionShape createMeshCompoundShape(Node rootNode) {
|
private static CompoundCollisionShape createMeshCompoundShape(Node rootNode) {
|
||||||
return createCompoundShape(rootNode, new CompoundCollisionShape(), true);
|
return createCompoundShape(rootNode, new CompoundCollisionShape(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type of collision shape creates a CompoundShape made out of boxes that
|
* This type of collision shape creates a CompoundShape made out of boxes
|
||||||
* are based on the bounds of the Geometries in the tree.
|
* that are based on the bounds of the Geometries in the tree.
|
||||||
* @param rootNode
|
*
|
||||||
* @return
|
* @param rootNode the node on which to base the shape (not null)
|
||||||
|
* @return a new shape (not null)
|
||||||
*/
|
*/
|
||||||
private static CompoundCollisionShape createBoxCompoundShape(Node rootNode) {
|
private static CompoundCollisionShape createBoxCompoundShape(Node rootNode) {
|
||||||
return createCompoundShape(rootNode, new CompoundCollisionShape(), false);
|
return createCompoundShape(rootNode, new CompoundCollisionShape(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type of collision shape is mesh-accurate and meant for immovable "world objects".
|
* Create a mesh shape for the given Spatial.
|
||||||
* Examples include terrain, houses or whole shooter levels.<br/>
|
* <p>
|
||||||
* Objects with "mesh" type collision shape will not collide with each other.<br/>
|
* This type of collision shape is mesh-accurate and meant for immovable
|
||||||
* Creates a HeightfieldCollisionShape if the supplied spatial is a TerrainQuad.
|
* "world objects". Examples include terrain, houses or whole shooter
|
||||||
* @return A MeshCollisionShape or a CompoundCollisionShape with MeshCollisionShapes as children if the supplied spatial is a Node. A HeightieldCollisionShape if a TerrainQuad was supplied.
|
* levels.
|
||||||
|
* <p>
|
||||||
|
* Objects with "mesh" type collision shape will not collide with each
|
||||||
|
* other.
|
||||||
|
* <p>
|
||||||
|
* Creates a HeightfieldCollisionShape if the supplied spatial is a
|
||||||
|
* TerrainQuad.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial on which to base the shape (not null)
|
||||||
|
* @return A MeshCollisionShape or a CompoundCollisionShape with
|
||||||
|
* MeshCollisionShapes as children if the supplied spatial is a Node. A
|
||||||
|
* HeightieldCollisionShape if a TerrainQuad was supplied.
|
||||||
*/
|
*/
|
||||||
public static CollisionShape createMeshShape(Spatial spatial) {
|
public static CollisionShape createMeshShape(Spatial spatial) {
|
||||||
if (spatial instanceof TerrainQuad) {
|
if (spatial instanceof TerrainQuad) {
|
||||||
@ -177,9 +199,14 @@ public class CollisionShapeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates a hull shape for the given Spatial.<br>
|
* Create a hull shape for the given Spatial.
|
||||||
* If you want to have mesh-accurate dynamic shapes (CPU intense!!!) use GImpact shapes, its probably best to do so with a low-poly version of your model.
|
* <p>
|
||||||
* @return A HullCollisionShape or a CompoundCollisionShape with HullCollisionShapes as children if the supplied spatial is a Node.
|
* For mesh-accurate animated meshes (CPU intense!) use GImpact shapes.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial on which to base the shape (not null)
|
||||||
|
* @return a HullCollisionShape (if spatial is a Geometry) or a
|
||||||
|
* CompoundCollisionShape with HullCollisionShapes as children (if spatial
|
||||||
|
* is a Node)
|
||||||
*/
|
*/
|
||||||
public static CollisionShape createDynamicMeshShape(Spatial spatial) {
|
public static CollisionShape createDynamicMeshShape(Spatial spatial) {
|
||||||
if (spatial instanceof Geometry) {
|
if (spatial instanceof Geometry) {
|
||||||
@ -192,6 +219,14 @@ public class CollisionShapeFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a box shape for the given Spatial.
|
||||||
|
*
|
||||||
|
* @param spatial the spatial on which to base the shape (not null)
|
||||||
|
* @return a BoxCollisionShape (if spatial is a Geometry) or a
|
||||||
|
* CompoundCollisionShape with BoxCollisionShapes as children (if spatial is
|
||||||
|
* a Node)
|
||||||
|
*/
|
||||||
public static CollisionShape createBoxShape(Spatial spatial) {
|
public static CollisionShape createBoxShape(Spatial spatial) {
|
||||||
if (spatial instanceof Geometry) {
|
if (spatial instanceof Geometry) {
|
||||||
return createSingleBoxShape((Geometry) spatial, spatial);
|
return createSingleBoxShape((Geometry) spatial, spatial);
|
||||||
@ -203,9 +238,12 @@ public class CollisionShapeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type of collision shape is mesh-accurate and meant for immovable "world objects".
|
* This type of collision shape is mesh-accurate and meant for immovable
|
||||||
* Examples include terrain, houses or whole shooter levels.<br>
|
* "world objects". Examples include terrain, houses or whole shooter
|
||||||
* Objects with "mesh" type collision shape will not collide with each other.
|
* levels.
|
||||||
|
* <p>
|
||||||
|
* Objects with "mesh" type collision shape will not collide with each
|
||||||
|
* other.
|
||||||
*/
|
*/
|
||||||
private static MeshCollisionShape createSingleMeshShape(Geometry geom, Spatial parent) {
|
private static MeshCollisionShape createSingleMeshShape(Geometry geom, Spatial parent) {
|
||||||
Mesh mesh = geom.getMesh();
|
Mesh mesh = geom.getMesh();
|
||||||
@ -220,9 +258,13 @@ public class CollisionShapeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the bounding box of the supplied spatial to create a BoxCollisionShape
|
* Use the bounding box of the supplied spatial to create a
|
||||||
* @param spatial
|
* BoxCollisionShape.
|
||||||
* @return BoxCollisionShape with the size of the spatials BoundingBox
|
*
|
||||||
|
* @param spatial the spatial on which to base the shape (not null)
|
||||||
|
* @param parent unused
|
||||||
|
* @return a new shape with the dimensions of the spatial's bounding box
|
||||||
|
* (not null)
|
||||||
*/
|
*/
|
||||||
private static BoxCollisionShape createSingleBoxShape(Spatial spatial, Spatial parent) {
|
private static BoxCollisionShape createSingleBoxShape(Spatial spatial, Spatial parent) {
|
||||||
//TODO: using world bound here instead of "local world" bound...
|
//TODO: using world bound here instead of "local world" bound...
|
||||||
@ -232,7 +274,10 @@ public class CollisionShapeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates a hull collision shape for the given mesh.<br>
|
* Create a hull collision shape for the specified geometry.
|
||||||
|
*
|
||||||
|
* @param geom the geometry on which to base the shape (not null)
|
||||||
|
* @param parent
|
||||||
*/
|
*/
|
||||||
private static HullCollisionShape createSingleDynamicMeshShape(Geometry geom, Spatial parent) {
|
private static HullCollisionShape createSingleDynamicMeshShape(Geometry geom, Spatial parent) {
|
||||||
Mesh mesh = geom.getMesh();
|
Mesh mesh = geom.getMesh();
|
||||||
|
@ -62,17 +62,36 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>PhysicsSpace - The central jbullet-jme physics space</p>
|
* A jbullet-jme physics space with its own btDynamicsWorld.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsSpace {
|
public class PhysicsSpace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message logger for this class
|
||||||
|
*/
|
||||||
private static final Logger logger = Logger.getLogger(PhysicsSpace.class.getName());
|
private static final Logger logger = Logger.getLogger(PhysicsSpace.class.getName());
|
||||||
|
/**
|
||||||
|
* index of the X axis
|
||||||
|
*/
|
||||||
public static final int AXIS_X = 0;
|
public static final int AXIS_X = 0;
|
||||||
|
/**
|
||||||
|
* index of the Y axis
|
||||||
|
*/
|
||||||
public static final int AXIS_Y = 1;
|
public static final int AXIS_Y = 1;
|
||||||
|
/**
|
||||||
|
* index of the Z axis
|
||||||
|
*/
|
||||||
public static final int AXIS_Z = 2;
|
public static final int AXIS_Z = 2;
|
||||||
|
/**
|
||||||
|
* Bullet identifier of the physics space. The constructor sets this to a
|
||||||
|
* non-zero value.
|
||||||
|
*/
|
||||||
private long physicsSpaceId = 0;
|
private long physicsSpaceId = 0;
|
||||||
|
/**
|
||||||
|
* first-in/first-out (FIFO) queue of physics tasks for each thread
|
||||||
|
*/
|
||||||
private static ThreadLocal<ConcurrentLinkedQueue<AppTask<?>>> pQueueTL =
|
private static ThreadLocal<ConcurrentLinkedQueue<AppTask<?>>> pQueueTL =
|
||||||
new ThreadLocal<ConcurrentLinkedQueue<AppTask<?>>>() {
|
new ThreadLocal<ConcurrentLinkedQueue<AppTask<?>>>() {
|
||||||
@Override
|
@Override
|
||||||
@ -80,8 +99,17 @@ public class PhysicsSpace {
|
|||||||
return new ConcurrentLinkedQueue<AppTask<?>>();
|
return new ConcurrentLinkedQueue<AppTask<?>>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* first-in/first-out (FIFO) queue of physics tasks
|
||||||
|
*/
|
||||||
private ConcurrentLinkedQueue<AppTask<?>> pQueue = new ConcurrentLinkedQueue<AppTask<?>>();
|
private ConcurrentLinkedQueue<AppTask<?>> pQueue = new ConcurrentLinkedQueue<AppTask<?>>();
|
||||||
|
/**
|
||||||
|
* physics space for each thread
|
||||||
|
*/
|
||||||
private static ThreadLocal<PhysicsSpace> physicsSpaceTL = new ThreadLocal<PhysicsSpace>();
|
private static ThreadLocal<PhysicsSpace> physicsSpaceTL = new ThreadLocal<PhysicsSpace>();
|
||||||
|
/**
|
||||||
|
* copy of type of acceleration structure used
|
||||||
|
*/
|
||||||
private BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
private BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
||||||
// private DiscreteDynamicsWorld dynamicsWorld = null;
|
// private DiscreteDynamicsWorld dynamicsWorld = null;
|
||||||
// private BroadphaseInterface broadphase;
|
// private BroadphaseInterface broadphase;
|
||||||
@ -99,10 +127,32 @@ public class PhysicsSpace {
|
|||||||
private Map<Integer, PhysicsCollisionGroupListener> collisionGroupListeners = new ConcurrentHashMap<Integer, PhysicsCollisionGroupListener>();
|
private Map<Integer, PhysicsCollisionGroupListener> collisionGroupListeners = new ConcurrentHashMap<Integer, PhysicsCollisionGroupListener>();
|
||||||
private ConcurrentLinkedQueue<PhysicsTickListener> tickListeners = new ConcurrentLinkedQueue<PhysicsTickListener>();
|
private ConcurrentLinkedQueue<PhysicsTickListener> tickListeners = new ConcurrentLinkedQueue<PhysicsTickListener>();
|
||||||
private PhysicsCollisionEventFactory eventFactory = new PhysicsCollisionEventFactory();
|
private PhysicsCollisionEventFactory eventFactory = new PhysicsCollisionEventFactory();
|
||||||
|
/**
|
||||||
|
* copy of minimum coordinate values when using AXIS_SWEEP broadphase
|
||||||
|
* algorithms
|
||||||
|
*/
|
||||||
private Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
private Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
||||||
|
/**
|
||||||
|
* copy of maximum coordinate values when using AXIS_SWEEP broadphase
|
||||||
|
* algorithms
|
||||||
|
*/
|
||||||
private Vector3f worldMax = new Vector3f(10000f, 10000f, 10000f);
|
private Vector3f worldMax = new Vector3f(10000f, 10000f, 10000f);
|
||||||
|
/**
|
||||||
|
* physics time step (in seconds, >0)
|
||||||
|
*/
|
||||||
private float accuracy = 1f / 60f;
|
private float accuracy = 1f / 60f;
|
||||||
private int maxSubSteps = 4, rayTestFlags = 1 << 2;
|
/**
|
||||||
|
* maximum number of physics steps per frame (≥0, default=4)
|
||||||
|
*/
|
||||||
|
private int maxSubSteps = 4;
|
||||||
|
/**
|
||||||
|
* flags used in ray tests
|
||||||
|
*/
|
||||||
|
private int rayTestFlags = 1 << 2;
|
||||||
|
/**
|
||||||
|
* copy of number of iterations used by the contact-and-constraint solver
|
||||||
|
* (default=10)
|
||||||
|
*/
|
||||||
private int solverNumIterations = 10;
|
private int solverNumIterations = 10;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -111,9 +161,8 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current PhysicsSpace <b>running on this thread</b><br/> For
|
* Access the PhysicsSpace <b>running on this thread</b>. For parallel
|
||||||
* parallel physics, this can also be called from the OpenGL thread to
|
* physics, this can be invoked from the OpenGL thread.
|
||||||
* receive the PhysicsSpace
|
|
||||||
*
|
*
|
||||||
* @return the PhysicsSpace running on this thread
|
* @return the PhysicsSpace running on this thread
|
||||||
*/
|
*/
|
||||||
@ -124,24 +173,47 @@ public class PhysicsSpace {
|
|||||||
/**
|
/**
|
||||||
* Used internally
|
* Used internally
|
||||||
*
|
*
|
||||||
* @param space
|
* @param space which physics space to simulate on this thread
|
||||||
*/
|
*/
|
||||||
public static void setLocalThreadPhysicsSpace(PhysicsSpace space) {
|
public static void setLocalThreadPhysicsSpace(PhysicsSpace space) {
|
||||||
physicsSpaceTL.set(space);
|
physicsSpaceTL.set(space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a PhysicsSpace. Must be invoked on the designated physics
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
public PhysicsSpace() {
|
public PhysicsSpace() {
|
||||||
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), BroadphaseType.DBVT);
|
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), BroadphaseType.DBVT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a PhysicsSpace. Must be invoked on the designated physics
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
public PhysicsSpace(BroadphaseType broadphaseType) {
|
public PhysicsSpace(BroadphaseType broadphaseType) {
|
||||||
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a PhysicsSpace. Must be invoked on the designated physics
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
public PhysicsSpace(Vector3f worldMin, Vector3f worldMax) {
|
public PhysicsSpace(Vector3f worldMin, Vector3f worldMax) {
|
||||||
this(worldMin, worldMax, BroadphaseType.AXIS_SWEEP_3);
|
this(worldMin, worldMax, BroadphaseType.AXIS_SWEEP_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a PhysicsSpace. Must be invoked on the designated physics
|
||||||
|
* thread.
|
||||||
|
*
|
||||||
|
* @param worldMin the desired minimum coordinates values (not null,
|
||||||
|
* unaffected, default=-10k,-10k,-10k)
|
||||||
|
* @param worldMax the desired minimum coordinates values (not null,
|
||||||
|
* unaffected, default=10k,10k,10k)
|
||||||
|
* @param broadphaseType which broadphase collision-detection algorithm to
|
||||||
|
* use (not null)
|
||||||
|
*/
|
||||||
public PhysicsSpace(Vector3f worldMin, Vector3f worldMax, BroadphaseType broadphaseType) {
|
public PhysicsSpace(Vector3f worldMin, Vector3f worldMax, BroadphaseType broadphaseType) {
|
||||||
this.worldMin.set(worldMin);
|
this.worldMin.set(worldMin);
|
||||||
this.worldMax.set(worldMax);
|
this.worldMax.set(worldMax);
|
||||||
@ -150,7 +222,7 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has to be called from the (designated) physics thread
|
* Must be invoked on the designated physics thread.
|
||||||
*/
|
*/
|
||||||
public void create() {
|
public void create() {
|
||||||
physicsSpaceId = createPhysicsSpace(worldMin.x, worldMin.y, worldMin.z, worldMax.x, worldMax.y, worldMax.z, broadphaseType.ordinal(), false);
|
physicsSpaceId = createPhysicsSpace(worldMin.x, worldMin.y, worldMin.z, worldMax.x, worldMax.y, worldMax.z, broadphaseType.ordinal(), false);
|
||||||
@ -191,6 +263,13 @@ public class PhysicsSpace {
|
|||||||
|
|
||||||
private native long createPhysicsSpace(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int broadphaseType, boolean threading);
|
private native long createPhysicsSpace(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int broadphaseType, boolean threading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked just before the physics is stepped.
|
||||||
|
* <p>
|
||||||
|
* This method is invoked from native code.
|
||||||
|
*
|
||||||
|
* @param timeStep the time per physics step (in seconds, ≥0)
|
||||||
|
*/
|
||||||
private void preTick_native(float f) {
|
private void preTick_native(float f) {
|
||||||
AppTask task;
|
AppTask task;
|
||||||
while((task=pQueue.poll())!=null){
|
while((task=pQueue.poll())!=null){
|
||||||
@ -208,6 +287,13 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked just after the physics is stepped.
|
||||||
|
* <p>
|
||||||
|
* This method is invoked from native code.
|
||||||
|
*
|
||||||
|
* @param timeStep the time per physics step (in seconds, ≥0)
|
||||||
|
*/
|
||||||
private void postTick_native(float f) {
|
private void postTick_native(float f) {
|
||||||
for (Iterator<PhysicsTickListener> it = tickListeners.iterator(); it.hasNext();) {
|
for (Iterator<PhysicsTickListener> it = tickListeners.iterator(); it.hasNext();) {
|
||||||
PhysicsTickListener physicsTickCallback = it.next();
|
PhysicsTickListener physicsTickCallback = it.next();
|
||||||
@ -215,6 +301,9 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is invoked from native code.
|
||||||
|
*/
|
||||||
private void addCollision_native() {
|
private void addCollision_native() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +423,9 @@ public class PhysicsSpace {
|
|||||||
collisionEvents.add(eventFactory.getEvent(PhysicsCollisionEvent.TYPE_PROCESSED, node, node1, manifoldPointObjectId));
|
collisionEvents.add(eventFactory.getEvent(PhysicsCollisionEvent.TYPE_PROCESSED, node, node1, manifoldPointObjectId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is invoked from native code.
|
||||||
|
*/
|
||||||
private boolean notifyCollisionGroupListeners_native(PhysicsCollisionObject node, PhysicsCollisionObject node1){
|
private boolean notifyCollisionGroupListeners_native(PhysicsCollisionObject node, PhysicsCollisionObject node1){
|
||||||
PhysicsCollisionGroupListener listener = collisionGroupListeners.get(node.getCollisionGroup());
|
PhysicsCollisionGroupListener listener = collisionGroupListeners.get(node.getCollisionGroup());
|
||||||
PhysicsCollisionGroupListener listener1 = collisionGroupListeners.get(node1.getCollisionGroup());
|
PhysicsCollisionGroupListener listener1 = collisionGroupListeners.get(node1.getCollisionGroup());
|
||||||
@ -350,19 +442,21 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* updates the physics space
|
* Update this space. Invoked (by the Bullet app state) once per frame while
|
||||||
|
* the app state is attached and enabled.
|
||||||
*
|
*
|
||||||
* @param time the current time value
|
* @param time time-per-frame multiplied by speed (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
public void update(float time) {
|
public void update(float time) {
|
||||||
update(time, maxSubSteps);
|
update(time, maxSubSteps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* updates the physics space, uses maxSteps<br>
|
* Simulate for the specified time interval, using no more than the
|
||||||
|
* specified number of steps.
|
||||||
*
|
*
|
||||||
* @param time the current time value
|
* @param time the time interval (in seconds, ≥0)
|
||||||
* @param maxSteps
|
* @param maxSteps the maximum number of steps (≥1)
|
||||||
*/
|
*/
|
||||||
public void update(float time, int maxSteps) {
|
public void update(float time, int maxSteps) {
|
||||||
// if (getDynamicsWorld() == null) {
|
// if (getDynamicsWorld() == null) {
|
||||||
@ -374,6 +468,9 @@ public class PhysicsSpace {
|
|||||||
|
|
||||||
private native void stepSimulation(long space, float time, int maxSteps, float accuracy);
|
private native void stepSimulation(long space, float time, int maxSteps, float accuracy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distribute each collision event to all listeners.
|
||||||
|
*/
|
||||||
public void distributeEvents() {
|
public void distributeEvents() {
|
||||||
//add collision callbacks
|
//add collision callbacks
|
||||||
int clistsize = collisionListeners.size();
|
int clistsize = collisionListeners.size();
|
||||||
@ -387,6 +484,13 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a callable on the currently executing thread.
|
||||||
|
*
|
||||||
|
* @param <V> the task's result type
|
||||||
|
* @param callable the task to be executed
|
||||||
|
* @return a new task (not null)
|
||||||
|
*/
|
||||||
public static <V> Future<V> enqueueOnThisThread(Callable<V> callable) {
|
public static <V> Future<V> enqueueOnThisThread(Callable<V> callable) {
|
||||||
AppTask<V> task = new AppTask<V>(callable);
|
AppTask<V> task = new AppTask<V>(callable);
|
||||||
System.out.println("created apptask");
|
System.out.println("created apptask");
|
||||||
@ -395,11 +499,11 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* calls the callable on the next physics tick (ensuring e.g. force
|
* Invoke the specified callable during the next physics tick. This is
|
||||||
* applying)
|
* useful for applying forces.
|
||||||
*
|
*
|
||||||
* @param <V>
|
* @param <V> the return type of the callable
|
||||||
* @param callable
|
* @param callable which callable to invoke
|
||||||
* @return Future object
|
* @return Future object
|
||||||
*/
|
*/
|
||||||
public <V> Future<V> enqueue(Callable<V> callable) {
|
public <V> Future<V> enqueue(Callable<V> callable) {
|
||||||
@ -409,9 +513,10 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds an object to the physics space
|
* Add the specified object to this space.
|
||||||
*
|
*
|
||||||
* @param obj the PhysicsControl or Spatial with PhysicsControl to add
|
* @param obj the PhysicsControl, Spatial-with-PhysicsControl,
|
||||||
|
* PhysicsCollisionObject, or PhysicsJoint to add (not null, modified)
|
||||||
*/
|
*/
|
||||||
public void add(Object obj) {
|
public void add(Object obj) {
|
||||||
if (obj instanceof PhysicsControl) {
|
if (obj instanceof PhysicsControl) {
|
||||||
@ -432,6 +537,11 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the specified collision object to this space.
|
||||||
|
*
|
||||||
|
* @param obj the PhysicsCollisionObject to add (not null, modified)
|
||||||
|
*/
|
||||||
public void addCollisionObject(PhysicsCollisionObject obj) {
|
public void addCollisionObject(PhysicsCollisionObject obj) {
|
||||||
if (obj instanceof PhysicsGhostObject) {
|
if (obj instanceof PhysicsGhostObject) {
|
||||||
addGhostObject((PhysicsGhostObject) obj);
|
addGhostObject((PhysicsGhostObject) obj);
|
||||||
@ -445,9 +555,9 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes an object from the physics space
|
* Remove the specified object from this space.
|
||||||
*
|
*
|
||||||
* @param obj the PhysicsControl or Spatial with PhysicsControl to remove
|
* @param obj the PhysicsCollisionObject to add, or null (modified)
|
||||||
*/
|
*/
|
||||||
public void remove(Object obj) {
|
public void remove(Object obj) {
|
||||||
if (obj == null) return;
|
if (obj == null) return;
|
||||||
@ -469,6 +579,11 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified collision object from this space.
|
||||||
|
*
|
||||||
|
* @param obj the PhysicsControl or Spatial with PhysicsControl to remove
|
||||||
|
*/
|
||||||
public void removeCollisionObject(PhysicsCollisionObject obj) {
|
public void removeCollisionObject(PhysicsCollisionObject obj) {
|
||||||
if (obj instanceof PhysicsGhostObject) {
|
if (obj instanceof PhysicsGhostObject) {
|
||||||
removeGhostObject((PhysicsGhostObject) obj);
|
removeGhostObject((PhysicsGhostObject) obj);
|
||||||
@ -480,9 +595,10 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds all physics controls and joints in the given spatial node to the physics space
|
* Add all physics controls and joints in the specified subtree of the scene
|
||||||
* (e.g. after loading from disk) - recursive if node
|
* graph to this space (e.g. after loading from disk). Note: recursive!
|
||||||
* @param spatial the rootnode containing the physics objects
|
*
|
||||||
|
* @param spatial the root of the subtree (not null)
|
||||||
*/
|
*/
|
||||||
public void addAll(Spatial spatial) {
|
public void addAll(Spatial spatial) {
|
||||||
add(spatial);
|
add(spatial);
|
||||||
@ -510,9 +626,11 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all physics controls and joints in the given spatial from the physics space
|
* Remove all physics controls and joints in the specified subtree of the
|
||||||
* (e.g. before saving to disk) - recursive if node
|
* scene graph from the physics space (e.g. before saving to disk) Note:
|
||||||
* @param spatial the rootnode containing the physics objects
|
* recursive!
|
||||||
|
*
|
||||||
|
* @param spatial the root of the subtree (not null)
|
||||||
*/
|
*/
|
||||||
public void removeAll(Spatial spatial) {
|
public void removeAll(Spatial spatial) {
|
||||||
if (spatial.getControl(RigidBodyControl.class) != null) {
|
if (spatial.getControl(RigidBodyControl.class) != null) {
|
||||||
@ -611,6 +729,12 @@ public class PhysicsSpace {
|
|||||||
// dynamicsWorld.removeCollisionObject(node.getObjectId());
|
// dynamicsWorld.removeCollisionObject(node.getObjectId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: When a rigid body is added, its gravity gets set to that of the
|
||||||
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param node the body to add (not null, not already in the space)
|
||||||
|
*/
|
||||||
private void addRigidBody(PhysicsRigidBody node) {
|
private void addRigidBody(PhysicsRigidBody node) {
|
||||||
if (physicsBodies.containsKey(node.getObjectId())) {
|
if (physicsBodies.containsKey(node.getObjectId())) {
|
||||||
logger.log(Level.WARNING, "RigidBody {0} already exists in PhysicsSpace, cannot add.", node);
|
logger.log(Level.WARNING, "RigidBody {0} already exists in PhysicsSpace, cannot add.", node);
|
||||||
@ -619,7 +743,7 @@ public class PhysicsSpace {
|
|||||||
physicsBodies.put(node.getObjectId(), node);
|
physicsBodies.put(node.getObjectId(), node);
|
||||||
|
|
||||||
//Workaround
|
//Workaround
|
||||||
//It seems that adding a Kinematic RigidBody to the dynamicWorld prevent it from being non kinematic again afterward.
|
//It seems that adding a Kinematic RigidBody to the dynamicWorld prevents it from being non-kinematic again afterward.
|
||||||
//so we add it non kinematic, then set it kinematic again.
|
//so we add it non kinematic, then set it kinematic again.
|
||||||
boolean kinematic = false;
|
boolean kinematic = false;
|
||||||
if (node.isKinematic()) {
|
if (node.isKinematic()) {
|
||||||
@ -682,30 +806,64 @@ public class PhysicsSpace {
|
|||||||
// dynamicsWorld.removeConstraint(joint.getObjectId());
|
// dynamicsWorld.removeConstraint(joint.getObjectId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the list of rigid bodies that have been added to this space and not
|
||||||
|
* yet removed.
|
||||||
|
*
|
||||||
|
* @return a new list (not null)
|
||||||
|
*/
|
||||||
public Collection<PhysicsRigidBody> getRigidBodyList() {
|
public Collection<PhysicsRigidBody> getRigidBodyList() {
|
||||||
return new LinkedList<PhysicsRigidBody>(physicsBodies.values());
|
return new LinkedList<PhysicsRigidBody>(physicsBodies.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the list of ghost objects that have been added to this space and not
|
||||||
|
* yet removed.
|
||||||
|
*
|
||||||
|
* @return a new list (not null)
|
||||||
|
*/
|
||||||
public Collection<PhysicsGhostObject> getGhostObjectList() {
|
public Collection<PhysicsGhostObject> getGhostObjectList() {
|
||||||
return new LinkedList<PhysicsGhostObject>(physicsGhostObjects.values());
|
return new LinkedList<PhysicsGhostObject>(physicsGhostObjects.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the list of physics characters that have been added to this space
|
||||||
|
* and not yet removed.
|
||||||
|
*
|
||||||
|
* @return a new list (not null)
|
||||||
|
*/
|
||||||
public Collection<PhysicsCharacter> getCharacterList() {
|
public Collection<PhysicsCharacter> getCharacterList() {
|
||||||
return new LinkedList<PhysicsCharacter>(physicsCharacters.values());
|
return new LinkedList<PhysicsCharacter>(physicsCharacters.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the list of physics joints that have been added to this space and
|
||||||
|
* not yet removed.
|
||||||
|
*
|
||||||
|
* @return a new list (not null)
|
||||||
|
*/
|
||||||
public Collection<PhysicsJoint> getJointList() {
|
public Collection<PhysicsJoint> getJointList() {
|
||||||
return new LinkedList<PhysicsJoint>(physicsJoints.values());
|
return new LinkedList<PhysicsJoint>(physicsJoints.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the list of physics vehicles that have been added to this space and
|
||||||
|
* not yet removed.
|
||||||
|
*
|
||||||
|
* @return a new list (not null)
|
||||||
|
*/
|
||||||
public Collection<PhysicsVehicle> getVehicleList() {
|
public Collection<PhysicsVehicle> getVehicleList() {
|
||||||
return new LinkedList<PhysicsVehicle>(physicsVehicles.values());
|
return new LinkedList<PhysicsVehicle>(physicsVehicles.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the gravity of the PhysicsSpace, set before adding physics objects!
|
* Alter the gravitational acceleration acting on newly-added bodies.
|
||||||
|
* <p>
|
||||||
|
* Whenever a rigid body is added to a space, the body's gravity gets set to
|
||||||
|
* that of the space. Thus it makes sense to set the space's vector before
|
||||||
|
* adding any bodies to the space.
|
||||||
*
|
*
|
||||||
* @param gravity
|
* @param gravity the desired acceleration vector (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setGravity(Vector3f gravity) {
|
public void setGravity(Vector3f gravity) {
|
||||||
this.gravity.set(gravity);
|
this.gravity.set(gravity);
|
||||||
@ -714,8 +872,17 @@ public class PhysicsSpace {
|
|||||||
|
|
||||||
private native void setGravity(long spaceId, Vector3f gravity);
|
private native void setGravity(long spaceId, Vector3f gravity);
|
||||||
|
|
||||||
//TODO: getGravity
|
/**
|
||||||
|
* copy of gravity-acceleration vector (default is 9.81 in the -Y direction,
|
||||||
|
* corresponding to Earth-normal in MKS units)
|
||||||
|
*/
|
||||||
private final Vector3f gravity = new Vector3f(0,-9.81f,0);
|
private final Vector3f gravity = new Vector3f(0,-9.81f,0);
|
||||||
|
/**
|
||||||
|
* Copy the gravitational acceleration acting on newly-added bodies.
|
||||||
|
*
|
||||||
|
* @param gravity storage for the result (not null, modified)
|
||||||
|
* @return acceleration (in the vector provided)
|
||||||
|
*/
|
||||||
public Vector3f getGravity(Vector3f gravity) {
|
public Vector3f getGravity(Vector3f gravity) {
|
||||||
return gravity.set(this.gravity);
|
return gravity.set(this.gravity);
|
||||||
}
|
}
|
||||||
@ -735,57 +902,89 @@ public class PhysicsSpace {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
/**
|
/**
|
||||||
* Adds the specified listener to the physics tick listeners. The listeners
|
* Register the specified tick listener with this space.
|
||||||
* are called on each physics step, which is not necessarily each frame but
|
* <p>
|
||||||
* is determined by the accuracy of the physics space.
|
* Tick listeners are notified before and after each physics step. A physics
|
||||||
|
* step is not necessarily the same as a frame; it is more influenced by the
|
||||||
|
* accuracy of the physics space.
|
||||||
*
|
*
|
||||||
* @param listener
|
* @see #setAccuracy(float)
|
||||||
|
*
|
||||||
|
* @param listener the listener to register (not null)
|
||||||
*/
|
*/
|
||||||
public void addTickListener(PhysicsTickListener listener) {
|
public void addTickListener(PhysicsTickListener listener) {
|
||||||
tickListeners.add(listener);
|
tickListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-register the specified tick listener.
|
||||||
|
*
|
||||||
|
* @see #addTickListener(com.jme3.bullet.PhysicsTickListener)
|
||||||
|
* @param listener the listener to de-register (not null)
|
||||||
|
*/
|
||||||
public void removeTickListener(PhysicsTickListener listener) {
|
public void removeTickListener(PhysicsTickListener listener) {
|
||||||
tickListeners.remove(listener);
|
tickListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a CollisionListener that will be informed about collision events
|
* Register the specified collision listener with this space.
|
||||||
|
* <p>
|
||||||
|
* Collision listeners are notified when collisions occur in the space.
|
||||||
*
|
*
|
||||||
* @param listener the CollisionListener to add
|
* @param listener the listener to register (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public void addCollisionListener(PhysicsCollisionListener listener) {
|
public void addCollisionListener(PhysicsCollisionListener listener) {
|
||||||
collisionListeners.add(listener);
|
collisionListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a CollisionListener from the list
|
* De-register the specified collision listener.
|
||||||
*
|
*
|
||||||
* @param listener the CollisionListener to remove
|
* @see
|
||||||
|
* #addCollisionListener(com.jme3.bullet.collision.PhysicsCollisionListener)
|
||||||
|
* @param listener the listener to de-register (not null)
|
||||||
*/
|
*/
|
||||||
public void removeCollisionListener(PhysicsCollisionListener listener) {
|
public void removeCollisionListener(PhysicsCollisionListener listener) {
|
||||||
collisionListeners.remove(listener);
|
collisionListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a listener for a specific collision group, such a listener can
|
* Register the specified collision-group listener with the specified
|
||||||
* disable collisions when they happen.<br> There can be only one listener
|
* collision group of this space.
|
||||||
* per collision group.
|
* <p>
|
||||||
|
* Such a listener can disable collisions when they occur. There can be only
|
||||||
|
* one listener per collision group per space.
|
||||||
*
|
*
|
||||||
* @param listener
|
* @param listener the listener to register (not null)
|
||||||
* @param collisionGroup
|
* @param collisionGroup which group it should listen for (bit mask with
|
||||||
|
* exactly one bit set)
|
||||||
*/
|
*/
|
||||||
public void addCollisionGroupListener(PhysicsCollisionGroupListener listener, int collisionGroup) {
|
public void addCollisionGroupListener(PhysicsCollisionGroupListener listener, int collisionGroup) {
|
||||||
collisionGroupListeners.put(collisionGroup, listener);
|
collisionGroupListeners.put(collisionGroup, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-register the specified collision-group listener.
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* #addCollisionGroupListener(com.jme3.bullet.collision.PhysicsCollisionGroupListener,
|
||||||
|
* int)
|
||||||
|
* @param collisionGroup the group of the listener to de-register (bit mask
|
||||||
|
* with exactly one bit set)
|
||||||
|
*/
|
||||||
public void removeCollisionGroupListener(int collisionGroup) {
|
public void removeCollisionGroupListener(int collisionGroup) {
|
||||||
collisionGroupListeners.remove(collisionGroup);
|
collisionGroupListeners.remove(collisionGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a ray collision test and returns the results as a list of
|
* Perform a ray-collision test and return the results as a list of
|
||||||
* PhysicsRayTestResults ordered by it hitFraction (lower to higher)
|
* PhysicsRayTestResults sorted by ascending hitFraction.
|
||||||
|
*
|
||||||
|
* @param from the starting location (physics-space coordinates, not null,
|
||||||
|
* unaffected)
|
||||||
|
* @param to the ending location (in physics-space coordinates, not null,
|
||||||
|
* unaffected)
|
||||||
|
* @return a new list of results (not null)
|
||||||
*/
|
*/
|
||||||
public List rayTest(Vector3f from, Vector3f to) {
|
public List rayTest(Vector3f from, Vector3f to) {
|
||||||
List<PhysicsRayTestResult> results = new ArrayList<PhysicsRayTestResult>();
|
List<PhysicsRayTestResult> results = new ArrayList<PhysicsRayTestResult>();
|
||||||
@ -795,8 +994,14 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a ray collision test and returns the results as a list of
|
* Perform a ray-collision test and return the results as a list of
|
||||||
* PhysicsRayTestResults without performing any sort operation
|
* PhysicsRayTestResults in arbitrary order.
|
||||||
|
*
|
||||||
|
* @param from the starting location (in physics-space coordinates, not
|
||||||
|
* null, unaffected)
|
||||||
|
* @param to the ending location (in physics-space coordinates, not null,
|
||||||
|
* unaffected)
|
||||||
|
* @return a new list of results (not null)
|
||||||
*/
|
*/
|
||||||
public List rayTestRaw(Vector3f from, Vector3f to) {
|
public List rayTestRaw(Vector3f from, Vector3f to) {
|
||||||
List<PhysicsRayTestResult> results = new ArrayList<PhysicsRayTestResult>();
|
List<PhysicsRayTestResult> results = new ArrayList<PhysicsRayTestResult>();
|
||||||
@ -806,17 +1011,22 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets m_flags for raytest, see https://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
|
* Alters the m_flags used in ray tests. see
|
||||||
|
* https://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
|
||||||
* for possible options. Defaults to using the faster, approximate raytest.
|
* for possible options. Defaults to using the faster, approximate raytest.
|
||||||
|
*
|
||||||
|
* @param flags the desired flags, ORed together (default=0x4)
|
||||||
*/
|
*/
|
||||||
public void SetRayTestFlags(int flags) {
|
public void SetRayTestFlags(int flags) {
|
||||||
rayTestFlags = flags;
|
rayTestFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets m_flags for raytest, see https://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
|
* Reads m_flags used in ray tests. see
|
||||||
|
* https://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
|
||||||
* for possible options.
|
* for possible options.
|
||||||
* @return rayTestFlags
|
*
|
||||||
|
* @return which flags are used
|
||||||
*/
|
*/
|
||||||
public int GetRayTestFlags() {
|
public int GetRayTestFlags() {
|
||||||
return rayTestFlags;
|
return rayTestFlags;
|
||||||
@ -831,8 +1041,15 @@ public class PhysicsSpace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a ray collision test and returns the results as a list of
|
* Perform a ray-collision test and return the results as a list of
|
||||||
* PhysicsRayTestResults ordered by it hitFraction (lower to higher)
|
* PhysicsRayTestResults sorted by ascending hitFraction.
|
||||||
|
*
|
||||||
|
* @param from coordinates of the starting location (in physics space, not
|
||||||
|
* null, unaffected)
|
||||||
|
* @param to coordinates of the ending location (in physics space, not null,
|
||||||
|
* unaffected)
|
||||||
|
* @param results the list to hold results (not null, modified)
|
||||||
|
* @return results
|
||||||
*/
|
*/
|
||||||
public List<PhysicsRayTestResult> rayTest(Vector3f from, Vector3f to, List<PhysicsRayTestResult> results) {
|
public List<PhysicsRayTestResult> rayTest(Vector3f from, Vector3f to, List<PhysicsRayTestResult> results) {
|
||||||
results.clear();
|
results.clear();
|
||||||
@ -843,8 +1060,15 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a ray collision test and returns the results as a list of
|
* Perform a ray-collision test and return the results as a list of
|
||||||
* PhysicsRayTestResults without performing any sort operation
|
* PhysicsRayTestResults in arbitrary order.
|
||||||
|
*
|
||||||
|
* @param from coordinates of the starting location (in physics space, not
|
||||||
|
* null, unaffected)
|
||||||
|
* @param to coordinates of the ending location (in physics space, not null,
|
||||||
|
* unaffected)
|
||||||
|
* @param results the list to hold results (not null, modified)
|
||||||
|
* @return results
|
||||||
*/
|
*/
|
||||||
public List<PhysicsRayTestResult> rayTestRaw(Vector3f from, Vector3f to, List<PhysicsRayTestResult> results) {
|
public List<PhysicsRayTestResult> rayTestRaw(Vector3f from, Vector3f to, List<PhysicsRayTestResult> results) {
|
||||||
results.clear();
|
results.clear();
|
||||||
@ -874,11 +1098,18 @@ public class PhysicsSpace {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a sweep collision test and returns the results as a list of
|
* Perform a sweep-collision test and return the results as a new list.
|
||||||
* PhysicsSweepTestResults<br/> You have to use different Transforms for
|
* <p>
|
||||||
* start and end (at least distance > 0.4f). SweepTest will not see a
|
* The starting and ending locations must be at least 0.4f physics-space
|
||||||
* collision if it starts INSIDE an object and is moving AWAY from its
|
* units apart.
|
||||||
* center.
|
* <p>
|
||||||
|
* A sweep test will miss a collision if it starts inside an object and
|
||||||
|
* sweeps away from the object's center.
|
||||||
|
*
|
||||||
|
* @param shape the shape to sweep (not null)
|
||||||
|
* @param start the starting physics-space transform (not null)
|
||||||
|
* @param end the ending physics-space transform (not null)
|
||||||
|
* @return a new list of results
|
||||||
*/
|
*/
|
||||||
public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end) {
|
public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end) {
|
||||||
List results = new LinkedList();
|
List results = new LinkedList();
|
||||||
@ -886,17 +1117,41 @@ public class PhysicsSpace {
|
|||||||
return (List<PhysicsSweepTestResult>) results;
|
return (List<PhysicsSweepTestResult>) results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a sweep-collision test and store the results in an existing list.
|
||||||
|
* <p>
|
||||||
|
* The starting and ending locations must be at least 0.4f physics-space
|
||||||
|
* units apart.
|
||||||
|
* <p>
|
||||||
|
* A sweep test will miss a collision if it starts inside an object and
|
||||||
|
* sweeps away from the object's center.
|
||||||
|
*
|
||||||
|
* @param shape the shape to sweep (not null)
|
||||||
|
* @param start the starting physics-space transform (not null)
|
||||||
|
* @param end the ending physics-space transform (not null)
|
||||||
|
* @param results the list to hold results (not null, modified)
|
||||||
|
* @return results
|
||||||
|
*/
|
||||||
public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end, List<PhysicsSweepTestResult> results) {
|
public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end, List<PhysicsSweepTestResult> results) {
|
||||||
return sweepTest(shape, start, end, results, 0.0f);
|
return sweepTest(shape, start, end, results, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public native void sweepTest_native(long shape, Transform from, Transform to, long physicsSpaceId, List<PhysicsSweepTestResult> results, float allowedCcdPenetration);
|
public native void sweepTest_native(long shape, Transform from, Transform to, long physicsSpaceId, List<PhysicsSweepTestResult> results, float allowedCcdPenetration);
|
||||||
/**
|
/**
|
||||||
* Performs a sweep collision test and returns the results as a list of
|
* Perform a sweep-collision test and store the results in an existing list.
|
||||||
* PhysicsSweepTestResults<br/> You have to use different Transforms for
|
* <p>
|
||||||
* start and end (at least distance > allowedCcdPenetration). SweepTest will not see a
|
* The starting and ending locations must be at least 0.4f physics-space
|
||||||
* collision if it starts INSIDE an object and is moving AWAY from its
|
* units apart.
|
||||||
* center.
|
* <p>
|
||||||
|
* A sweep test will miss a collision if it starts inside an object and
|
||||||
|
* sweeps away from the object's center.
|
||||||
|
*
|
||||||
|
* @param shape the shape to sweep (not null)
|
||||||
|
* @param start the starting physics-space transform (not null)
|
||||||
|
* @param end the ending physics-space transform (not null)
|
||||||
|
* @param results the list to hold results (not null, modified)
|
||||||
|
* @param allowedCcdPenetration true→allow, false→disallow
|
||||||
|
* @return results
|
||||||
*/
|
*/
|
||||||
public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end, List<PhysicsSweepTestResult> results, float allowedCcdPenetration ) {
|
public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end, List<PhysicsSweepTestResult> results, float allowedCcdPenetration ) {
|
||||||
results.clear();
|
results.clear();
|
||||||
@ -923,7 +1178,7 @@ public class PhysicsSpace {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroys the current PhysicsSpace so that a new one can be created
|
* Destroy this space so that a new one can be instantiated.
|
||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
physicsBodies.clear();
|
physicsBodies.clear();
|
||||||
@ -942,59 +1197,87 @@ public class PhysicsSpace {
|
|||||||
return physicsSpaceId;
|
return physicsSpaceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the type of acceleration structure used.
|
||||||
|
*
|
||||||
|
* @return an enum value (not null)
|
||||||
|
*/
|
||||||
public BroadphaseType getBroadphaseType() {
|
public BroadphaseType getBroadphaseType() {
|
||||||
return broadphaseType;
|
return broadphaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the type of acceleration structure used.
|
||||||
|
*
|
||||||
|
* @param broadphaseType the desired algorithm (not null)
|
||||||
|
*/
|
||||||
public void setBroadphaseType(BroadphaseType broadphaseType) {
|
public void setBroadphaseType(BroadphaseType broadphaseType) {
|
||||||
this.broadphaseType = broadphaseType;
|
this.broadphaseType = broadphaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum amount of extra steps that will be used to step the
|
* Alter the maximum number of physics steps per frame.
|
||||||
* physics when the fps is below the physics fps. Doing this maintains
|
* <p>
|
||||||
* determinism in physics. For example a maximum number of 2 can compensate
|
* Extra physics steps help maintain determinism when the render fps drops
|
||||||
* for framerates as low as 30fps when the physics has the default accuracy
|
* below 1/accuracy. For example a value of 2 can compensate for frame rates
|
||||||
* of 60 fps. Note that setting this value too high can make the physics
|
* as low as 30fps, assuming the physics has an accuracy of 1/60 sec.
|
||||||
* drive down its own fps in case it's overloaded.
|
* <p>
|
||||||
|
* Setting this value too high can depress the frame rate.
|
||||||
*
|
*
|
||||||
* @param steps The maximum number of extra steps, default is 4.
|
* @param steps the desired maximum number of steps per frame (≥1,
|
||||||
|
* default=4)
|
||||||
*/
|
*/
|
||||||
public void setMaxSubSteps(int steps) {
|
public void setMaxSubSteps(int steps) {
|
||||||
maxSubSteps = steps;
|
maxSubSteps = steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the current accuracy of the physics computation
|
* Read the accuracy (time step) of the physics simulation.
|
||||||
*
|
*
|
||||||
* @return the current accuracy
|
* @return the timestep (in seconds, >0)
|
||||||
*/
|
*/
|
||||||
public float getAccuracy() {
|
public float getAccuracy() {
|
||||||
return accuracy;
|
return accuracy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the accuracy of the physics computation, default=1/60s<br>
|
* Alter the accuracy (time step) of the physics simulation.
|
||||||
|
* <p>
|
||||||
|
* In general, the smaller the time step, the more accurate (and
|
||||||
|
* compute-intensive) the simulation will be. Bullet works best with a
|
||||||
|
* timestep of no more than 1/60 second.
|
||||||
*
|
*
|
||||||
* @param accuracy
|
* @param accuracy the desired time step (in seconds, >0, default=1/60)
|
||||||
*/
|
*/
|
||||||
public void setAccuracy(float accuracy) {
|
public void setAccuracy(float accuracy) {
|
||||||
this.accuracy = accuracy;
|
this.accuracy = accuracy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the minimum coordinate values for this space.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector
|
||||||
|
*/
|
||||||
public Vector3f getWorldMin() {
|
public Vector3f getWorldMin() {
|
||||||
return worldMin;
|
return worldMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* only applies for AXIS_SWEEP broadphase
|
* Alter the minimum coordinate values for this space. (only affects
|
||||||
|
* AXIS_SWEEP broadphase algorithms)
|
||||||
*
|
*
|
||||||
* @param worldMin
|
* @param worldMin the desired minimum coordinate values (not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
public void setWorldMin(Vector3f worldMin) {
|
public void setWorldMin(Vector3f worldMin) {
|
||||||
this.worldMin.set(worldMin);
|
this.worldMin.set(worldMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the maximum coordinate values for this space.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getWorldMax() {
|
public Vector3f getWorldMax() {
|
||||||
return worldMax;
|
return worldMax;
|
||||||
}
|
}
|
||||||
@ -1009,11 +1292,11 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the number of iterations used by the contact solver.
|
* Alter the number of iterations used by the contact-and-constraint solver.
|
||||||
*
|
* <p>
|
||||||
* The default is 10. Use 4 for low quality, 20 for high quality.
|
* Use 4 for low quality, 20 for high quality.
|
||||||
*
|
*
|
||||||
* @param numIterations The number of iterations used by the contact & constraint solver.
|
* @param numIterations the desired number of iterations (≥1, default=10)
|
||||||
*/
|
*/
|
||||||
public void setSolverNumIterations(int numIterations) {
|
public void setSolverNumIterations(int numIterations) {
|
||||||
this.solverNumIterations = numIterations;
|
this.solverNumIterations = numIterations;
|
||||||
@ -1021,9 +1304,9 @@ public class PhysicsSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of iterations used by the contact solver.
|
* Read the number of iterations used by the contact-and-constraint solver.
|
||||||
*
|
*
|
||||||
* @return The number of iterations used by the contact & constraint solver.
|
* @return the number of iterations used
|
||||||
*/
|
*/
|
||||||
public int getSolverNumIterations() {
|
public int getSolverNumIterations() {
|
||||||
return solverNumIterations;
|
return solverNumIterations;
|
||||||
@ -1034,28 +1317,40 @@ public class PhysicsSpace {
|
|||||||
public static native void initNativePhysics();
|
public static native void initNativePhysics();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* interface with Broadphase types
|
* Enumerate the available acceleration structures for broadphase collision
|
||||||
|
* detection.
|
||||||
*/
|
*/
|
||||||
public enum BroadphaseType {
|
public enum BroadphaseType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* basic Broadphase
|
* btSimpleBroadphase: a brute-force reference implementation for
|
||||||
|
* debugging purposes
|
||||||
*/
|
*/
|
||||||
SIMPLE,
|
SIMPLE,
|
||||||
/**
|
/**
|
||||||
* better Broadphase, needs worldBounds , max Object number = 16384
|
* btAxisSweep3: uses incremental 3-D sweep and prune, requires world
|
||||||
|
* bounds, limited to 16_384 objects
|
||||||
*/
|
*/
|
||||||
AXIS_SWEEP_3,
|
AXIS_SWEEP_3,
|
||||||
/**
|
/**
|
||||||
* better Broadphase, needs worldBounds , max Object number = 65536
|
* bt32BitAxisSweep3: uses incremental 3-D sweep and prune, requires
|
||||||
|
* world bounds, limited to 65_536 objects
|
||||||
*/
|
*/
|
||||||
AXIS_SWEEP_3_32,
|
AXIS_SWEEP_3_32,
|
||||||
/**
|
/**
|
||||||
* Broadphase allowing quicker adding/removing of physics objects
|
* btDbvtBroadphase: uses a fast, dynamic bounding-volume hierarchy
|
||||||
|
* based on AABB tree to allow quicker addition/removal of physics
|
||||||
|
* objects
|
||||||
*/
|
*/
|
||||||
DBVT;
|
DBVT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this physics space just before it is destroyed. Should be
|
||||||
|
* invoked only by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -36,21 +36,53 @@ import com.jme3.scene.Spatial;
|
|||||||
import java.util.EventObject;
|
import java.util.EventObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CollisionEvent stores all information about a collision in the PhysicsWorld.
|
* An event that describes a collision in the physics world.
|
||||||
* Do not store this Object, as it will be reused after the collision() method has been called.
|
* <p>
|
||||||
* Get/reference all data you need in the collide method.
|
* Do not retain this object, as it will be reused after the collision() method
|
||||||
|
* returns. Copy any data you need during the collide() method.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsCollisionEvent extends EventObject {
|
public class PhysicsCollisionEvent extends EventObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* type value to indicate a new event
|
||||||
|
*/
|
||||||
public static final int TYPE_ADDED = 0;
|
public static final int TYPE_ADDED = 0;
|
||||||
|
/**
|
||||||
|
* type value to indicate an event that has been added to a PhysicsSpace
|
||||||
|
* queue
|
||||||
|
*/
|
||||||
public static final int TYPE_PROCESSED = 1;
|
public static final int TYPE_PROCESSED = 1;
|
||||||
|
/**
|
||||||
|
* type value to indicate a cleaned/destroyed event
|
||||||
|
*/
|
||||||
public static final int TYPE_DESTROYED = 2;
|
public static final int TYPE_DESTROYED = 2;
|
||||||
|
/**
|
||||||
|
* type value that indicates the event's status
|
||||||
|
*/
|
||||||
private int type;
|
private int type;
|
||||||
|
/**
|
||||||
|
* 1st involved object
|
||||||
|
*/
|
||||||
private PhysicsCollisionObject nodeA;
|
private PhysicsCollisionObject nodeA;
|
||||||
|
/**
|
||||||
|
* 2nd involved object
|
||||||
|
*/
|
||||||
private PhysicsCollisionObject nodeB;
|
private PhysicsCollisionObject nodeB;
|
||||||
|
/**
|
||||||
|
* Bullet identifier of the btManifoldPoint
|
||||||
|
*/
|
||||||
private long manifoldPointObjectId = 0;
|
private long manifoldPointObjectId = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a collision event.
|
||||||
|
*
|
||||||
|
* @param type event type (0=added/1=processed/2=destroyed)
|
||||||
|
* @param nodeA 1st involved object (alias created)
|
||||||
|
* @param nodeB 2nd involved object (alias created)
|
||||||
|
* @param manifoldPointObjectId Bullet identifier of the btManifoldPoint
|
||||||
|
*/
|
||||||
public PhysicsCollisionEvent(int type, PhysicsCollisionObject nodeA, PhysicsCollisionObject nodeB, long manifoldPointObjectId) {
|
public PhysicsCollisionEvent(int type, PhysicsCollisionObject nodeA, PhysicsCollisionObject nodeB, long manifoldPointObjectId) {
|
||||||
super(nodeA);
|
super(nodeA);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -58,9 +90,9 @@ public class PhysicsCollisionEvent extends EventObject {
|
|||||||
this.nodeB = nodeB;
|
this.nodeB = nodeB;
|
||||||
this.manifoldPointObjectId = manifoldPointObjectId;
|
this.manifoldPointObjectId = manifoldPointObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used by event factory, called when event is destroyed
|
* Destroy this event.
|
||||||
*/
|
*/
|
||||||
public void clean() {
|
public void clean() {
|
||||||
source = null;
|
source = null;
|
||||||
@ -71,7 +103,12 @@ public class PhysicsCollisionEvent extends EventObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used by event factory, called when event reused
|
* Reuse this event.
|
||||||
|
*
|
||||||
|
* @param type event type (added/processed/destroyed)
|
||||||
|
* @param source 1st involved object (alias created)
|
||||||
|
* @param nodeB 2nd involved object (alias created)
|
||||||
|
* @param manifoldPointObjectId Bullet identifier
|
||||||
*/
|
*/
|
||||||
public void refactor(int type, PhysicsCollisionObject source, PhysicsCollisionObject nodeB, long manifoldPointObjectId) {
|
public void refactor(int type, PhysicsCollisionObject source, PhysicsCollisionObject nodeB, long manifoldPointObjectId) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
@ -81,12 +118,19 @@ public class PhysicsCollisionEvent extends EventObject {
|
|||||||
this.manifoldPointObjectId = manifoldPointObjectId;
|
this.manifoldPointObjectId = manifoldPointObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the type of event.
|
||||||
|
*
|
||||||
|
* @return added/processed/destroyed
|
||||||
|
*/
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A Spatial if the UserObject of the PhysicsCollisionObject is a Spatial
|
* Access the user object of collision object A, provided it's a Spatial.
|
||||||
|
*
|
||||||
|
* @return the pre-existing Spatial, or null if none
|
||||||
*/
|
*/
|
||||||
public Spatial getNodeA() {
|
public Spatial getNodeA() {
|
||||||
if (nodeA.getUserObject() instanceof Spatial) {
|
if (nodeA.getUserObject() instanceof Spatial) {
|
||||||
@ -96,7 +140,9 @@ public class PhysicsCollisionEvent extends EventObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A Spatial if the UserObject of the PhysicsCollisionObject is a Spatial
|
* Access the user object of collision object B, provided it's a Spatial.
|
||||||
|
*
|
||||||
|
* @return the pre-existing Spatial, or null if none
|
||||||
*/
|
*/
|
||||||
public Spatial getNodeB() {
|
public Spatial getNodeB() {
|
||||||
if (nodeB.getUserObject() instanceof Spatial) {
|
if (nodeB.getUserObject() instanceof Spatial) {
|
||||||
@ -105,139 +151,286 @@ public class PhysicsCollisionEvent extends EventObject {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access collision object A.
|
||||||
|
*
|
||||||
|
* @return the pre-existing object (not null)
|
||||||
|
*/
|
||||||
public PhysicsCollisionObject getObjectA() {
|
public PhysicsCollisionObject getObjectA() {
|
||||||
return nodeA;
|
return nodeA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access collision object B.
|
||||||
|
*
|
||||||
|
* @return the pre-existing object (not null)
|
||||||
|
*/
|
||||||
public PhysicsCollisionObject getObjectB() {
|
public PhysicsCollisionObject getObjectB() {
|
||||||
return nodeB;
|
return nodeB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's applied impulse.
|
||||||
|
*
|
||||||
|
* @return impulse
|
||||||
|
*/
|
||||||
public float getAppliedImpulse() {
|
public float getAppliedImpulse() {
|
||||||
return getAppliedImpulse(manifoldPointObjectId);
|
return getAppliedImpulse(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native float getAppliedImpulse(long manifoldPointObjectId);
|
private native float getAppliedImpulse(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's applied lateral impulse #1.
|
||||||
|
*
|
||||||
|
* @return impulse
|
||||||
|
*/
|
||||||
public float getAppliedImpulseLateral1() {
|
public float getAppliedImpulseLateral1() {
|
||||||
return getAppliedImpulseLateral1(manifoldPointObjectId);
|
return getAppliedImpulseLateral1(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native float getAppliedImpulseLateral1(long manifoldPointObjectId);
|
private native float getAppliedImpulseLateral1(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's applied lateral impulse #2.
|
||||||
|
*
|
||||||
|
* @return impulse
|
||||||
|
*/
|
||||||
public float getAppliedImpulseLateral2() {
|
public float getAppliedImpulseLateral2() {
|
||||||
return getAppliedImpulseLateral2(manifoldPointObjectId);
|
return getAppliedImpulseLateral2(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native float getAppliedImpulseLateral2(long manifoldPointObjectId);
|
private native float getAppliedImpulseLateral2(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's combined friction.
|
||||||
|
*
|
||||||
|
* @return friction
|
||||||
|
*/
|
||||||
public float getCombinedFriction() {
|
public float getCombinedFriction() {
|
||||||
return getCombinedFriction(manifoldPointObjectId);
|
return getCombinedFriction(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native float getCombinedFriction(long manifoldPointObjectId);
|
private native float getCombinedFriction(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's combined restitution.
|
||||||
|
*
|
||||||
|
* @return restitution
|
||||||
|
*/
|
||||||
public float getCombinedRestitution() {
|
public float getCombinedRestitution() {
|
||||||
return getCombinedRestitution(manifoldPointObjectId);
|
return getCombinedRestitution(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native float getCombinedRestitution(long manifoldPointObjectId);
|
private native float getCombinedRestitution(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's distance #1.
|
||||||
|
*
|
||||||
|
* @return distance
|
||||||
|
*/
|
||||||
public float getDistance1() {
|
public float getDistance1() {
|
||||||
return getDistance1(manifoldPointObjectId);
|
return getDistance1(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native float getDistance1(long manifoldPointObjectId);
|
private native float getDistance1(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's index 0.
|
||||||
|
*
|
||||||
|
* @return index
|
||||||
|
*/
|
||||||
public int getIndex0() {
|
public int getIndex0() {
|
||||||
return getIndex0(manifoldPointObjectId);
|
return getIndex0(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native int getIndex0(long manifoldPointObjectId);
|
private native int getIndex0(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's index 1.
|
||||||
|
*
|
||||||
|
* @return index
|
||||||
|
*/
|
||||||
public int getIndex1() {
|
public int getIndex1() {
|
||||||
return getIndex1(manifoldPointObjectId);
|
return getIndex1(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native int getIndex1(long manifoldPointObjectId);
|
private native int getIndex1(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's lateral friction direction #1.
|
||||||
|
*
|
||||||
|
* @return a new vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getLateralFrictionDir1() {
|
public Vector3f getLateralFrictionDir1() {
|
||||||
return getLateralFrictionDir1(new Vector3f());
|
return getLateralFrictionDir1(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's lateral friction direction #1.
|
||||||
|
*
|
||||||
|
* @param lateralFrictionDir1 storage for the result (not null, modified)
|
||||||
|
* @return direction vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getLateralFrictionDir1(Vector3f lateralFrictionDir1) {
|
public Vector3f getLateralFrictionDir1(Vector3f lateralFrictionDir1) {
|
||||||
getLateralFrictionDir1(manifoldPointObjectId, lateralFrictionDir1);
|
getLateralFrictionDir1(manifoldPointObjectId, lateralFrictionDir1);
|
||||||
return lateralFrictionDir1;
|
return lateralFrictionDir1;
|
||||||
}
|
}
|
||||||
private native void getLateralFrictionDir1(long manifoldPointObjectId, Vector3f lateralFrictionDir1);
|
private native void getLateralFrictionDir1(long manifoldPointObjectId, Vector3f lateralFrictionDir1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's lateral friction direction #2.
|
||||||
|
*
|
||||||
|
* @return a new vector
|
||||||
|
*/
|
||||||
public Vector3f getLateralFrictionDir2() {
|
public Vector3f getLateralFrictionDir2() {
|
||||||
return getLateralFrictionDir2(new Vector3f());
|
return getLateralFrictionDir2(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's lateral friction direction #2.
|
||||||
|
*
|
||||||
|
* @param lateralFrictionDir2 storage for the result (not null, modified)
|
||||||
|
* @return direction vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getLateralFrictionDir2(Vector3f lateralFrictionDir2) {
|
public Vector3f getLateralFrictionDir2(Vector3f lateralFrictionDir2) {
|
||||||
getLateralFrictionDir2(manifoldPointObjectId, lateralFrictionDir2);
|
getLateralFrictionDir2(manifoldPointObjectId, lateralFrictionDir2);
|
||||||
return lateralFrictionDir2;
|
return lateralFrictionDir2;
|
||||||
}
|
}
|
||||||
private native void getLateralFrictionDir2(long manifoldPointObjectId, Vector3f lateralFrictionDir2);
|
private native void getLateralFrictionDir2(long manifoldPointObjectId, Vector3f lateralFrictionDir2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the collision's lateral friction is initialized.
|
||||||
|
*
|
||||||
|
* @return true if initialized, otherwise false
|
||||||
|
*/
|
||||||
public boolean isLateralFrictionInitialized() {
|
public boolean isLateralFrictionInitialized() {
|
||||||
return isLateralFrictionInitialized(manifoldPointObjectId);
|
return isLateralFrictionInitialized(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native boolean isLateralFrictionInitialized(long manifoldPointObjectId);
|
private native boolean isLateralFrictionInitialized(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision's lifetime.
|
||||||
|
*
|
||||||
|
* @return lifetime
|
||||||
|
*/
|
||||||
public int getLifeTime() {
|
public int getLifeTime() {
|
||||||
return getLifeTime(manifoldPointObjectId);
|
return getLifeTime(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native int getLifeTime(long manifoldPointObjectId);
|
private native int getLifeTime(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location in the local coordinates of object A.
|
||||||
|
*
|
||||||
|
* @return a new location vector (in local coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getLocalPointA() {
|
public Vector3f getLocalPointA() {
|
||||||
return getLocalPointA(new Vector3f());
|
return getLocalPointA(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location in the local coordinates of object A.
|
||||||
|
*
|
||||||
|
* @param localPointA storage for the result (not null, modified)
|
||||||
|
* @return a location vector (in local coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getLocalPointA(Vector3f localPointA) {
|
public Vector3f getLocalPointA(Vector3f localPointA) {
|
||||||
getLocalPointA(manifoldPointObjectId, localPointA);
|
getLocalPointA(manifoldPointObjectId, localPointA);
|
||||||
return localPointA;
|
return localPointA;
|
||||||
}
|
}
|
||||||
private native void getLocalPointA(long manifoldPointObjectId, Vector3f localPointA);
|
private native void getLocalPointA(long manifoldPointObjectId, Vector3f localPointA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location in the local coordinates of object B.
|
||||||
|
*
|
||||||
|
* @return a new location vector (in local coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getLocalPointB() {
|
public Vector3f getLocalPointB() {
|
||||||
return getLocalPointB(new Vector3f());
|
return getLocalPointB(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location in the local coordinates of object B.
|
||||||
|
*
|
||||||
|
* @param localPointB storage for the result (not null, modified)
|
||||||
|
* @return a location vector (in local coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getLocalPointB(Vector3f localPointB) {
|
public Vector3f getLocalPointB(Vector3f localPointB) {
|
||||||
getLocalPointB(manifoldPointObjectId, localPointB);
|
getLocalPointB(manifoldPointObjectId, localPointB);
|
||||||
return localPointB;
|
return localPointB;
|
||||||
}
|
}
|
||||||
private native void getLocalPointB(long manifoldPointObjectId, Vector3f localPointB);
|
private native void getLocalPointB(long manifoldPointObjectId, Vector3f localPointB);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's normal on object B.
|
||||||
|
*
|
||||||
|
* @return a new normal vector (in physics-space coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getNormalWorldOnB() {
|
public Vector3f getNormalWorldOnB() {
|
||||||
return getNormalWorldOnB(new Vector3f());
|
return getNormalWorldOnB(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's normal on object B.
|
||||||
|
*
|
||||||
|
* @param normalWorldOnB storage for the result (not null, modified)
|
||||||
|
* @return a normal vector (in physics-space coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getNormalWorldOnB(Vector3f normalWorldOnB) {
|
public Vector3f getNormalWorldOnB(Vector3f normalWorldOnB) {
|
||||||
getNormalWorldOnB(manifoldPointObjectId, normalWorldOnB);
|
getNormalWorldOnB(manifoldPointObjectId, normalWorldOnB);
|
||||||
return normalWorldOnB;
|
return normalWorldOnB;
|
||||||
}
|
}
|
||||||
private native void getNormalWorldOnB(long manifoldPointObjectId, Vector3f normalWorldOnB);
|
private native void getNormalWorldOnB(long manifoldPointObjectId, Vector3f normalWorldOnB);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read part identifier 0.
|
||||||
|
*
|
||||||
|
* @return identifier
|
||||||
|
*/
|
||||||
public int getPartId0() {
|
public int getPartId0() {
|
||||||
return getPartId0(manifoldPointObjectId);
|
return getPartId0(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
private native int getPartId0(long manifoldPointObjectId);
|
private native int getPartId0(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read part identifier 1.
|
||||||
|
*
|
||||||
|
* @return identifier
|
||||||
|
*/
|
||||||
public int getPartId1() {
|
public int getPartId1() {
|
||||||
return getPartId1(manifoldPointObjectId);
|
return getPartId1(manifoldPointObjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native int getPartId1(long manifoldPointObjectId);
|
private native int getPartId1(long manifoldPointObjectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location.
|
||||||
|
*
|
||||||
|
* @return a new vector (in physics-space coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getPositionWorldOnA() {
|
public Vector3f getPositionWorldOnA() {
|
||||||
return getPositionWorldOnA(new Vector3f());
|
return getPositionWorldOnA(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location.
|
||||||
|
*
|
||||||
|
* @param positionWorldOnA storage for the result (not null, modified)
|
||||||
|
* @return a location vector (in physics-space coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getPositionWorldOnA(Vector3f positionWorldOnA) {
|
public Vector3f getPositionWorldOnA(Vector3f positionWorldOnA) {
|
||||||
getPositionWorldOnA(manifoldPointObjectId, positionWorldOnA);
|
getPositionWorldOnA(manifoldPointObjectId, positionWorldOnA);
|
||||||
return positionWorldOnA;
|
return positionWorldOnA;
|
||||||
}
|
}
|
||||||
private native void getPositionWorldOnA(long manifoldPointObjectId, Vector3f positionWorldOnA);
|
private native void getPositionWorldOnA(long manifoldPointObjectId, Vector3f positionWorldOnA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location.
|
||||||
|
*
|
||||||
|
* @return a new location vector (in physics-space coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getPositionWorldOnB() {
|
public Vector3f getPositionWorldOnB() {
|
||||||
return getPositionWorldOnB(new Vector3f());
|
return getPositionWorldOnB(new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the collision's location.
|
||||||
|
*
|
||||||
|
* @param positionWorldOnB storage for the result (not null, modified)
|
||||||
|
* @return a location vector (in physics-space coordinates, not null)
|
||||||
|
*/
|
||||||
public Vector3f getPositionWorldOnB(Vector3f positionWorldOnB) {
|
public Vector3f getPositionWorldOnB(Vector3f positionWorldOnB) {
|
||||||
getPositionWorldOnB(manifoldPointObjectId, positionWorldOnB);
|
getPositionWorldOnB(manifoldPointObjectId, positionWorldOnB);
|
||||||
return positionWorldOnB;
|
return positionWorldOnB;
|
||||||
|
@ -41,6 +41,11 @@ public class PhysicsCollisionEventFactory {
|
|||||||
|
|
||||||
private ConcurrentLinkedQueue<PhysicsCollisionEvent> eventBuffer = new ConcurrentLinkedQueue<PhysicsCollisionEvent>();
|
private ConcurrentLinkedQueue<PhysicsCollisionEvent> eventBuffer = new ConcurrentLinkedQueue<PhysicsCollisionEvent>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain an unused event.
|
||||||
|
*
|
||||||
|
* @return an event (not null)
|
||||||
|
*/
|
||||||
public PhysicsCollisionEvent getEvent(int type, PhysicsCollisionObject source, PhysicsCollisionObject nodeB, long manifoldPointObjectId) {
|
public PhysicsCollisionEvent getEvent(int type, PhysicsCollisionObject source, PhysicsCollisionObject nodeB, long manifoldPointObjectId) {
|
||||||
PhysicsCollisionEvent event = eventBuffer.poll();
|
PhysicsCollisionEvent event = eventBuffer.poll();
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
@ -51,6 +56,11 @@ public class PhysicsCollisionEventFactory {
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recycle the specified event.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
public void recycle(PhysicsCollisionEvent event) {
|
public void recycle(PhysicsCollisionEvent event) {
|
||||||
event.clean();
|
event.clean();
|
||||||
eventBuffer.add(event);
|
eventBuffer.add(event);
|
||||||
|
@ -38,67 +38,147 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for collision objects (PhysicsRigidBody, PhysicsGhostObject)
|
* The abstract base class for collision objects based on Bullet's
|
||||||
|
* btCollisionObject.
|
||||||
|
* <p>
|
||||||
|
* Collision objects include PhysicsCharacter, PhysicsRigidBody, and
|
||||||
|
* PhysicsGhostObject.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public abstract class PhysicsCollisionObject implements Savable {
|
public abstract class PhysicsCollisionObject implements Savable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier of the btCollisionObject. Constructors are responsible
|
||||||
|
* for setting this to a non-zero value. The id might change if the object
|
||||||
|
* gets rebuilt.
|
||||||
|
*/
|
||||||
protected long objectId = 0;
|
protected long objectId = 0;
|
||||||
|
/**
|
||||||
|
* shape associated with this object (not null)
|
||||||
|
*/
|
||||||
protected CollisionShape collisionShape;
|
protected CollisionShape collisionShape;
|
||||||
|
/**
|
||||||
|
* collideWithGroups bitmask that represents "no groups"
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_NONE = 0x00000000;
|
public static final int COLLISION_GROUP_NONE = 0x00000000;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #1
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_01 = 0x00000001;
|
public static final int COLLISION_GROUP_01 = 0x00000001;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #2
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_02 = 0x00000002;
|
public static final int COLLISION_GROUP_02 = 0x00000002;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #3
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_03 = 0x00000004;
|
public static final int COLLISION_GROUP_03 = 0x00000004;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #4
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_04 = 0x00000008;
|
public static final int COLLISION_GROUP_04 = 0x00000008;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #5
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_05 = 0x00000010;
|
public static final int COLLISION_GROUP_05 = 0x00000010;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #6
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_06 = 0x00000020;
|
public static final int COLLISION_GROUP_06 = 0x00000020;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #7
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_07 = 0x00000040;
|
public static final int COLLISION_GROUP_07 = 0x00000040;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #8
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_08 = 0x00000080;
|
public static final int COLLISION_GROUP_08 = 0x00000080;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #9
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_09 = 0x00000100;
|
public static final int COLLISION_GROUP_09 = 0x00000100;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #10
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_10 = 0x00000200;
|
public static final int COLLISION_GROUP_10 = 0x00000200;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #11
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_11 = 0x00000400;
|
public static final int COLLISION_GROUP_11 = 0x00000400;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #12
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_12 = 0x00000800;
|
public static final int COLLISION_GROUP_12 = 0x00000800;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #13
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_13 = 0x00001000;
|
public static final int COLLISION_GROUP_13 = 0x00001000;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #14
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_14 = 0x00002000;
|
public static final int COLLISION_GROUP_14 = 0x00002000;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #15
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_15 = 0x00004000;
|
public static final int COLLISION_GROUP_15 = 0x00004000;
|
||||||
|
/**
|
||||||
|
* collisionGroup/collideWithGroups bitmask that represents group #16
|
||||||
|
*/
|
||||||
public static final int COLLISION_GROUP_16 = 0x00008000;
|
public static final int COLLISION_GROUP_16 = 0x00008000;
|
||||||
|
/**
|
||||||
|
* collision group to which this physics object belongs (default=group #1)
|
||||||
|
*/
|
||||||
protected int collisionGroup = 0x00000001;
|
protected int collisionGroup = 0x00000001;
|
||||||
|
/**
|
||||||
|
* collision groups with which this object can collide (default=only group
|
||||||
|
* #1)
|
||||||
|
*/
|
||||||
protected int collisionGroupsMask = 0x00000001;
|
protected int collisionGroupsMask = 0x00000001;
|
||||||
private Object userObject;
|
private Object userObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a CollisionShape to this physics object, note that the object should
|
* Apply the specified CollisionShape to this object. Note that the object
|
||||||
* not be in the physics space when adding a new collision shape as it is rebuilt
|
* should not be in any physics space while changing shape; the object gets
|
||||||
* on the physics side.
|
* rebuilt on the physics side.
|
||||||
* @param collisionShape the CollisionShape to set
|
*
|
||||||
|
* @param collisionShape the shape to apply (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public void setCollisionShape(CollisionShape collisionShape) {
|
public void setCollisionShape(CollisionShape collisionShape) {
|
||||||
this.collisionShape = collisionShape;
|
this.collisionShape = collisionShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the CollisionShape of this PhysicsNode, to be able to reuse it with
|
* Access the shape of this physics object.
|
||||||
* other physics nodes (increases performance)
|
*
|
||||||
|
* @return the pre-existing instance, which can then be applied to other
|
||||||
|
* physics objects (increases performance)
|
||||||
*/
|
*/
|
||||||
public CollisionShape getCollisionShape() {
|
public CollisionShape getCollisionShape() {
|
||||||
return collisionShape;
|
return collisionShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the collision group for this collision shape
|
* Read the collision group for this physics object.
|
||||||
* @return The collision group
|
*
|
||||||
|
* @return the collision group (bit mask with exactly one bit set)
|
||||||
*/
|
*/
|
||||||
public int getCollisionGroup() {
|
public int getCollisionGroup() {
|
||||||
return collisionGroup;
|
return collisionGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the collision group number for this physics object. <br>
|
* Alter the collision group for this physics object.
|
||||||
* The groups are integer bit masks and some pre-made variables are available in CollisionObject.
|
* <p>
|
||||||
* All physics objects are by default in COLLISION_GROUP_01.<br>
|
* Groups are represented by integer bit masks with exactly 1 bit set.
|
||||||
* Two object will collide when <b>one</b> of the parties has the
|
* Pre-made variables are available in PhysicsCollisionObject. By default,
|
||||||
* collisionGroup of the other in its collideWithGroups set.
|
* physics objects are in COLLISION_GROUP_01.
|
||||||
* @param collisionGroup the collisionGroup to set
|
* <p>
|
||||||
|
* Two objects can collide only if one of them has the collisionGroup of the
|
||||||
|
* other in its collideWithGroups set.
|
||||||
|
*
|
||||||
|
* @param collisionGroup the collisionGroup to apply (bit mask with exactly
|
||||||
|
* 1 bit set)
|
||||||
*/
|
*/
|
||||||
public void setCollisionGroup(int collisionGroup) {
|
public void setCollisionGroup(int collisionGroup) {
|
||||||
this.collisionGroup = collisionGroup;
|
this.collisionGroup = collisionGroup;
|
||||||
@ -108,10 +188,12 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a group that this object will collide with.<br>
|
* Add collision groups to the set with which this object can collide.
|
||||||
* Two object will collide when <b>one</b> of the parties has the
|
*
|
||||||
* collisionGroup of the other in its collideWithGroups set.<br>
|
* Two objects can collide only if one of them has the collisionGroup of the
|
||||||
* @param collisionGroup
|
* other in its collideWithGroups set.
|
||||||
|
*
|
||||||
|
* @param collisionGroup groups to add (bit mask)
|
||||||
*/
|
*/
|
||||||
public void addCollideWithGroup(int collisionGroup) {
|
public void addCollideWithGroup(int collisionGroup) {
|
||||||
this.collisionGroupsMask = this.collisionGroupsMask | collisionGroup;
|
this.collisionGroupsMask = this.collisionGroupsMask | collisionGroup;
|
||||||
@ -121,8 +203,9 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a group from the list this object collides with.
|
* Remove collision groups from the set with which this object can collide.
|
||||||
* @param collisionGroup
|
*
|
||||||
|
* @param collisionGroup groups to remove, ORed together (bit mask)
|
||||||
*/
|
*/
|
||||||
public void removeCollideWithGroup(int collisionGroup) {
|
public void removeCollideWithGroup(int collisionGroup) {
|
||||||
this.collisionGroupsMask = this.collisionGroupsMask & ~collisionGroup;
|
this.collisionGroupsMask = this.collisionGroupsMask & ~collisionGroup;
|
||||||
@ -132,8 +215,9 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directly set the bitmask for collision groups that this object collides with.
|
* Directly alter the collision groups with which this object can collide.
|
||||||
* @param collisionGroups
|
*
|
||||||
|
* @param collisionGroups desired groups, ORed together (bit mask)
|
||||||
*/
|
*/
|
||||||
public void setCollideWithGroups(int collisionGroups) {
|
public void setCollideWithGroups(int collisionGroups) {
|
||||||
this.collisionGroupsMask = collisionGroups;
|
this.collisionGroupsMask = collisionGroups;
|
||||||
@ -143,13 +227,17 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the bitmask of collision groups that this object collides with.
|
* Read the set of collision groups with which this object can collide.
|
||||||
* @return Collision groups mask
|
*
|
||||||
|
* @return bit mask
|
||||||
*/
|
*/
|
||||||
public int getCollideWithGroups() {
|
public int getCollideWithGroups() {
|
||||||
return collisionGroupsMask;
|
return collisionGroupsMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the user pointer and collision-group information of this object.
|
||||||
|
*/
|
||||||
protected void initUserPointer() {
|
protected void initUserPointer() {
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "initUserPointer() objectId = {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "initUserPointer() objectId = {0}", Long.toHexString(objectId));
|
||||||
initUserPointer(objectId, collisionGroup, collisionGroupsMask);
|
initUserPointer(objectId, collisionGroup, collisionGroupsMask);
|
||||||
@ -157,27 +245,51 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
native void initUserPointer(long objectId, int group, int groups);
|
native void initUserPointer(long objectId, int group, int groups);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the userObject
|
* Access the user object associated with this collision object.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance, or null if none
|
||||||
*/
|
*/
|
||||||
public Object getUserObject() {
|
public Object getUserObject() {
|
||||||
return userObject;
|
return userObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param userObject the userObject to set
|
* Associate a user object (such as a Spatial) with this collision object.
|
||||||
|
*
|
||||||
|
* @param userObject the object to associate with this collision object
|
||||||
|
* (alias created, may be null)
|
||||||
*/
|
*/
|
||||||
public void setUserObject(Object userObject) {
|
public void setUserObject(Object userObject) {
|
||||||
this.userObject = userObject;
|
this.userObject = userObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getObjectId(){
|
/**
|
||||||
|
* Read the id of the btCollisionObject.
|
||||||
|
*
|
||||||
|
* @return the unique identifier (not zero)
|
||||||
|
*/
|
||||||
|
public long getObjectId(){
|
||||||
return objectId;
|
return objectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach the identified btCollisionShape to the identified
|
||||||
|
* btCollisionObject. Native method.
|
||||||
|
*
|
||||||
|
* @param objectId the unique identifier of the btCollisionObject (not zero)
|
||||||
|
* @param collisionShapeId the unique identifier of the btCollisionShape
|
||||||
|
* (not zero)
|
||||||
|
*/
|
||||||
protected native void attachCollisionShape(long objectId, long collisionShapeId);
|
protected native void attachCollisionShape(long objectId, long collisionShapeId);
|
||||||
native void setCollisionGroup(long objectId, int collisionGroup);
|
native void setCollisionGroup(long objectId, int collisionGroup);
|
||||||
native void setCollideWithGroups(long objectId, int collisionGroups);
|
native void setCollideWithGroups(long objectId, int collisionGroups);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this object, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param e exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter e) throws IOException {
|
public void write(JmeExporter e) throws IOException {
|
||||||
OutputCapsule capsule = e.getCapsule(this);
|
OutputCapsule capsule = e.getCapsule(this);
|
||||||
@ -186,6 +298,12 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
capsule.write(collisionShape, "collisionShape", null);
|
capsule.write(collisionShape, "collisionShape", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this object, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param e importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
InputCapsule capsule = e.getCapsule(this);
|
InputCapsule capsule = e.getCapsule(this);
|
||||||
@ -195,6 +313,12 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
collisionShape = shape;
|
collisionShape = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this collision object just before it is destroyed. Should be
|
||||||
|
* invoked only by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
@ -202,5 +326,10 @@ public abstract class PhysicsCollisionObject implements Savable {
|
|||||||
finalizeNative(objectId);
|
finalizeNative(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize the identified btCollisionObject. Native method.
|
||||||
|
*
|
||||||
|
* @param objectId the unique identifier of the btCollisionObject (not zero)
|
||||||
|
*/
|
||||||
protected native void finalizeNative(long objectId);
|
protected native void finalizeNative(long objectId);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,47 +34,67 @@ package com.jme3.bullet.collision;
|
|||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the results of a PhysicsSpace rayTest
|
* Represent the results of a Bullet ray test.
|
||||||
* bulletAppState.getPhysicsSpace().rayTest(new Vector3f(0,1000,0),new Vector3f(0,-1000,0));
|
*
|
||||||
javap -s java.util.List
|
|
||||||
* @author Empire-Phoenix,normenhansen
|
* @author Empire-Phoenix,normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsRayTestResult {
|
public class PhysicsRayTestResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* collision object that was hit
|
||||||
|
*/
|
||||||
private PhysicsCollisionObject collisionObject;
|
private PhysicsCollisionObject collisionObject;
|
||||||
|
/**
|
||||||
|
* normal vector at the point of contact
|
||||||
|
*/
|
||||||
private Vector3f hitNormalLocal;
|
private Vector3f hitNormalLocal;
|
||||||
|
/**
|
||||||
|
* fraction of the ray's total length (from=0, to=1, ≥0, ≤1)
|
||||||
|
*/
|
||||||
private float hitFraction;
|
private float hitFraction;
|
||||||
|
/**
|
||||||
|
* true→need to transform normal into world space
|
||||||
|
*/
|
||||||
private boolean normalInWorldSpace = true;
|
private boolean normalInWorldSpace = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* allocated by native code only
|
* A private constructor to inhibit instantiation of this class by Java.
|
||||||
|
* These results are instantiated exclusively by native code.
|
||||||
*/
|
*/
|
||||||
private PhysicsRayTestResult() {
|
private PhysicsRayTestResult() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the collisionObject
|
* Access the collision object that was hit.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public PhysicsCollisionObject getCollisionObject() {
|
public PhysicsCollisionObject getCollisionObject() {
|
||||||
return collisionObject;
|
return collisionObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the hitNormalLocal
|
* Access the normal vector at the point of contact.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getHitNormalLocal() {
|
public Vector3f getHitNormalLocal() {
|
||||||
return hitNormalLocal;
|
return hitNormalLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the hitFraction
|
* Read the fraction of the ray's total length.
|
||||||
|
*
|
||||||
|
* @return fraction (from=0, to=1, ≥0, ≤1)
|
||||||
*/
|
*/
|
||||||
public float getHitFraction() {
|
public float getHitFraction() {
|
||||||
return hitFraction;
|
return hitFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the normalInWorldSpace
|
* Test whether the normal is in world space.
|
||||||
|
*
|
||||||
|
* @return true if in world space, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isNormalInWorldSpace() {
|
public boolean isNormalInWorldSpace() {
|
||||||
return normalInWorldSpace;
|
return normalInWorldSpace;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -35,13 +35,26 @@ import com.jme3.math.Vector3f;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the results of a PhysicsSpace rayTest
|
* Contains the results of a PhysicsSpace rayTest
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsSweepTestResult {
|
public class PhysicsSweepTestResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* collision object that was hit
|
||||||
|
*/
|
||||||
private PhysicsCollisionObject collisionObject;
|
private PhysicsCollisionObject collisionObject;
|
||||||
|
/**
|
||||||
|
* normal vector at the point of contact
|
||||||
|
*/
|
||||||
private Vector3f hitNormalLocal;
|
private Vector3f hitNormalLocal;
|
||||||
|
/**
|
||||||
|
* fraction of the way between the transforms (from=0, to=1, ≥0, ≤1)
|
||||||
|
*/
|
||||||
private float hitFraction;
|
private float hitFraction;
|
||||||
|
/**
|
||||||
|
* true→need to transform normal into world space
|
||||||
|
*/
|
||||||
private boolean normalInWorldSpace;
|
private boolean normalInWorldSpace;
|
||||||
|
|
||||||
public PhysicsSweepTestResult() {
|
public PhysicsSweepTestResult() {
|
||||||
@ -55,33 +68,49 @@ public class PhysicsSweepTestResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the collisionObject
|
* Access the collision object that was hit.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public PhysicsCollisionObject getCollisionObject() {
|
public PhysicsCollisionObject getCollisionObject() {
|
||||||
return collisionObject;
|
return collisionObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the hitNormalLocal
|
* Access the normal vector at the point of contact.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getHitNormalLocal() {
|
public Vector3f getHitNormalLocal() {
|
||||||
return hitNormalLocal;
|
return hitNormalLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the hitFraction
|
* Read the hit fraction.
|
||||||
|
*
|
||||||
|
* @return fraction (from=0, to=1, ≥0, ≤1)
|
||||||
*/
|
*/
|
||||||
public float getHitFraction() {
|
public float getHitFraction() {
|
||||||
return hitFraction;
|
return hitFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the normalInWorldSpace
|
* Test whether the normal is in world space.
|
||||||
|
*
|
||||||
|
* @return true if in world space, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isNormalInWorldSpace() {
|
public boolean isNormalInWorldSpace() {
|
||||||
return normalInWorldSpace;
|
return normalInWorldSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in the fields of this result.
|
||||||
|
*
|
||||||
|
* @param collisionObject
|
||||||
|
* @param hitNormalLocal
|
||||||
|
* @param hitFraction
|
||||||
|
* @param normalInWorldSpace
|
||||||
|
*/
|
||||||
public void fill(PhysicsCollisionObject collisionObject, Vector3f hitNormalLocal, float hitFraction, boolean normalInWorldSpace) {
|
public void fill(PhysicsCollisionObject collisionObject, Vector3f hitNormalLocal, float hitFraction, boolean normalInWorldSpace) {
|
||||||
this.collisionObject = collisionObject;
|
this.collisionObject = collisionObject;
|
||||||
this.hitNormalLocal = hitNormalLocal;
|
this.hitNormalLocal = hitNormalLocal;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,35 +41,63 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic box collision shape
|
* A rectangular-solid collision shape based on Bullet's btBoxShape.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BoxCollisionShape extends CollisionShape {
|
public class BoxCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy of half-extents of the box on each local axis (not null, no negative
|
||||||
|
* component)
|
||||||
|
*/
|
||||||
private Vector3f halfExtents;
|
private Vector3f halfExtents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public BoxCollisionShape() {
|
public BoxCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a collision box from the given halfExtents
|
* Instantiate a box shape with the specified half extents.
|
||||||
* @param halfExtents the halfExtents of the CollisionBox
|
*
|
||||||
|
* @param halfExtents the desired half extents (not null, no negative
|
||||||
|
* component, alias created)
|
||||||
*/
|
*/
|
||||||
public BoxCollisionShape(Vector3f halfExtents) {
|
public BoxCollisionShape(Vector3f halfExtents) {
|
||||||
this.halfExtents = halfExtents;
|
this.halfExtents = halfExtents;
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the half extents.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance (not null, no negative component)
|
||||||
|
*/
|
||||||
public final Vector3f getHalfExtents() {
|
public final Vector3f getHalfExtents() {
|
||||||
return halfExtents;
|
return halfExtents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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(halfExtents, "halfExtents", new Vector3f(1, 1, 1));
|
capsule.write(halfExtents, "halfExtents", new Vector3f(1, 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -78,6 +106,9 @@ public class BoxCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
objectId = createShape(halfExtents);
|
objectId = createShape(halfExtents);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,20 +41,37 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic capsule collision shape
|
* A capsule collision shape based on Bullet's btCapsuleShapeX, btCapsuleShape,
|
||||||
|
* or btCapsuleShapeZ.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class CapsuleCollisionShape extends CollisionShape{
|
public class CapsuleCollisionShape extends CollisionShape{
|
||||||
protected float radius,height;
|
/**
|
||||||
protected int axis;
|
* copy of height of the cylindrical portion (≥0)
|
||||||
|
*/
|
||||||
|
private float height;
|
||||||
|
/**
|
||||||
|
* copy of radius (≥0)
|
||||||
|
*/
|
||||||
|
private float radius;
|
||||||
|
/**
|
||||||
|
* copy of main (height) axis (0→X, 1→Y, 2→Z)
|
||||||
|
*/
|
||||||
|
private int axis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public CapsuleCollisionShape() {
|
public CapsuleCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a new CapsuleCollisionShape with the given radius and height
|
* Instantiate a Y-axis capsule shape with the specified radius and height.
|
||||||
* @param radius the radius of the capsule
|
*
|
||||||
* @param height the height of the capsule
|
* @param radius the desired radius (≥0)
|
||||||
|
* @param height the desired height (of the cylindrical portion) (≥0)
|
||||||
*/
|
*/
|
||||||
public CapsuleCollisionShape(float radius, float height) {
|
public CapsuleCollisionShape(float radius, float height) {
|
||||||
this.radius=radius;
|
this.radius=radius;
|
||||||
@ -64,10 +81,11 @@ public class CapsuleCollisionShape extends CollisionShape{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a capsule shape around the given axis (0=X,1=Y,2=Z)
|
* Instantiate a capsule shape around the specified main (height) axis.
|
||||||
* @param radius
|
*
|
||||||
* @param height
|
* @param radius the desired radius (≥0)
|
||||||
* @param axis
|
* @param height the desired height (of the cylindrical portion) (≥0)
|
||||||
|
* @param axis which local axis: 0→X, 1→Y, 2→Z
|
||||||
*/
|
*/
|
||||||
public CapsuleCollisionShape(float radius, float height, int axis) {
|
public CapsuleCollisionShape(float radius, float height, int axis) {
|
||||||
this.radius=radius;
|
this.radius=radius;
|
||||||
@ -76,20 +94,39 @@ public class CapsuleCollisionShape extends CollisionShape{
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of the capsule.
|
||||||
|
*
|
||||||
|
* @return radius (≥0)
|
||||||
|
*/
|
||||||
public float getRadius() {
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the height (of the cylindrical portion) of the capsule.
|
||||||
|
*
|
||||||
|
* @return height (≥0)
|
||||||
|
*/
|
||||||
public float getHeight() {
|
public float getHeight() {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the main (height) axis of the capsule.
|
||||||
|
*
|
||||||
|
* @return 0 for local X, 1 for local Y, or 2 for local Z
|
||||||
|
*/
|
||||||
public int getAxis() {
|
public int getAxis() {
|
||||||
return axis;
|
return axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WARNING - CompoundCollisionShape scaling has no effect.
|
* Alter the scaling factors of this shape. Scaling is disabled
|
||||||
|
* for capsule shapes.
|
||||||
|
*
|
||||||
|
* @param scale the desired scaling factor for each local axis (not null, no
|
||||||
|
* negative component, unaffected, default=1,1,1)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setScale(Vector3f scale) {
|
public void setScale(Vector3f scale) {
|
||||||
@ -98,6 +135,12 @@ public class CapsuleCollisionShape extends CollisionShape{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -106,6 +149,12 @@ public class CapsuleCollisionShape extends CollisionShape{
|
|||||||
capsule.write(axis, "axis", 1);
|
capsule.write(axis, "axis", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -115,6 +164,9 @@ public class CapsuleCollisionShape extends CollisionShape{
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape(){
|
protected void createShape(){
|
||||||
objectId = createShape(axis, radius, height);
|
objectId = createShape(axis, radius, height);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -38,15 +38,32 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Object holds information about a jbullet CollisionShape to be able to reuse
|
* The abstract base class for collision shapes based on Bullet's
|
||||||
* CollisionShapes (as suggested in bullet manuals)
|
* btCollisionShape.
|
||||||
* TODO: add static methods to create shapes from nodes (like jbullet-jme constructor)
|
* <p>
|
||||||
|
* Collision shapes include BoxCollisionShape and CapsuleCollisionShape. As
|
||||||
|
* suggested in the Bullet manual, a single collision shape can be shared among
|
||||||
|
* multiple collision objects.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public abstract class CollisionShape implements Savable {
|
public abstract class CollisionShape implements Savable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unique identifier of the Bullet shape
|
||||||
|
* <p>
|
||||||
|
* Constructors are responsible for setting this to a non-zero value. After
|
||||||
|
* that, the id never changes.
|
||||||
|
*/
|
||||||
protected long objectId = 0;
|
protected long objectId = 0;
|
||||||
|
/**
|
||||||
|
* copy of scaling factors: one for each local axis (default=1,1,1)
|
||||||
|
*/
|
||||||
protected Vector3f scale = new Vector3f(1, 1, 1);
|
protected Vector3f scale = new Vector3f(1, 1, 1);
|
||||||
|
/**
|
||||||
|
* copy of collision margin (in physics-space units, >0,
|
||||||
|
* default=0)
|
||||||
|
*/
|
||||||
protected float margin = 0.0f;
|
protected float margin = 0.0f;
|
||||||
|
|
||||||
public CollisionShape() {
|
public CollisionShape() {
|
||||||
@ -70,7 +87,9 @@ public abstract class CollisionShape implements Savable {
|
|||||||
// private native void calculateLocalInertia(long objectId, long shapeId, float mass);
|
// private native void calculateLocalInertia(long objectId, long shapeId, float mass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used internally
|
* Read the id of the Bullet shape.
|
||||||
|
*
|
||||||
|
* @return the unique identifier (not zero)
|
||||||
*/
|
*/
|
||||||
public long getObjectId() {
|
public long getObjectId() {
|
||||||
return objectId;
|
return objectId;
|
||||||
@ -83,21 +102,52 @@ public abstract class CollisionShape implements Savable {
|
|||||||
this.objectId = id;
|
this.objectId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the scaling factors of this shape. CAUTION: Not all shapes can be
|
||||||
|
* scaled.
|
||||||
|
* <p>
|
||||||
|
* Note that if the shape is shared (between collision objects and/or
|
||||||
|
* compound shapes) changes can have unintended consequences.
|
||||||
|
*
|
||||||
|
* @param scale the desired scaling factor for each local axis (not null, no
|
||||||
|
* negative component, unaffected, default=1,1,1)
|
||||||
|
*/
|
||||||
public void setScale(Vector3f scale) {
|
public void setScale(Vector3f scale) {
|
||||||
this.scale.set(scale);
|
this.scale.set(scale);
|
||||||
setLocalScaling(objectId, scale);
|
setLocalScaling(objectId, scale);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Access the scaling factors.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getScale() {
|
public Vector3f getScale() {
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the collision margin for this shape.
|
||||||
|
*
|
||||||
|
* @return the margin distance (in physics-space units, >0)
|
||||||
|
*/
|
||||||
public float getMargin() {
|
public float getMargin() {
|
||||||
return getMargin(objectId);
|
return getMargin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMargin(long objectId);
|
private native float getMargin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the collision margin for this shape. CAUTION: Margin is applied
|
||||||
|
* differently, depending on the type of shape. Generally the collision
|
||||||
|
* margin expands the object, creating a gap. Don't set the collision margin
|
||||||
|
* to zero.
|
||||||
|
* <p>
|
||||||
|
* Note that if the shape is shared (between collision objects and/or
|
||||||
|
* compound shapes) changes can have unintended consequences.
|
||||||
|
*
|
||||||
|
* @param margin the desired margin distance (in physics-space units, >0,
|
||||||
|
* default=0)
|
||||||
|
*/
|
||||||
public void setMargin(float margin) {
|
public void setMargin(float margin) {
|
||||||
setMargin(objectId, margin);
|
setMargin(objectId, margin);
|
||||||
this.margin = margin;
|
this.margin = margin;
|
||||||
@ -107,18 +157,37 @@ public abstract class CollisionShape implements Savable {
|
|||||||
|
|
||||||
private native void setMargin(long objectId, float margin);
|
private native void setMargin(long objectId, float margin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule capsule = ex.getCapsule(this);
|
OutputCapsule capsule = ex.getCapsule(this);
|
||||||
capsule.write(scale, "scale", new Vector3f(1, 1, 1));
|
capsule.write(scale, "scale", new Vector3f(1, 1, 1));
|
||||||
capsule.write(getMargin(), "margin", 0.0f);
|
capsule.write(getMargin(), "margin", 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
this.scale = (Vector3f) capsule.readSavable("scale", new Vector3f(1, 1, 1));
|
this.scale = (Vector3f) capsule.readSavable("scale", new Vector3f(1, 1, 1));
|
||||||
this.margin = capsule.readFloat("margin", 0.0f);
|
this.margin = capsule.readFloat("margin", 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this shape just before it is destroyed. Should be invoked only
|
||||||
|
* by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -46,23 +46,33 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CompoundCollisionShape allows combining multiple base shapes
|
* A collision shape formed by combining convex child shapes, based on Bullet's
|
||||||
* to generate a more sophisticated shape.
|
* btCompoundShape.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class CompoundCollisionShape extends CollisionShape {
|
public class CompoundCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* children of this shape
|
||||||
|
*/
|
||||||
protected ArrayList<ChildCollisionShape> children = new ArrayList<ChildCollisionShape>();
|
protected ArrayList<ChildCollisionShape> children = new ArrayList<ChildCollisionShape>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an empty compound shape (with no children).
|
||||||
|
*/
|
||||||
public CompoundCollisionShape() {
|
public CompoundCollisionShape() {
|
||||||
objectId = createShape();//new CompoundShape();
|
objectId = createShape();//new CompoundShape();
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds a child shape at the given local translation
|
* Add a child shape with the specified local translation.
|
||||||
* @param shape the child shape to add
|
*
|
||||||
* @param location the local location of the child shape
|
* @param shape the child shape to add (not null, not a compound shape,
|
||||||
|
* alias created)
|
||||||
|
* @param location the local coordinates of the child shape's center (not
|
||||||
|
* null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void addChildShape(CollisionShape shape, Vector3f location) {
|
public void addChildShape(CollisionShape shape, Vector3f location) {
|
||||||
// Transform transA = new Transform(Converter.convert(new Matrix3f()));
|
// Transform transA = new Transform(Converter.convert(new Matrix3f()));
|
||||||
@ -73,9 +83,14 @@ public class CompoundCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds a child shape at the given local translation
|
* Add a child shape with the specified local translation and orientation.
|
||||||
* @param shape the child shape to add
|
*
|
||||||
* @param location the local location of the child shape
|
* @param shape the child shape to add (not null, not a compound shape,
|
||||||
|
* alias created)
|
||||||
|
* @param location the local coordinates of the child shape's center (not
|
||||||
|
* null, unaffected)
|
||||||
|
* @param rotation the local orientation of the child shape (not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
public void addChildShape(CollisionShape shape, Vector3f location, Matrix3f rotation) {
|
public void addChildShape(CollisionShape shape, Vector3f location, Matrix3f rotation) {
|
||||||
if(shape instanceof CompoundCollisionShape){
|
if(shape instanceof CompoundCollisionShape){
|
||||||
@ -101,8 +116,9 @@ public class CompoundCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes a child shape
|
* Remove a child from this shape.
|
||||||
* @param shape the child shape to remove
|
*
|
||||||
|
* @param shape the child shape to remove (not null)
|
||||||
*/
|
*/
|
||||||
public void removeChildShape(CollisionShape shape) {
|
public void removeChildShape(CollisionShape shape) {
|
||||||
removeChildShape(objectId, shape.getObjectId());
|
removeChildShape(objectId, shape.getObjectId());
|
||||||
@ -115,6 +131,11 @@ public class CompoundCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the list of children.
|
||||||
|
*
|
||||||
|
* @return the pre-existing list (not null)
|
||||||
|
*/
|
||||||
public List<ChildCollisionShape> getChildren() {
|
public List<ChildCollisionShape> getChildren() {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
@ -125,12 +146,24 @@ public class CompoundCollisionShape extends CollisionShape {
|
|||||||
|
|
||||||
private native long removeChildShape(long objectId, long childId);
|
private native long removeChildShape(long objectId, long childId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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.writeSavableArrayList(children, "children", new ArrayList<ChildCollisionShape>());
|
capsule.writeSavableArrayList(children, "children", new ArrayList<ChildCollisionShape>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,18 +41,40 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A conical collision shape based on Bullet's btConeShapeX, btConeShape, or
|
||||||
|
* btConeShapeZ.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class ConeCollisionShape extends CollisionShape {
|
public class ConeCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy of radius (≥0)
|
||||||
|
*/
|
||||||
protected float radius;
|
protected float radius;
|
||||||
|
/**
|
||||||
|
* copy of height (≥0)
|
||||||
|
*/
|
||||||
protected float height;
|
protected float height;
|
||||||
|
/**
|
||||||
|
* copy of main (height) axis (0→X, 1→Y, 2→Z)
|
||||||
|
*/
|
||||||
protected int axis;
|
protected int axis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public ConeCollisionShape() {
|
public ConeCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a cone shape around the specified main (height) axis.
|
||||||
|
*
|
||||||
|
* @param radius the desired radius (≥0)
|
||||||
|
* @param height the desired height (≥0)
|
||||||
|
* @param axis which local axis: 0→X, 1→Y, 2→Z
|
||||||
|
*/
|
||||||
public ConeCollisionShape(float radius, float height, int axis) {
|
public ConeCollisionShape(float radius, float height, int axis) {
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@ -60,6 +82,12 @@ public class ConeCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a cone shape oriented along the Y axis.
|
||||||
|
*
|
||||||
|
* @param radius the desired radius (≥0)
|
||||||
|
* @param height the desired height (≥0)
|
||||||
|
*/
|
||||||
public ConeCollisionShape(float radius, float height) {
|
public ConeCollisionShape(float radius, float height) {
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@ -67,14 +95,30 @@ public class ConeCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of the cone.
|
||||||
|
*
|
||||||
|
* @return radius (≥0)
|
||||||
|
*/
|
||||||
public float getRadius() {
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the height of the cone.
|
||||||
|
*
|
||||||
|
* @return height (≥0)
|
||||||
|
*/
|
||||||
public float getHeight() {
|
public float getHeight() {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -83,6 +127,12 @@ public class ConeCollisionShape extends CollisionShape {
|
|||||||
capsule.write(axis, "axis", PhysicsSpace.AXIS_Y);
|
capsule.write(axis, "axis", PhysicsSpace.AXIS_Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -92,6 +142,9 @@ public class ConeCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
objectId = createShape(axis, radius, height);
|
objectId = createShape(axis, radius, height);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,20 +41,35 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic cylinder collision shape
|
* A cylindrical collision shape based on Bullet's btCylinderShapeX, new
|
||||||
|
* btCylinderShape, or btCylinderShapeZ.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class CylinderCollisionShape extends CollisionShape {
|
public class CylinderCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy of half-extents of the cylinder on each local axis (not null, no
|
||||||
|
* negative component)
|
||||||
|
*/
|
||||||
protected Vector3f halfExtents;
|
protected Vector3f halfExtents;
|
||||||
|
/**
|
||||||
|
* main (height) axis (0→X, 1→Y, 2→Z)
|
||||||
|
*/
|
||||||
protected int axis;
|
protected int axis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public CylinderCollisionShape() {
|
public CylinderCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a cylinder shape from the given halfextents
|
* Instantiate a Z-axis cylinder shape with the specified half extents.
|
||||||
* @param halfExtents the halfextents to use
|
*
|
||||||
|
* @param halfExtents the desired half extents (not null, no negative
|
||||||
|
* component, alias created)
|
||||||
*/
|
*/
|
||||||
public CylinderCollisionShape(Vector3f halfExtents) {
|
public CylinderCollisionShape(Vector3f halfExtents) {
|
||||||
this.halfExtents = halfExtents;
|
this.halfExtents = halfExtents;
|
||||||
@ -63,9 +78,11 @@ public class CylinderCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a cylinder shape around the given axis from the given halfextents
|
* Instantiate a cylinder shape around the specified axis.
|
||||||
* @param halfExtents the halfextents to use
|
*
|
||||||
* @param axis (0=X,1=Y,2=Z)
|
* @param halfExtents the desired half extents (not null, no negative
|
||||||
|
* component, alias created)
|
||||||
|
* @param axis which local axis: 0→X, 1→Y, 2→Z
|
||||||
*/
|
*/
|
||||||
public CylinderCollisionShape(Vector3f halfExtents, int axis) {
|
public CylinderCollisionShape(Vector3f halfExtents, int axis) {
|
||||||
this.halfExtents = halfExtents;
|
this.halfExtents = halfExtents;
|
||||||
@ -73,16 +90,30 @@ public class CylinderCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the half extents of the cylinder.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector (not null, no negative component)
|
||||||
|
*/
|
||||||
public final Vector3f getHalfExtents() {
|
public final Vector3f getHalfExtents() {
|
||||||
return halfExtents;
|
return halfExtents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the main axis of the cylinder.
|
||||||
|
*
|
||||||
|
* @return 0→X, 1→Y, 2→Z
|
||||||
|
*/
|
||||||
public int getAxis() {
|
public int getAxis() {
|
||||||
return axis;
|
return axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WARNING - CompoundCollisionShape scaling has no effect.
|
* Alter the scaling factors of this shape. Scaling is disabled
|
||||||
|
* for cylinder shapes.
|
||||||
|
*
|
||||||
|
* @param scale the desired scaling factor for each local axis (not null, no
|
||||||
|
* negative component, unaffected, default=1,1,1)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setScale(Vector3f scale) {
|
public void setScale(Vector3f scale) {
|
||||||
@ -91,6 +122,12 @@ public class CylinderCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -98,6 +135,12 @@ public class CylinderCollisionShape extends CollisionShape {
|
|||||||
capsule.write(axis, "axis", 1);
|
capsule.write(axis, "axis", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -106,6 +149,9 @@ public class CylinderCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
objectId = createShape(axis, halfExtents);
|
objectId = createShape(axis, halfExtents);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -47,7 +47,8 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic mesh collision shape
|
* A mesh collision shape based on Bullet's btGImpactMeshShape.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class GImpactCollisionShape extends CollisionShape {
|
public class GImpactCollisionShape extends CollisionShape {
|
||||||
@ -55,14 +56,23 @@ public class GImpactCollisionShape extends CollisionShape {
|
|||||||
// protected Vector3f worldScale;
|
// protected Vector3f worldScale;
|
||||||
protected int numVertices, numTriangles, vertexStride, triangleIndexStride;
|
protected int numVertices, numTriangles, vertexStride, triangleIndexStride;
|
||||||
protected ByteBuffer triangleIndexBase, vertexBase;
|
protected ByteBuffer triangleIndexBase, vertexBase;
|
||||||
|
/**
|
||||||
|
* Unique identifier of the Bullet mesh. The constructor sets this to a
|
||||||
|
* non-zero value.
|
||||||
|
*/
|
||||||
protected long meshId = 0;
|
protected long meshId = 0;
|
||||||
// protected IndexedMesh bulletMesh;
|
// protected IndexedMesh bulletMesh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public GImpactCollisionShape() {
|
public GImpactCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a collision shape from the given Mesh
|
* Instantiate a shape based on the specified JME mesh.
|
||||||
|
*
|
||||||
* @param mesh the Mesh to use
|
* @param mesh the Mesh to use
|
||||||
*/
|
*/
|
||||||
public GImpactCollisionShape(Mesh mesh) {
|
public GImpactCollisionShape(Mesh mesh) {
|
||||||
@ -105,6 +115,12 @@ public class GImpactCollisionShape extends CollisionShape {
|
|||||||
// public Mesh createJmeMesh() {
|
// public Mesh createJmeMesh() {
|
||||||
// return Converter.convert(bulletMesh);
|
// return Converter.convert(bulletMesh);
|
||||||
// }
|
// }
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -118,6 +134,12 @@ public class GImpactCollisionShape extends CollisionShape {
|
|||||||
capsule.write(vertexBase.array(), "vertexBase", new byte[0]);
|
capsule.write(vertexBase.array(), "vertexBase", new byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -132,6 +154,9 @@ public class GImpactCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
// bulletMesh = new IndexedMesh();
|
// bulletMesh = new IndexedMesh();
|
||||||
// bulletMesh.numVertices = numVertices;
|
// bulletMesh.numVertices = numVertices;
|
||||||
@ -157,6 +182,12 @@ public class GImpactCollisionShape extends CollisionShape {
|
|||||||
|
|
||||||
private native long createShape(long meshId);
|
private native long createShape(long meshId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this shape just before it is destroyed. Should be invoked only
|
||||||
|
* by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -45,36 +45,72 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses Bullet Physics Heightfield terrain collision system. This is MUCH faster
|
* A terrain collision shape based on Bullet's btHeightfieldTerrainShape.
|
||||||
* than using a regular mesh.
|
* <p>
|
||||||
* There are a couple tricks though:
|
* This is much more efficient than a regular mesh, but it has a couple
|
||||||
* -No rotation or translation is supported.
|
* limitations:
|
||||||
* -The collision bbox must be centered around 0,0,0 with the height above and below the y-axis being
|
* <ul>
|
||||||
* equal on either side. If not, the whole collision box is shifted vertically and things don't collide
|
* <li>No rotation or translation.</li>
|
||||||
* as they should.
|
* <li>The collision bounding box must be centered on (0,0,0) with the height
|
||||||
*
|
* above and below the X-Z plane being equal on either side. If not, the whole
|
||||||
|
* collision box is shifted vertically and objects won't collide properly.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* @author Brent Owens
|
* @author Brent Owens
|
||||||
*/
|
*/
|
||||||
public class HeightfieldCollisionShape extends CollisionShape {
|
public class HeightfieldCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of rows in the heightfield (>1)
|
||||||
|
*/
|
||||||
protected int heightStickWidth;
|
protected int heightStickWidth;
|
||||||
|
/**
|
||||||
|
* number of columns in the heightfield (>1)
|
||||||
|
*/
|
||||||
protected int heightStickLength;
|
protected int heightStickLength;
|
||||||
|
/**
|
||||||
|
* array of heightfield samples
|
||||||
|
*/
|
||||||
protected float[] heightfieldData;
|
protected float[] heightfieldData;
|
||||||
protected float heightScale;
|
protected float heightScale;
|
||||||
protected float minHeight;
|
protected float minHeight;
|
||||||
protected float maxHeight;
|
protected float maxHeight;
|
||||||
|
/**
|
||||||
|
* index of the height axis (0→X, 1→Y, 2→Z)
|
||||||
|
*/
|
||||||
protected int upAxis;
|
protected int upAxis;
|
||||||
protected boolean flipQuadEdges;
|
protected boolean flipQuadEdges;
|
||||||
|
/**
|
||||||
|
* buffer for passing height data to Bullet
|
||||||
|
* <p>
|
||||||
|
* A Java reference must persist after createShape() completes, or else the
|
||||||
|
* buffer might get garbaged collected.
|
||||||
|
*/
|
||||||
protected ByteBuffer bbuf;
|
protected ByteBuffer bbuf;
|
||||||
// protected FloatBuffer fbuf;
|
// protected FloatBuffer fbuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public HeightfieldCollisionShape() {
|
public HeightfieldCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a new shape for the specified height map.
|
||||||
|
*
|
||||||
|
* @param heightmap (not null, length≥4, length a perfect square)
|
||||||
|
*/
|
||||||
public HeightfieldCollisionShape(float[] heightmap) {
|
public HeightfieldCollisionShape(float[] heightmap) {
|
||||||
createCollisionHeightfield(heightmap, Vector3f.UNIT_XYZ);
|
createCollisionHeightfield(heightmap, Vector3f.UNIT_XYZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a new shape for the specified height map and scale vector.
|
||||||
|
*
|
||||||
|
* @param heightmap (not null, length≥4, length a perfect square)
|
||||||
|
* @param scale (not null, no negative component, unaffected, default=1,1,1)
|
||||||
|
*/
|
||||||
public HeightfieldCollisionShape(float[] heightmap, Vector3f scale) {
|
public HeightfieldCollisionShape(float[] heightmap, Vector3f scale) {
|
||||||
createCollisionHeightfield(heightmap, scale);
|
createCollisionHeightfield(heightmap, scale);
|
||||||
}
|
}
|
||||||
@ -120,6 +156,9 @@ public class HeightfieldCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
bbuf = BufferUtils.createByteBuffer(heightfieldData.length * 4);
|
bbuf = BufferUtils.createByteBuffer(heightfieldData.length * 4);
|
||||||
// fbuf = bbuf.asFloatBuffer();//FloatBuffer.wrap(heightfieldData);
|
// fbuf = bbuf.asFloatBuffer();//FloatBuffer.wrap(heightfieldData);
|
||||||
@ -138,11 +177,22 @@ public class HeightfieldCollisionShape extends CollisionShape {
|
|||||||
|
|
||||||
private native long createShape(int heightStickWidth, int heightStickLength, ByteBuffer heightfieldData, float heightScale, float minHeight, float maxHeight, int upAxis, boolean flipQuadEdges);
|
private native long createShape(int heightStickWidth, int heightStickLength, ByteBuffer heightfieldData, float heightScale, float minHeight, float maxHeight, int upAxis, boolean flipQuadEdges);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does nothing.
|
||||||
|
*
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
public Mesh createJmeMesh() {
|
public Mesh createJmeMesh() {
|
||||||
//TODO return Converter.convert(bulletMesh);
|
//TODO return Converter.convert(bulletMesh);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -156,6 +206,12 @@ public class HeightfieldCollisionShape extends CollisionShape {
|
|||||||
capsule.write(flipQuadEdges, "flipQuadEdges", false);
|
capsule.write(flipQuadEdges, "flipQuadEdges", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -44,24 +44,50 @@ import java.nio.FloatBuffer;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convex hull collision shape based on Bullet's btConvexHullShape.
|
||||||
|
*/
|
||||||
public class HullCollisionShape extends CollisionShape {
|
public class HullCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
private float[] points;
|
private float[] points;
|
||||||
// protected FloatBuffer fbuf;
|
// protected FloatBuffer fbuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public HullCollisionShape() {
|
public HullCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a collision shape based on the specified JME mesh. For best
|
||||||
|
* performance and stability, use the mesh should have no more than 100
|
||||||
|
* vertices.
|
||||||
|
*
|
||||||
|
* @param mesh a mesh on which to base the shape (not null)
|
||||||
|
*/
|
||||||
public HullCollisionShape(Mesh mesh) {
|
public HullCollisionShape(Mesh mesh) {
|
||||||
this.points = getPoints(mesh);
|
this.points = getPoints(mesh);
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a collision shape based on the specified JME mesh.
|
||||||
|
*
|
||||||
|
* @param points an array of coordinates on which to base the shape (not
|
||||||
|
* null, length a multiple of 3)
|
||||||
|
*/
|
||||||
public HullCollisionShape(float[] points) {
|
public HullCollisionShape(float[] points) {
|
||||||
this.points = points;
|
this.points = points;
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -70,6 +96,12 @@ public class HullCollisionShape extends CollisionShape {
|
|||||||
capsule.write(points, "points", null);
|
capsule.write(points, "points", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
@ -89,6 +121,9 @@ public class HullCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
// 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) {
|
||||||
@ -114,6 +149,12 @@ public class HullCollisionShape extends CollisionShape {
|
|||||||
|
|
||||||
private native long createShape(ByteBuffer points);
|
private native long createShape(ByteBuffer points);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the vertex positions from a JME mesh.
|
||||||
|
*
|
||||||
|
* @param mesh the mesh to read (not null)
|
||||||
|
* @return a new array (not null, length a multiple of 3)
|
||||||
|
*/
|
||||||
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();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -49,7 +49,7 @@ import com.jme3.scene.mesh.IndexBuffer;
|
|||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic mesh collision shape
|
* A mesh collision shape based on Bullet's btBvhTriangleMeshShape.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
@ -64,38 +64,45 @@ public class MeshCollisionShape extends CollisionShape {
|
|||||||
private static final String NATIVE_BVH = "nativeBvh";
|
private static final String NATIVE_BVH = "nativeBvh";
|
||||||
protected int numVertices, numTriangles, vertexStride, triangleIndexStride;
|
protected int numVertices, numTriangles, vertexStride, triangleIndexStride;
|
||||||
protected ByteBuffer triangleIndexBase, vertexBase;
|
protected ByteBuffer triangleIndexBase, vertexBase;
|
||||||
|
/**
|
||||||
|
* Unique identifier of the Bullet mesh. The constructor sets this to a
|
||||||
|
* non-zero value.
|
||||||
|
*/
|
||||||
protected long meshId = 0;
|
protected long meshId = 0;
|
||||||
protected long nativeBVHBuffer = 0;
|
protected long nativeBVHBuffer = 0;
|
||||||
private boolean memoryOptimized;
|
private boolean memoryOptimized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public MeshCollisionShape() {
|
public MeshCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a collision shape from the given Mesh.
|
* Instantiate a collision shape based on the specified JME mesh, optimized
|
||||||
* Default behavior, more optimized for memory usage.
|
* for memory usage.
|
||||||
*
|
*
|
||||||
* @param mesh
|
* @param mesh the mesh on which to base the shape (not null)
|
||||||
*/
|
*/
|
||||||
public MeshCollisionShape(Mesh mesh) {
|
public MeshCollisionShape(Mesh mesh) {
|
||||||
this(mesh, true);
|
this(mesh, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a collision shape from the given Mesh.
|
* Instantiate a collision shape based on the specified JME mesh.
|
||||||
* <code>memoryOptimized</code> determines if optimized instead of
|
* <p>
|
||||||
* quantized BVH will be used.
|
* <code>memoryOptimized</code> determines if optimized instead of quantized
|
||||||
* Internally, <code>memoryOptimized</code> BVH is slower to calculate (~4x)
|
* BVH will be used. Internally, <code>memoryOptimized</code> BVH is slower
|
||||||
* but also smaller (~0.5x).
|
* to calculate (~4x) but also smaller (~0.5x). It is preferable to use the
|
||||||
* It is preferable to use the memory optimized version and then serialize
|
* memory optimized version and then serialize the resulting
|
||||||
* the resulting MeshCollisionshape as this will also save the
|
* MeshCollisionshape as this will also save the generated BVH. An exception
|
||||||
* generated BVH.
|
* can be procedurally / generated collision shapes, where the generation
|
||||||
* An exception can be procedurally / generated collision shapes, where
|
* time is more of a concern
|
||||||
* the generation time is more of a concern
|
|
||||||
*
|
*
|
||||||
* @param mesh the Mesh to use
|
* @param mesh the mesh on which to base the shape (not null)
|
||||||
* @param memoryOptimized True to generate a memory optimized BVH,
|
* @param memoryOptimized true to generate a memory-optimized BVH, false to
|
||||||
* false to generate quantized BVH.
|
* generate quantized BVH
|
||||||
*/
|
*/
|
||||||
public MeshCollisionShape(final Mesh mesh, final boolean memoryOptimized) {
|
public MeshCollisionShape(final Mesh mesh, final boolean memoryOptimized) {
|
||||||
this.memoryOptimized = memoryOptimized;
|
this.memoryOptimized = memoryOptimized;
|
||||||
@ -103,16 +110,15 @@ public class MeshCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advanced constructor, usually you don’t want to use this, but the Mesh
|
* An advanced constructor. Passing false values can lead to a crash.
|
||||||
* based one. Passing false values can lead to a crash, use at own risk
|
* Usually you don’t want to use this. Use at own risk.
|
||||||
*
|
* <p>
|
||||||
* This constructor bypasses all copy logic normally used, this allows for
|
* This constructor bypasses all copy logic normally used, this allows for
|
||||||
* faster bullet shape generation when using procedurally generated Meshes.
|
* faster Bullet shape generation when using procedurally generated Meshes.
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* @param indices the raw index buffer
|
* @param indices the raw index buffer
|
||||||
* @param vertices the raw vertex buffer
|
* @param vertices the raw vertex buffer
|
||||||
* @param memoryOptimized use quantisize BVH, uses less memory, but slower
|
* @param memoryOptimized use quantized BVH, uses less memory, but slower
|
||||||
*/
|
*/
|
||||||
public MeshCollisionShape(ByteBuffer indices, ByteBuffer vertices, boolean memoryOptimized) {
|
public MeshCollisionShape(ByteBuffer indices, ByteBuffer vertices, boolean memoryOptimized) {
|
||||||
this.triangleIndexBase = indices;
|
this.triangleIndexBase = indices;
|
||||||
@ -153,6 +159,12 @@ public class MeshCollisionShape extends CollisionShape {
|
|||||||
this.createShape(null);
|
this.createShape(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(final JmeExporter ex) throws IOException {
|
public void write(final JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -178,6 +190,12 @@ public class MeshCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(final JmeImporter im) throws IOException {
|
public void read(final JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
@ -195,6 +213,9 @@ public class MeshCollisionShape extends CollisionShape {
|
|||||||
createShape(nativeBvh);
|
createShape(nativeBvh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
private void createShape(byte bvh[]) {
|
private void createShape(byte bvh[]) {
|
||||||
boolean buildBvh=bvh==null||bvh.length==0;
|
boolean buildBvh=bvh==null||bvh.length==0;
|
||||||
this.meshId = NativeMeshUtil.createTriangleIndexVertexArray(this.triangleIndexBase, this.vertexBase, this.numTriangles, this.numVertices, this.vertexStride, this.triangleIndexStride);
|
this.meshId = NativeMeshUtil.createTriangleIndexVertexArray(this.triangleIndexBase, this.vertexBase, this.numTriangles, this.numVertices, this.vertexStride, this.triangleIndexStride);
|
||||||
@ -216,6 +237,12 @@ public class MeshCollisionShape extends CollisionShape {
|
|||||||
|
|
||||||
private native long createShape(boolean memoryOptimized, boolean buildBvt, long meshId);
|
private native long createShape(boolean memoryOptimized, boolean buildBvt, long meshId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this shape just before it is destroyed. Should be invoked only
|
||||||
|
* by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void finalize() throws Throwable {
|
public void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,34 +42,60 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A planar collision shape based on Bullet's btStaticPlaneShape.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PlaneCollisionShape extends CollisionShape{
|
public class PlaneCollisionShape extends CollisionShape{
|
||||||
|
/**
|
||||||
|
* description of the plane
|
||||||
|
*/
|
||||||
private Plane plane;
|
private Plane plane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public PlaneCollisionShape() {
|
public PlaneCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a plane Collision shape
|
* Instantiate a plane shape defined by the specified plane.
|
||||||
* @param plane the plane that defines the shape
|
*
|
||||||
|
* @param plane the desired plane (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public PlaneCollisionShape(Plane plane) {
|
public PlaneCollisionShape(Plane plane) {
|
||||||
this.plane = plane;
|
this.plane = plane;
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the defining plane.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance (not null)
|
||||||
|
*/
|
||||||
public final Plane getPlane() {
|
public final Plane getPlane() {
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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(plane, "collisionPlane", new Plane());
|
capsule.write(plane, "collisionPlane", new Plane());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -77,6 +103,9 @@ public class PlaneCollisionShape extends CollisionShape{
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
objectId = createShape(plane.getNormal(), plane.getConstant());
|
objectId = createShape(plane.getNormal(), plane.getConstant());
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,16 +41,33 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple point, line, triangle or quad collisionShape based on one to four points-
|
* A simple point, line-segment, triangle, or tetrahedron collision shape based
|
||||||
|
* on Bullet's btBU_Simplex1to4.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class SimplexCollisionShape extends CollisionShape {
|
public class SimplexCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vertex positions
|
||||||
|
*/
|
||||||
private Vector3f vector1, vector2, vector3, vector4;
|
private Vector3f vector1, vector2, vector3, vector4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public SimplexCollisionShape() {
|
public SimplexCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a tetrahedral collision shape based on the specified points.
|
||||||
|
*
|
||||||
|
* @param point1 the coordinates of 1st point (not null, alias created)
|
||||||
|
* @param point2 the coordinates of 2nd point (not null, alias created)
|
||||||
|
* @param point3 the coordinates of 3rd point (not null, alias created)
|
||||||
|
* @param point4 the coordinates of 4th point (not null, alias created)
|
||||||
|
*/
|
||||||
public SimplexCollisionShape(Vector3f point1, Vector3f point2, Vector3f point3, Vector3f point4) {
|
public SimplexCollisionShape(Vector3f point1, Vector3f point2, Vector3f point3, Vector3f point4) {
|
||||||
vector1 = point1;
|
vector1 = point1;
|
||||||
vector2 = point2;
|
vector2 = point2;
|
||||||
@ -59,6 +76,13 @@ public class SimplexCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a triangular collision shape based on the specified points.
|
||||||
|
*
|
||||||
|
* @param point1 the coordinates of 1st point (not null, alias created)
|
||||||
|
* @param point2 the coordinates of 2nd point (not null, alias created)
|
||||||
|
* @param point3 the coordinates of 3rd point (not null, alias created)
|
||||||
|
*/
|
||||||
public SimplexCollisionShape(Vector3f point1, Vector3f point2, Vector3f point3) {
|
public SimplexCollisionShape(Vector3f point1, Vector3f point2, Vector3f point3) {
|
||||||
vector1 = point1;
|
vector1 = point1;
|
||||||
vector2 = point2;
|
vector2 = point2;
|
||||||
@ -66,17 +90,34 @@ public class SimplexCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a line-segment collision shape based on the specified points.
|
||||||
|
*
|
||||||
|
* @param point1 the coordinates of 1st point (not null, alias created)
|
||||||
|
* @param point2 the coordinates of 2nd point (not null, alias created)
|
||||||
|
*/
|
||||||
public SimplexCollisionShape(Vector3f point1, Vector3f point2) {
|
public SimplexCollisionShape(Vector3f point1, Vector3f point2) {
|
||||||
vector1 = point1;
|
vector1 = point1;
|
||||||
vector2 = point2;
|
vector2 = point2;
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a point collision shape based on the specified points.
|
||||||
|
*
|
||||||
|
* @param point1 the coordinates of point (not null, alias created)
|
||||||
|
*/
|
||||||
public SimplexCollisionShape(Vector3f point1) {
|
public SimplexCollisionShape(Vector3f point1) {
|
||||||
vector1 = point1;
|
vector1 = point1;
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -86,6 +127,12 @@ public class SimplexCollisionShape extends CollisionShape {
|
|||||||
capsule.write(vector4, "simplexPoint4", null);
|
capsule.write(vector4, "simplexPoint4", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -96,6 +143,9 @@ public class SimplexCollisionShape extends CollisionShape {
|
|||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
if (vector4 != null) {
|
if (vector4 != null) {
|
||||||
objectId = createShape(vector1, vector2, vector3, vector4);
|
objectId = createShape(vector1, vector2, vector3, vector4);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,35 +41,61 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic sphere collision shape
|
* A spherical collision shape based on Bullet's btSphereShape.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class SphereCollisionShape extends CollisionShape {
|
public class SphereCollisionShape extends CollisionShape {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy of radius (≥0)
|
||||||
|
*/
|
||||||
protected float radius;
|
protected float radius;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public SphereCollisionShape() {
|
public SphereCollisionShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a SphereCollisionShape with the given radius
|
* Instantiate a sphere shape with the specified radius.
|
||||||
* @param radius
|
*
|
||||||
|
* @param radius the desired radius (≥0)
|
||||||
*/
|
*/
|
||||||
public SphereCollisionShape(float radius) {
|
public SphereCollisionShape(float radius) {
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
createShape();
|
createShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of this shape.
|
||||||
|
*
|
||||||
|
* @return the radius (≥0)
|
||||||
|
*/
|
||||||
public float getRadius() {
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this shape, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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(radius, "radius", 0.5f);
|
capsule.write(radius, "radius", 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this shape, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -78,7 +104,11 @@ public class SphereCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WARNING - CompoundCollisionShape scaling has no effect.
|
* Alter the scaling factors of this shape. Scaling is disabled
|
||||||
|
* for sphere shapes.
|
||||||
|
*
|
||||||
|
* @param scale the desired scaling factor for each local axis (not null, no
|
||||||
|
* negative component, unaffected, default=1,1,1)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setScale(Vector3f scale) {
|
public void setScale(Vector3f scale) {
|
||||||
@ -87,6 +117,9 @@ public class SphereCollisionShape extends CollisionShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured shape in Bullet.
|
||||||
|
*/
|
||||||
protected void createShape() {
|
protected void createShape() {
|
||||||
objectId = createShape(radius);
|
objectId = createShape(radius);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Shape {0}", Long.toHexString(objectId));
|
||||||
|
@ -43,10 +43,13 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>From bullet manual:</i><br>
|
* A joint based on Bullet's btConeTwistConstraint.
|
||||||
* To create ragdolls, the cone twist constraint is very useful for limbs like the upper arm.
|
* <p>
|
||||||
* It is a special point to point constraint that adds cone and twist axis limits.
|
* <i>From the Bullet manual:</i><br>
|
||||||
* The x-axis serves as twist axis.
|
* To create ragdolls, the cone twist constraint is very useful for limbs like
|
||||||
|
* the upper arm. It is a special point to point constraint that adds cone and
|
||||||
|
* twist axis limits. The x-axis serves as twist axis.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class ConeJoint extends PhysicsJoint {
|
public class ConeJoint extends PhysicsJoint {
|
||||||
@ -57,12 +60,25 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
protected float twistSpan = 1e30f;
|
protected float twistSpan = 1e30f;
|
||||||
protected boolean angularOnly = false;
|
protected boolean angularOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public ConeJoint() {
|
public ConeJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a ConeJoint. To be effective, the joint must be added to a
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
*/
|
*/
|
||||||
public ConeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
|
public ConeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -72,8 +88,21 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Instantiate a ConeJoint. To be effective, the joint must be added to a
|
||||||
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* @param pivotA local translation of the joint connection point in node A
|
||||||
|
* (not null, alias created)
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* @param pivotB local translation of the joint connection point in node B
|
||||||
|
* (not null, alias created)
|
||||||
|
* @param rotA the local orientation of the connection to node A (not null,
|
||||||
|
* alias created)
|
||||||
|
* @param rotB the local orientation of the connection to node B (not null,
|
||||||
|
* alias created)
|
||||||
*/
|
*/
|
||||||
public ConeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB) {
|
public ConeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -82,6 +111,13 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
createJoint();
|
createJoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the angular limits for this joint.
|
||||||
|
*
|
||||||
|
* @param swingSpan1 angle (in radians)
|
||||||
|
* @param swingSpan2 angle (in radians)
|
||||||
|
* @param twistSpan angle (in radians)
|
||||||
|
*/
|
||||||
public void setLimit(float swingSpan1, float swingSpan2, float twistSpan) {
|
public void setLimit(float swingSpan1, float swingSpan2, float twistSpan) {
|
||||||
this.swingSpan1 = swingSpan1;
|
this.swingSpan1 = swingSpan1;
|
||||||
this.swingSpan2 = swingSpan2;
|
this.swingSpan2 = swingSpan2;
|
||||||
@ -91,6 +127,11 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setLimit(long objectId, float swingSpan1, float swingSpan2, float twistSpan);
|
private native void setLimit(long objectId, float swingSpan1, float swingSpan2, float twistSpan);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether this joint is angular only.
|
||||||
|
*
|
||||||
|
* @param value the desired setting (default=false)
|
||||||
|
*/
|
||||||
public void setAngularOnly(boolean value) {
|
public void setAngularOnly(boolean value) {
|
||||||
angularOnly = value;
|
angularOnly = value;
|
||||||
setAngularOnly(objectId, value);
|
setAngularOnly(objectId, value);
|
||||||
@ -98,6 +139,12 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setAngularOnly(long objectId, boolean value);
|
private native void setAngularOnly(long objectId, boolean value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this joint, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -111,6 +158,12 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
capsule.write(twistSpan, "twistSpan", 1e30f);
|
capsule.write(twistSpan, "twistSpan", 1e30f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this joint, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
@ -125,6 +178,9 @@ public class ConeJoint extends PhysicsJoint {
|
|||||||
createJoint();
|
createJoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the configured joint in Bullet.
|
||||||
|
*/
|
||||||
protected void createJoint() {
|
protected void createJoint() {
|
||||||
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, rotA, pivotB, rotB);
|
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, rotA, pivotB, rotB);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
||||||
|
@ -42,29 +42,63 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>From bullet manual:</i><br>
|
* A joint based on Bullet's btHingeConstraint.
|
||||||
* Hinge constraint, or revolute joint restricts two additional angular degrees of freedom,
|
* <p>
|
||||||
* so the body can only rotate around one axis, the hinge axis.
|
* <i>From the Bullet manual:</i><br>
|
||||||
* This can be useful to represent doors or wheels rotating around one axis.
|
* Hinge constraint, or revolute joint restricts two additional angular degrees
|
||||||
* The user can specify limits and motor for the hinge.
|
* of freedom, so the body can only rotate around one axis, the hinge axis. This
|
||||||
|
* can be useful to represent doors or wheels rotating around one axis. The user
|
||||||
|
* can specify limits and motor for the hinge.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class HingeJoint extends PhysicsJoint {
|
public class HingeJoint extends PhysicsJoint {
|
||||||
|
|
||||||
protected Vector3f axisA;
|
protected Vector3f axisA;
|
||||||
protected Vector3f axisB;
|
protected Vector3f axisB;
|
||||||
|
/**
|
||||||
|
* copy of the angular-only flag (default=false)
|
||||||
|
*/
|
||||||
protected boolean angularOnly = false;
|
protected boolean angularOnly = false;
|
||||||
|
/**
|
||||||
|
* copy of the limit's bias factor, how strictly position errors (drift) is
|
||||||
|
* corrected (default=0.3)
|
||||||
|
*/
|
||||||
protected float biasFactor = 0.3f;
|
protected float biasFactor = 0.3f;
|
||||||
|
/**
|
||||||
|
* copy of the limit's relaxation factor, the rate at which velocity errors
|
||||||
|
* are corrected (default=1)
|
||||||
|
*/
|
||||||
protected float relaxationFactor = 1.0f;
|
protected float relaxationFactor = 1.0f;
|
||||||
|
/**
|
||||||
|
* copy of the limit's softness, the range fraction at which velocity-error
|
||||||
|
* correction starts operating (default=0.9)
|
||||||
|
*/
|
||||||
protected float limitSoftness = 0.9f;
|
protected float limitSoftness = 0.9f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public HingeJoint() {
|
public HingeJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new HingeJoint
|
* Instantiate a HingeJoint. To be effective, the joint must be added to a
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* physics space.
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param axisA the local axis of the connection to node A (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param axisB the local axis of the connection to node B (not null, alias
|
||||||
|
* created)
|
||||||
*/
|
*/
|
||||||
public HingeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Vector3f axisA, Vector3f axisB) {
|
public HingeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Vector3f axisA, Vector3f axisB) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -74,10 +108,11 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the motor.
|
* Enable or disable this joint's motor.
|
||||||
* @param enable if true, motor is enabled.
|
*
|
||||||
* @param targetVelocity the target velocity of the rotation.
|
* @param enable true to enable, false to disable
|
||||||
* @param maxMotorImpulse the max force applied to the hinge to rotate it.
|
* @param targetVelocity the desired target velocity
|
||||||
|
* @param maxMotorImpulse the desired maximum rotational force
|
||||||
*/
|
*/
|
||||||
public void enableMotor(boolean enable, float targetVelocity, float maxMotorImpulse) {
|
public void enableMotor(boolean enable, float targetVelocity, float maxMotorImpulse) {
|
||||||
enableMotor(objectId, enable, targetVelocity, maxMotorImpulse);
|
enableMotor(objectId, enable, targetVelocity, maxMotorImpulse);
|
||||||
@ -85,18 +120,33 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void enableMotor(long objectId, boolean enable, float targetVelocity, float maxMotorImpulse);
|
private native void enableMotor(long objectId, boolean enable, float targetVelocity, float maxMotorImpulse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this joint's motor is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean getEnableMotor() {
|
public boolean getEnableMotor() {
|
||||||
return getEnableAngularMotor(objectId);
|
return getEnableAngularMotor(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native boolean getEnableAngularMotor(long objectId);
|
private native boolean getEnableAngularMotor(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the motor's target velocity.
|
||||||
|
*
|
||||||
|
* @return velocity
|
||||||
|
*/
|
||||||
public float getMotorTargetVelocity() {
|
public float getMotorTargetVelocity() {
|
||||||
return getMotorTargetVelocity(objectId);
|
return getMotorTargetVelocity(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMotorTargetVelocity(long objectId);
|
private native float getMotorTargetVelocity(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the motor's maximum impulse.
|
||||||
|
*
|
||||||
|
* @return impulse
|
||||||
|
*/
|
||||||
public float getMaxMotorImpulse() {
|
public float getMaxMotorImpulse() {
|
||||||
return getMaxMotorImpulse(objectId);
|
return getMaxMotorImpulse(objectId);
|
||||||
}
|
}
|
||||||
@ -104,9 +154,10 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
private native float getMaxMotorImpulse(long objectId);
|
private native float getMaxMotorImpulse(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the limits of this joint.
|
* Alter this joint's limits.
|
||||||
* @param low the low limit in radians.
|
*
|
||||||
* @param high the high limit in radians.
|
* @param low the desired lower limit of the hinge angle (in radians)
|
||||||
|
* @param high the desired upper limit of the joint angle (in radians)
|
||||||
*/
|
*/
|
||||||
public void setLimit(float low, float high) {
|
public void setLimit(float low, float high) {
|
||||||
setLimit(objectId, low, high);
|
setLimit(objectId, low, high);
|
||||||
@ -115,13 +166,20 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
private native void setLimit(long objectId, float low, float high);
|
private native void setLimit(long objectId, float low, float high);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the limits of this joint.
|
* Alter this joint's limits. If you're above the softness, velocities that
|
||||||
* If you're above the softness, velocities that would shoot through the actual limit are slowed down. The bias be in the range of 0.2 - 0.5.
|
* would shoot through the actual limit are slowed down. The bias should be
|
||||||
* @param low the low limit in radians.
|
* in the range of 0.2 - 0.5.
|
||||||
* @param high the high limit in radians.
|
*
|
||||||
* @param _softness the factor at which the velocity error correction starts operating,i.e a softness of 0.9 means that the vel. corr starts at 90% of the limit range.
|
* @param low the desired lower limit of the hinge angle (in radians)
|
||||||
* @param _biasFactor the magnitude of the position correction. It tells you how strictly the position error (drift ) is corrected.
|
* @param high the desired upper limit of the joint angle (in radians)
|
||||||
* @param _relaxationFactor the rate at which velocity errors are corrected. This can be seen as the strength of the limits. A low value will make the limits more spongy.
|
* @param _softness the desired range fraction at which velocity-error
|
||||||
|
* correction starts operating. A softness of 0.9 means that the correction
|
||||||
|
* starts at 90% of the limit range. (default=0.9)
|
||||||
|
* @param _biasFactor the desired magnitude of the position correction, how
|
||||||
|
* strictly position errors (drift) is corrected. (default=0.3)
|
||||||
|
* @param _relaxationFactor the desired rate at which velocity errors are
|
||||||
|
* corrected. This can be seen as the strength of the limits. A low value
|
||||||
|
* will make the limits more spongy. (default=1)
|
||||||
*/
|
*/
|
||||||
public void setLimit(float low, float high, float _softness, float _biasFactor, float _relaxationFactor) {
|
public void setLimit(float low, float high, float _softness, float _biasFactor, float _relaxationFactor) {
|
||||||
biasFactor = _biasFactor;
|
biasFactor = _biasFactor;
|
||||||
@ -132,18 +190,34 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setLimit(long objectId, float low, float high, float _softness, float _biasFactor, float _relaxationFactor);
|
private native void setLimit(long objectId, float low, float high, float _softness, float _biasFactor, float _relaxationFactor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the upper limit of the hinge angle.
|
||||||
|
*
|
||||||
|
* @return angle (in radians)
|
||||||
|
*/
|
||||||
public float getUpperLimit() {
|
public float getUpperLimit() {
|
||||||
return getUpperLimit(objectId);
|
return getUpperLimit(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getUpperLimit(long objectId);
|
private native float getUpperLimit(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the lower limit of the hinge angle.
|
||||||
|
*
|
||||||
|
* @return the angle (in radians)
|
||||||
|
*/
|
||||||
public float getLowerLimit() {
|
public float getLowerLimit() {
|
||||||
return getLowerLimit(objectId);
|
return getLowerLimit(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLowerLimit(long objectId);
|
private native float getLowerLimit(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the hinge translation flag.
|
||||||
|
*
|
||||||
|
* @param angularOnly true→rotate only, false→rotate and translate
|
||||||
|
* (default=false)
|
||||||
|
*/
|
||||||
public void setAngularOnly(boolean angularOnly) {
|
public void setAngularOnly(boolean angularOnly) {
|
||||||
this.angularOnly = angularOnly;
|
this.angularOnly = angularOnly;
|
||||||
setAngularOnly(objectId, angularOnly);
|
setAngularOnly(objectId, angularOnly);
|
||||||
@ -151,12 +225,23 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setAngularOnly(long objectId, boolean angularOnly);
|
private native void setAngularOnly(long objectId, boolean angularOnly);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the hinge angle.
|
||||||
|
*
|
||||||
|
* @return the angle (in radians)
|
||||||
|
*/
|
||||||
public float getHingeAngle() {
|
public float getHingeAngle() {
|
||||||
return getHingeAngle(objectId);
|
return getHingeAngle(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getHingeAngle(long objectId);
|
private native float getHingeAngle(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this joint, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
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);
|
||||||
@ -177,6 +262,12 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
capsule.write(getMaxMotorImpulse(), "maxMotorImpulse", 0.0f);
|
capsule.write(getMaxMotorImpulse(), "maxMotorImpulse", 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this joint, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -200,6 +291,9 @@ public class HingeJoint extends PhysicsJoint {
|
|||||||
setLimit(lowerLimit, upperLimit, limitSoftness, biasFactor, relaxationFactor);
|
setLimit(lowerLimit, upperLimit, limitSoftness, biasFactor, relaxationFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the configured joint in Bullet.
|
||||||
|
*/
|
||||||
protected void createJoint() {
|
protected void createJoint() {
|
||||||
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, axisA, pivotB, axisB);
|
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, axisA, pivotB, axisB);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -39,24 +39,59 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>PhysicsJoint - Basic Phyiscs Joint</p>
|
* The abstract base class for physics joints based on Bullet's
|
||||||
|
* btTypedConstraint, used to connect 2 dynamic rigid bodies in the same
|
||||||
|
* physics space.
|
||||||
|
* <p>
|
||||||
|
* Joints include ConeJoint, HingeJoint, Point2PointJoint, and SixDofJoint.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public abstract class PhysicsJoint implements Savable {
|
public abstract class PhysicsJoint implements Savable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier of the Bullet constraint. Constructors are responsible
|
||||||
|
* for setting this to a non-zero value. After that, the id never changes.
|
||||||
|
*/
|
||||||
protected long objectId = 0;
|
protected long objectId = 0;
|
||||||
|
/**
|
||||||
|
* one of the connected rigid bodies
|
||||||
|
*/
|
||||||
protected PhysicsRigidBody nodeA;
|
protected PhysicsRigidBody nodeA;
|
||||||
|
/**
|
||||||
|
* the other connected rigid body
|
||||||
|
*/
|
||||||
protected PhysicsRigidBody nodeB;
|
protected PhysicsRigidBody nodeB;
|
||||||
|
/**
|
||||||
|
* local offset of this joint's connection point in node A
|
||||||
|
*/
|
||||||
protected Vector3f pivotA;
|
protected Vector3f pivotA;
|
||||||
|
/**
|
||||||
|
* local offset of this joint's connection point in node B
|
||||||
|
*/
|
||||||
protected Vector3f pivotB;
|
protected Vector3f pivotB;
|
||||||
protected boolean collisionBetweenLinkedBodys = true;
|
protected boolean collisionBetweenLinkedBodys = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public PhysicsJoint() {
|
public PhysicsJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a PhysicsJoint. To be effective, the joint must be added to
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* the physics space of the two bodies. Also, the bodies must be dynamic and
|
||||||
|
* distinct.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA local offset of the joint connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB local offset of the joint connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
*/
|
*/
|
||||||
public PhysicsJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
|
public PhysicsJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
|
||||||
this.nodeA = nodeA;
|
this.nodeA = nodeA;
|
||||||
@ -67,6 +102,11 @@ public abstract class PhysicsJoint implements Savable {
|
|||||||
nodeB.addJoint(this);
|
nodeB.addJoint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the magnitude of the applied impulse.
|
||||||
|
*
|
||||||
|
* @return impulse
|
||||||
|
*/
|
||||||
public float getAppliedImpulse() {
|
public float getAppliedImpulse() {
|
||||||
return getAppliedImpulse(objectId);
|
return getAppliedImpulse(objectId);
|
||||||
}
|
}
|
||||||
@ -74,52 +114,84 @@ public abstract class PhysicsJoint implements Savable {
|
|||||||
private native float getAppliedImpulse(long objectId);
|
private native float getAppliedImpulse(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the constraint
|
* Read the id of the Bullet constraint.
|
||||||
|
*
|
||||||
|
* @return the unique identifier (not zero)
|
||||||
*/
|
*/
|
||||||
public long getObjectId() {
|
public long getObjectId() {
|
||||||
return objectId;
|
return objectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the collisionBetweenLinkedBodys
|
* Test whether collisions are allowed between the linked bodies.
|
||||||
|
*
|
||||||
|
* @return true if collision are allowed, otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean isCollisionBetweenLinkedBodys() {
|
public boolean isCollisionBetweenLinkedBodys() {
|
||||||
return collisionBetweenLinkedBodys;
|
return collisionBetweenLinkedBodys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* toggles collisions between linked bodys<br>
|
* Enable or disable collisions between the linked bodies. The joint must be
|
||||||
* joint has to be removed from and added to PhyiscsSpace to apply this.
|
* removed from and added to PhysicsSpace for this change to be effective.
|
||||||
* @param collisionBetweenLinkedBodys set to false to have no collisions between linked bodys
|
*
|
||||||
|
* @param collisionBetweenLinkedBodys true → allow collisions, false → prevent them
|
||||||
*/
|
*/
|
||||||
public void setCollisionBetweenLinkedBodys(boolean collisionBetweenLinkedBodys) {
|
public void setCollisionBetweenLinkedBodys(boolean collisionBetweenLinkedBodys) {
|
||||||
this.collisionBetweenLinkedBodys = collisionBetweenLinkedBodys;
|
this.collisionBetweenLinkedBodys = collisionBetweenLinkedBodys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the 1st body specified in during construction.
|
||||||
|
*
|
||||||
|
* @return the pre-existing body
|
||||||
|
*/
|
||||||
public PhysicsRigidBody getBodyA() {
|
public PhysicsRigidBody getBodyA() {
|
||||||
return nodeA;
|
return nodeA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the 2nd body specified in during construction.
|
||||||
|
*
|
||||||
|
* @return the pre-existing body
|
||||||
|
*/
|
||||||
public PhysicsRigidBody getBodyB() {
|
public PhysicsRigidBody getBodyB() {
|
||||||
return nodeB;
|
return nodeB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the local offset of the joint connection point in node A.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector
|
||||||
|
*/
|
||||||
public Vector3f getPivotA() {
|
public Vector3f getPivotA() {
|
||||||
return pivotA;
|
return pivotA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the local offset of the joint connection point in node A.
|
||||||
|
*
|
||||||
|
* @return the pre-existing vector
|
||||||
|
*/
|
||||||
public Vector3f getPivotB() {
|
public Vector3f getPivotB() {
|
||||||
return pivotB;
|
return pivotB;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroys this joint and removes it from its connected PhysicsRigidBodys joint lists
|
* Destroy this joint and remove it from the joint lists of its connected
|
||||||
|
* bodies.
|
||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
getBodyA().removeJoint(this);
|
getBodyA().removeJoint(this);
|
||||||
getBodyB().removeJoint(this);
|
getBodyB().removeJoint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this joint, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule capsule = ex.getCapsule(this);
|
OutputCapsule capsule = ex.getCapsule(this);
|
||||||
capsule.write(nodeA, "nodeA", null);
|
capsule.write(nodeA, "nodeA", null);
|
||||||
@ -128,6 +200,12 @@ public abstract class PhysicsJoint implements Savable {
|
|||||||
capsule.write(pivotB, "pivotB", null);
|
capsule.write(pivotB, "pivotB", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this joint, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
this.nodeA = ((PhysicsRigidBody) capsule.readSavable("nodeA", new PhysicsRigidBody()));
|
this.nodeA = ((PhysicsRigidBody) capsule.readSavable("nodeA", new PhysicsRigidBody()));
|
||||||
@ -136,6 +214,12 @@ public abstract class PhysicsJoint implements Savable {
|
|||||||
this.pivotB = (Vector3f) capsule.readSavable("pivotB", new Vector3f());
|
this.pivotB = (Vector3f) capsule.readSavable("pivotB", new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this physics joint just before it is destroyed. Should be
|
||||||
|
* invoked only by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,62 +42,116 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>From bullet manual:</i><br>
|
* A joint based on Bullet's btPoint2PointConstraint.
|
||||||
* Point to point constraint, also known as ball socket joint limits the translation
|
* <p>
|
||||||
* so that the local pivot points of 2 rigidbodies match in worldspace.
|
* <i>From the Bullet manual:</i><br>
|
||||||
* A chain of rigidbodies can be connected using this constraint.
|
* Point to point constraint limits the translation so that the local pivot
|
||||||
|
* points of 2 rigidbodies match in worldspace. A chain of rigidbodies can be
|
||||||
|
* connected using this constraint.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class Point2PointJoint extends PhysicsJoint {
|
public class Point2PointJoint extends PhysicsJoint {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public Point2PointJoint() {
|
public Point2PointJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a Point2PointJoint. To be effective, the joint must be added
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* to a physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
*/
|
*/
|
||||||
public Point2PointJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
|
public Point2PointJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
createJoint();
|
createJoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping.
|
||||||
|
*
|
||||||
|
* @param value the desired viscous damping ratio (0→no damping,
|
||||||
|
* 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDamping(float value) {
|
public void setDamping(float value) {
|
||||||
setDamping(objectId, value);
|
setDamping(objectId, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDamping(long objectId, float value);
|
private native void setDamping(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's impulse clamp.
|
||||||
|
*
|
||||||
|
* @param value the desired impulse clamp value (default=0)
|
||||||
|
*/
|
||||||
public void setImpulseClamp(float value) {
|
public void setImpulseClamp(float value) {
|
||||||
setImpulseClamp(objectId, value);
|
setImpulseClamp(objectId, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setImpulseClamp(long objectId, float value);
|
private native void setImpulseClamp(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's tau value.
|
||||||
|
*
|
||||||
|
* @param value the desired tau value (default=0.3)
|
||||||
|
*/
|
||||||
public void setTau(float value) {
|
public void setTau(float value) {
|
||||||
setTau(objectId, value);
|
setTau(objectId, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setTau(long objectId, float value);
|
private native void setTau(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping ratio.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDamping() {
|
public float getDamping() {
|
||||||
return getDamping(objectId);
|
return getDamping(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDamping(long objectId);
|
private native float getDamping(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's impulse clamp.
|
||||||
|
*
|
||||||
|
* @return the clamp value
|
||||||
|
*/
|
||||||
public float getImpulseClamp() {
|
public float getImpulseClamp() {
|
||||||
return getImpulseClamp(objectId);
|
return getImpulseClamp(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getImpulseClamp(long objectId);
|
private native float getImpulseClamp(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's tau value.
|
||||||
|
*
|
||||||
|
* @return the tau value
|
||||||
|
*/
|
||||||
public float getTau() {
|
public float getTau() {
|
||||||
return getTau(objectId);
|
return getTau(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getTau(long objectId);
|
private native float getTau(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this joint, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -107,6 +161,12 @@ public class Point2PointJoint extends PhysicsJoint {
|
|||||||
cap.write(getImpulseClamp(), "impulseClamp", 0f);
|
cap.write(getImpulseClamp(), "impulseClamp", 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this joint, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
@ -117,6 +177,9 @@ public class Point2PointJoint extends PhysicsJoint {
|
|||||||
setDamping(cap.readFloat("impulseClamp", 0f));
|
setDamping(cap.readFloat("impulseClamp", 0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the configured joint in Bullet.
|
||||||
|
*/
|
||||||
protected void createJoint() {
|
protected void createJoint() {
|
||||||
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, pivotB);
|
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, pivotB);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -47,33 +47,79 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>From bullet manual:</i><br>
|
* A joint based on Bullet's btGeneric6DofConstraint.
|
||||||
* This generic constraint can emulate a variety of standard constraints,
|
* <p>
|
||||||
* by configuring each of the 6 degrees of freedom (dof).
|
* <i>From the Bullet manual:</i><br>
|
||||||
* The first 3 dof axis are linear axis, which represent translation of rigidbodies,
|
* This generic constraint can emulate a variety of standard constraints, by
|
||||||
* and the latter 3 dof axis represent the angular motion. Each axis can be either locked,
|
* configuring each of the 6 degrees of freedom (dof). The first 3 dof axis are
|
||||||
* free or limited. On construction of a new btGeneric6DofConstraint, all axis are locked.
|
* linear axis, which represent translation of rigidbodies, and the latter 3 dof
|
||||||
* Afterwards the axis can be reconfigured. Note that several combinations that
|
* axis represent the angular motion. Each axis can be either locked, free or
|
||||||
* include free and/or limited angular degrees of freedom are undefined.
|
* limited. On construction of a new btGeneric6DofSpring2Constraint, all axis
|
||||||
|
* are locked. Afterwards the axis can be reconfigured. Note that several
|
||||||
|
* combinations that include free and/or limited angular degrees of freedom are
|
||||||
|
* undefined.
|
||||||
|
* <p>
|
||||||
|
* For each axis:<ul>
|
||||||
|
* <li>Lowerlimit = Upperlimit → axis is locked</li>
|
||||||
|
* <li>Lowerlimit > Upperlimit → axis is free</li>
|
||||||
|
* <li>Lowerlimit < Upperlimit → axis it limited in that range</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class SixDofJoint extends PhysicsJoint {
|
public class SixDofJoint extends PhysicsJoint {
|
||||||
|
|
||||||
Matrix3f rotA, rotB;
|
Matrix3f rotA, rotB;
|
||||||
|
/**
|
||||||
|
* true→limits give the allowable range of movement of frameB in frameA
|
||||||
|
* space, false→limits give the allowable range of movement of frameA
|
||||||
|
* in frameB space
|
||||||
|
*/
|
||||||
boolean useLinearReferenceFrameA;
|
boolean useLinearReferenceFrameA;
|
||||||
LinkedList<RotationalLimitMotor> rotationalMotors = new LinkedList<RotationalLimitMotor>();
|
LinkedList<RotationalLimitMotor> rotationalMotors = new LinkedList<RotationalLimitMotor>();
|
||||||
TranslationalLimitMotor translationalMotor;
|
TranslationalLimitMotor translationalMotor;
|
||||||
|
/**
|
||||||
|
* upper limits for rotation of all 3 axes
|
||||||
|
*/
|
||||||
Vector3f angularUpperLimit = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
Vector3f angularUpperLimit = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
||||||
|
/**
|
||||||
|
* lower limits for rotation of all 3 axes
|
||||||
|
*/
|
||||||
Vector3f angularLowerLimit = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
Vector3f angularLowerLimit = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
||||||
|
/**
|
||||||
|
* upper limit for translation of all 3 axes
|
||||||
|
*/
|
||||||
Vector3f linearUpperLimit = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
Vector3f linearUpperLimit = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
||||||
|
/**
|
||||||
|
* lower limits for translation of all 3 axes
|
||||||
|
*/
|
||||||
Vector3f linearLowerLimit = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
Vector3f linearLowerLimit = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public SixDofJoint() {
|
public SixDofJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a SixDofJoint. To be effective, the joint must be added to a
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param rotA the local orientation of the connection to node A (not null,
|
||||||
|
* alias created)
|
||||||
|
* @param rotB the local orientation of the connection to node B (not null,
|
||||||
|
* alias created)
|
||||||
|
* @param useLinearReferenceFrameA true→use node A, false→use node
|
||||||
|
* B
|
||||||
*/
|
*/
|
||||||
public SixDofJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB, boolean useLinearReferenceFrameA) {
|
public SixDofJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB, boolean useLinearReferenceFrameA) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -87,8 +133,19 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a SixDofJoint. To be effective, the joint must be added to a
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param useLinearReferenceFrameA true→use node A, false→use node
|
||||||
|
* B
|
||||||
*/
|
*/
|
||||||
public SixDofJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, boolean useLinearReferenceFrameA) {
|
public SixDofJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, boolean useLinearReferenceFrameA) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -114,24 +171,32 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
private native long getTranslationalLimitMotor(long objectId);
|
private native long getTranslationalLimitMotor(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the TranslationalLimitMotor of this 6DofJoint which allows
|
* Access the TranslationalLimitMotor of this joint, the motor which
|
||||||
* manipulating the translational axis
|
* influences translation on all 3 axes.
|
||||||
* @return the TranslationalLimitMotor
|
*
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public TranslationalLimitMotor getTranslationalLimitMotor() {
|
public TranslationalLimitMotor getTranslationalLimitMotor() {
|
||||||
return translationalMotor;
|
return translationalMotor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns one of the three RotationalLimitMotors of this 6DofJoint which
|
* Access the indexed RotationalLimitMotor of this joint, the motor which
|
||||||
* allow manipulating the rotational axes
|
* influences rotation around one axis.
|
||||||
* @param index the index of the RotationalLimitMotor
|
*
|
||||||
* @return the RotationalLimitMotor at the given index
|
* @param index the axis index of the desired motor: 0→X, 1→Y,
|
||||||
|
* 2→Z
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public RotationalLimitMotor getRotationalLimitMotor(int index) {
|
public RotationalLimitMotor getRotationalLimitMotor(int index) {
|
||||||
return rotationalMotors.get(index);
|
return rotationalMotors.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's upper limits for translation of all 3 axes.
|
||||||
|
*
|
||||||
|
* @param vector the desired upper limits (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setLinearUpperLimit(Vector3f vector) {
|
public void setLinearUpperLimit(Vector3f vector) {
|
||||||
linearUpperLimit.set(vector);
|
linearUpperLimit.set(vector);
|
||||||
setLinearUpperLimit(objectId, vector);
|
setLinearUpperLimit(objectId, vector);
|
||||||
@ -139,6 +204,11 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setLinearUpperLimit(long objctId, Vector3f vector);
|
private native void setLinearUpperLimit(long objctId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's lower limits for translation of all 3 axes.
|
||||||
|
*
|
||||||
|
* @param vector the desired lower limits (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setLinearLowerLimit(Vector3f vector) {
|
public void setLinearLowerLimit(Vector3f vector) {
|
||||||
linearLowerLimit.set(vector);
|
linearLowerLimit.set(vector);
|
||||||
setLinearLowerLimit(objectId, vector);
|
setLinearLowerLimit(objectId, vector);
|
||||||
@ -146,6 +216,11 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setLinearLowerLimit(long objctId, Vector3f vector);
|
private native void setLinearLowerLimit(long objctId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's upper limits for rotation of all 3 axes.
|
||||||
|
*
|
||||||
|
* @param vector the desired upper limits (in radians, not null, unaffected)
|
||||||
|
*/
|
||||||
public void setAngularUpperLimit(Vector3f vector) {
|
public void setAngularUpperLimit(Vector3f vector) {
|
||||||
angularUpperLimit.set(vector);
|
angularUpperLimit.set(vector);
|
||||||
setAngularUpperLimit(objectId, vector);
|
setAngularUpperLimit(objectId, vector);
|
||||||
@ -153,6 +228,11 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setAngularUpperLimit(long objctId, Vector3f vector);
|
private native void setAngularUpperLimit(long objctId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's lower limits for rotation of all 3 axes.
|
||||||
|
*
|
||||||
|
* @param vector the desired lower limits (in radians, not null, unaffected)
|
||||||
|
*/
|
||||||
public void setAngularLowerLimit(Vector3f vector) {
|
public void setAngularLowerLimit(Vector3f vector) {
|
||||||
angularLowerLimit.set(vector);
|
angularLowerLimit.set(vector);
|
||||||
setAngularLowerLimit(objectId, vector);
|
setAngularLowerLimit(objectId, vector);
|
||||||
@ -162,6 +242,12 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
native long createJoint(long objectIdA, long objectIdB, Vector3f pivotA, Matrix3f rotA, Vector3f pivotB, Matrix3f rotB, boolean useLinearReferenceFrameA);
|
native long createJoint(long objectIdA, long objectIdB, Vector3f pivotA, Matrix3f rotA, Vector3f pivotB, Matrix3f rotB, boolean useLinearReferenceFrameA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this joint, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
@ -197,6 +283,12 @@ public class SixDofJoint extends PhysicsJoint {
|
|||||||
getTranslationalLimitMotor().setUpperLimit((Vector3f) capsule.readSavable("transMotor_UpperLimit", Vector3f.ZERO));
|
getTranslationalLimitMotor().setUpperLimit((Vector3f) capsule.readSavable("transMotor_UpperLimit", Vector3f.ZERO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this joint, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -36,14 +36,24 @@ import com.jme3.math.Matrix3f;
|
|||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>From bullet manual:</i><br>
|
* A 6 degree-of-freedom joint based on Bullet's btGeneric6DofSpringConstraint.
|
||||||
* This generic constraint can emulate a variety of standard constraints,
|
* <p>
|
||||||
* by configuring each of the 6 degrees of freedom (dof).
|
* <i>From the Bullet manual:</i><br>
|
||||||
* The first 3 dof axis are linear axis, which represent translation of rigidbodies,
|
* This generic constraint can emulate a variety of standard constraints, by
|
||||||
* and the latter 3 dof axis represent the angular motion. Each axis can be either locked,
|
* configuring each of the 6 degrees of freedom (dof). The first 3 dof axis are
|
||||||
* free or limited. On construction of a new btGeneric6DofConstraint, all axis are locked.
|
* linear axis, which represent translation of rigidbodies, and the latter 3 dof
|
||||||
* Afterwards the axis can be reconfigured. Note that several combinations that
|
* axis represent the angular motion. Each axis can be either locked, free or
|
||||||
* include free and/or limited angular degrees of freedom are undefined.
|
* limited. On construction of a new btGeneric6DofSpring2Constraint, all axis
|
||||||
|
* are locked. Afterwards the axis can be reconfigured. Note that several
|
||||||
|
* combinations that include free and/or limited angular degrees of freedom are
|
||||||
|
* undefined.
|
||||||
|
* <p>
|
||||||
|
* For each axis:<ul>
|
||||||
|
* <li>Lowerlimit = Upperlimit → axis is locked</li>
|
||||||
|
* <li>Lowerlimit > Upperlimit → axis is free</li>
|
||||||
|
* <li>Lowerlimit < Upperlimit → axis it limited in that range</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class SixDofSpringJoint extends SixDofJoint {
|
public class SixDofSpringJoint extends SixDofJoint {
|
||||||
@ -53,35 +63,84 @@ public class SixDofSpringJoint extends SixDofJoint {
|
|||||||
final float springStiffness[] = new float[6];
|
final float springStiffness[] = new float[6];
|
||||||
final float springDamping[] = new float[6]; // between 0 and 1 (1 == no damping)
|
final float springDamping[] = new float[6]; // between 0 and 1 (1 == no damping)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public SixDofSpringJoint() {
|
public SixDofSpringJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a SixDofSpringJoint. To be effective, the joint must be added
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* to a physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param rotA the local orientation of the connection to node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param rotB the local orientation of the connection to node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param useLinearReferenceFrameA true→use node A, false→use node
|
||||||
|
* B
|
||||||
*/
|
*/
|
||||||
public SixDofSpringJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB, boolean useLinearReferenceFrameA) {
|
public SixDofSpringJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB, boolean useLinearReferenceFrameA) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB, rotA, rotB, useLinearReferenceFrameA);
|
super(nodeA, nodeB, pivotA, pivotB, rotA, rotB, useLinearReferenceFrameA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable the spring for the indexed degree of freedom.
|
||||||
|
*
|
||||||
|
* @param index which degree of freedom (≥0, <6)
|
||||||
|
* @param onOff true → enable, false → disable
|
||||||
|
*/
|
||||||
public void enableSpring(int index, boolean onOff) {
|
public void enableSpring(int index, boolean onOff) {
|
||||||
enableSpring(objectId, index, onOff);
|
enableSpring(objectId, index, onOff);
|
||||||
}
|
}
|
||||||
native void enableSpring(long objctId, int index, boolean onOff);
|
native void enableSpring(long objctId, int index, boolean onOff);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the spring stiffness for the indexed degree of freedom.
|
||||||
|
*
|
||||||
|
* @param index which degree of freedom (≥0, <6)
|
||||||
|
* @param stiffness the desired stiffness
|
||||||
|
*/
|
||||||
public void setStiffness(int index, float stiffness) {
|
public void setStiffness(int index, float stiffness) {
|
||||||
setStiffness(objectId, index, stiffness);
|
setStiffness(objectId, index, stiffness);
|
||||||
}
|
}
|
||||||
native void setStiffness(long objctId, int index, float stiffness);
|
native void setStiffness(long objctId, int index, float stiffness);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the damping for the indexed degree of freedom.
|
||||||
|
*
|
||||||
|
* @param index which degree of freedom (≥0, <6)
|
||||||
|
* @param damping the desired viscous damping ratio (0→no damping,
|
||||||
|
* 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDamping(int index, float damping) {
|
public void setDamping(int index, float damping) {
|
||||||
setDamping(objectId, index, damping);
|
setDamping(objectId, index, damping);
|
||||||
|
|
||||||
}
|
}
|
||||||
native void setDamping(long objctId, int index, float damping);
|
native void setDamping(long objctId, int index, float damping);
|
||||||
|
/**
|
||||||
|
* Alter the equilibrium points for all degrees of freedom, based on the
|
||||||
|
* current constraint position/orientation.
|
||||||
|
*/
|
||||||
public void setEquilibriumPoint() { // set the current constraint position/orientation as an equilibrium point for all DOF
|
public void setEquilibriumPoint() { // set the current constraint position/orientation as an equilibrium point for all DOF
|
||||||
setEquilibriumPoint(objectId);
|
setEquilibriumPoint(objectId);
|
||||||
}
|
}
|
||||||
native void setEquilibriumPoint(long objctId);
|
native void setEquilibriumPoint(long objctId);
|
||||||
|
/**
|
||||||
|
* Alter the equilibrium point of the indexed degree of freedom, based on
|
||||||
|
* the current constraint position/orientation.
|
||||||
|
*
|
||||||
|
* @param index which degree of freedom (≥0, <6)
|
||||||
|
*/
|
||||||
public void setEquilibriumPoint(int index){ // set the current constraint position/orientation as an equilibrium point for given DOF
|
public void setEquilibriumPoint(int index){ // set the current constraint position/orientation as an equilibrium point for given DOF
|
||||||
setEquilibriumPoint(objectId, index);
|
setEquilibriumPoint(objectId, index);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -43,8 +43,12 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>From bullet manual:</i><br>
|
* A slider joint based on Bullet's btSliderConstraint.
|
||||||
* The slider constraint allows the body to rotate around one axis and translate along this axis.
|
* <p>
|
||||||
|
* <i>From the Bullet manual:</i><br>
|
||||||
|
* The slider constraint allows the body to rotate around one axis and translate
|
||||||
|
* along this axis.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class SliderJoint extends PhysicsJoint {
|
public class SliderJoint extends PhysicsJoint {
|
||||||
@ -52,12 +56,29 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
protected Matrix3f rotA, rotB;
|
protected Matrix3f rotA, rotB;
|
||||||
protected boolean useLinearReferenceFrameA;
|
protected boolean useLinearReferenceFrameA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public SliderJoint() {
|
public SliderJoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a SliderJoint. To be effective, the joint must be added to a
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param rotA the local orientation of the connection to node A (not null, alias created)
|
||||||
|
* @param rotB the local orientation of the connection to node B (not null, alias created)
|
||||||
|
* @param useLinearReferenceFrameA true→use node A, false→use node
|
||||||
|
* B
|
||||||
*/
|
*/
|
||||||
public SliderJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB, boolean useLinearReferenceFrameA) {
|
public SliderJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB, boolean useLinearReferenceFrameA) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -68,8 +89,19 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pivotA local translation of the joint connection point in node A
|
* Instantiate a SliderJoint. To be effective, the joint must be added to a
|
||||||
* @param pivotB local translation of the joint connection point in node B
|
* physics space.
|
||||||
|
*
|
||||||
|
* @param nodeA the 1st body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param nodeB the 2nd body connected by the joint (not null, alias
|
||||||
|
* created)
|
||||||
|
* @param pivotA the local offset of the connection point in node A (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param pivotB the local offset of the connection point in node B (not
|
||||||
|
* null, alias created)
|
||||||
|
* @param useLinearReferenceFrameA true→use node A, false→use node
|
||||||
|
* B
|
||||||
*/
|
*/
|
||||||
public SliderJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, boolean useLinearReferenceFrameA) {
|
public SliderJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, boolean useLinearReferenceFrameA) {
|
||||||
super(nodeA, nodeB, pivotA, pivotB);
|
super(nodeA, nodeB, pivotA, pivotB);
|
||||||
@ -79,210 +111,399 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
createJoint();
|
createJoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's lower limit for on-axis translation.
|
||||||
|
*
|
||||||
|
* @return the lower limit
|
||||||
|
*/
|
||||||
public float getLowerLinLimit() {
|
public float getLowerLinLimit() {
|
||||||
return getLowerLinLimit(objectId);
|
return getLowerLinLimit(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLowerLinLimit(long objectId);
|
private native float getLowerLinLimit(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's lower limit for on-axis translation.
|
||||||
|
*
|
||||||
|
* @param lowerLinLimit the desired lower limit (default=-1)
|
||||||
|
*/
|
||||||
public void setLowerLinLimit(float lowerLinLimit) {
|
public void setLowerLinLimit(float lowerLinLimit) {
|
||||||
setLowerLinLimit(objectId, lowerLinLimit);
|
setLowerLinLimit(objectId, lowerLinLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLowerLinLimit(long objectId, float value);
|
private native void setLowerLinLimit(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's upper limit for on-axis translation.
|
||||||
|
*
|
||||||
|
* @return the upper limit
|
||||||
|
*/
|
||||||
public float getUpperLinLimit() {
|
public float getUpperLinLimit() {
|
||||||
return getUpperLinLimit(objectId);
|
return getUpperLinLimit(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getUpperLinLimit(long objectId);
|
private native float getUpperLinLimit(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's upper limit for on-axis translation.
|
||||||
|
*
|
||||||
|
* @param upperLinLimit the desired upper limit (default=1)
|
||||||
|
*/
|
||||||
public void setUpperLinLimit(float upperLinLimit) {
|
public void setUpperLinLimit(float upperLinLimit) {
|
||||||
setUpperLinLimit(objectId, upperLinLimit);
|
setUpperLinLimit(objectId, upperLinLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setUpperLinLimit(long objectId, float value);
|
private native void setUpperLinLimit(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's lower limit for on-axis rotation.
|
||||||
|
*
|
||||||
|
* @return the lower limit angle (in radians)
|
||||||
|
*/
|
||||||
public float getLowerAngLimit() {
|
public float getLowerAngLimit() {
|
||||||
return getLowerAngLimit(objectId);
|
return getLowerAngLimit(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLowerAngLimit(long objectId);
|
private native float getLowerAngLimit(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's lower limit for on-axis rotation.
|
||||||
|
*
|
||||||
|
* @param lowerAngLimit the desired lower limit angle (in radians,
|
||||||
|
* default=0)
|
||||||
|
*/
|
||||||
public void setLowerAngLimit(float lowerAngLimit) {
|
public void setLowerAngLimit(float lowerAngLimit) {
|
||||||
setLowerAngLimit(objectId, lowerAngLimit);
|
setLowerAngLimit(objectId, lowerAngLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLowerAngLimit(long objectId, float value);
|
private native void setLowerAngLimit(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's upper limit for on-axis rotation.
|
||||||
|
*
|
||||||
|
* @return the upper limit angle (in radians)
|
||||||
|
*/
|
||||||
public float getUpperAngLimit() {
|
public float getUpperAngLimit() {
|
||||||
return getUpperAngLimit(objectId);
|
return getUpperAngLimit(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getUpperAngLimit(long objectId);
|
private native float getUpperAngLimit(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's upper limit for on-axis rotation.
|
||||||
|
*
|
||||||
|
* @param upperAngLimit the desired upper limit angle (in radians,
|
||||||
|
* default=0)
|
||||||
|
*/
|
||||||
public void setUpperAngLimit(float upperAngLimit) {
|
public void setUpperAngLimit(float upperAngLimit) {
|
||||||
setUpperAngLimit(objectId, upperAngLimit);
|
setUpperAngLimit(objectId, upperAngLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setUpperAngLimit(long objectId, float value);
|
private native void setUpperAngLimit(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's softness for on-axis translation between the limits.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getSoftnessDirLin() {
|
public float getSoftnessDirLin() {
|
||||||
return getSoftnessDirLin(objectId);
|
return getSoftnessDirLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getSoftnessDirLin(long objectId);
|
private native float getSoftnessDirLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's softness for on-axis translation between the limits.
|
||||||
|
*
|
||||||
|
* @param softnessDirLin the desired softness (default=1)
|
||||||
|
*/
|
||||||
public void setSoftnessDirLin(float softnessDirLin) {
|
public void setSoftnessDirLin(float softnessDirLin) {
|
||||||
setSoftnessDirLin(objectId, softnessDirLin);
|
setSoftnessDirLin(objectId, softnessDirLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setSoftnessDirLin(long objectId, float value);
|
private native void setSoftnessDirLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's restitution for on-axis translation between the limits.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitutionDirLin() {
|
public float getRestitutionDirLin() {
|
||||||
return getRestitutionDirLin(objectId);
|
return getRestitutionDirLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getRestitutionDirLin(long objectId);
|
private native float getRestitutionDirLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's restitution for on-axis translation between the limits.
|
||||||
|
*
|
||||||
|
* @param restitutionDirLin the desired restitution (bounce) factor
|
||||||
|
* (default=0.7)
|
||||||
|
*/
|
||||||
public void setRestitutionDirLin(float restitutionDirLin) {
|
public void setRestitutionDirLin(float restitutionDirLin) {
|
||||||
setRestitutionDirLin(objectId, restitutionDirLin);
|
setRestitutionDirLin(objectId, restitutionDirLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setRestitutionDirLin(long objectId, float value);
|
private native void setRestitutionDirLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping for on-axis translation between the limits.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDampingDirLin() {
|
public float getDampingDirLin() {
|
||||||
return getDampingDirLin(objectId);
|
return getDampingDirLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDampingDirLin(long objectId);
|
private native float getDampingDirLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping for on-axis translation between the limits.
|
||||||
|
*
|
||||||
|
* @param dampingDirLin the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=0)
|
||||||
|
*/
|
||||||
public void setDampingDirLin(float dampingDirLin) {
|
public void setDampingDirLin(float dampingDirLin) {
|
||||||
setDampingDirLin(objectId, dampingDirLin);
|
setDampingDirLin(objectId, dampingDirLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDampingDirLin(long objectId, float value);
|
private native void setDampingDirLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's softness for on-axis rotation between the limits.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getSoftnessDirAng() {
|
public float getSoftnessDirAng() {
|
||||||
return getSoftnessDirAng(objectId);
|
return getSoftnessDirAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getSoftnessDirAng(long objectId);
|
private native float getSoftnessDirAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's softness for on-axis rotation between the limits.
|
||||||
|
*
|
||||||
|
* @param softnessDirAng the desired softness (default=1)
|
||||||
|
*/
|
||||||
public void setSoftnessDirAng(float softnessDirAng) {
|
public void setSoftnessDirAng(float softnessDirAng) {
|
||||||
setSoftnessDirAng(objectId, softnessDirAng);
|
setSoftnessDirAng(objectId, softnessDirAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setSoftnessDirAng(long objectId, float value);
|
private native void setSoftnessDirAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's restitution for on-axis rotation between the limits.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitutionDirAng() {
|
public float getRestitutionDirAng() {
|
||||||
return getRestitutionDirAng(objectId);
|
return getRestitutionDirAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getRestitutionDirAng(long objectId);
|
private native float getRestitutionDirAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's restitution for on-axis rotation between the limits.
|
||||||
|
*
|
||||||
|
* @param restitutionDirAng the desired restitution (bounce) factor
|
||||||
|
* (default=0.7)
|
||||||
|
*/
|
||||||
public void setRestitutionDirAng(float restitutionDirAng) {
|
public void setRestitutionDirAng(float restitutionDirAng) {
|
||||||
setRestitutionDirAng(objectId, restitutionDirAng);
|
setRestitutionDirAng(objectId, restitutionDirAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setRestitutionDirAng(long objectId, float value);
|
private native void setRestitutionDirAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping for on-axis rotation between the limits.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDampingDirAng() {
|
public float getDampingDirAng() {
|
||||||
return getDampingDirAng(objectId);
|
return getDampingDirAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDampingDirAng(long objectId);
|
private native float getDampingDirAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping for on-axis rotation between the limits.
|
||||||
|
*
|
||||||
|
* @param dampingDirAng the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=0)
|
||||||
|
*/
|
||||||
public void setDampingDirAng(float dampingDirAng) {
|
public void setDampingDirAng(float dampingDirAng) {
|
||||||
setDampingDirAng(objectId, dampingDirAng);
|
setDampingDirAng(objectId, dampingDirAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDampingDirAng(long objectId, float value);
|
private native void setDampingDirAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's softness for on-axis translation hitting the limits.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getSoftnessLimLin() {
|
public float getSoftnessLimLin() {
|
||||||
return getSoftnessLimLin(objectId);
|
return getSoftnessLimLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getSoftnessLimLin(long objectId);
|
private native float getSoftnessLimLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's softness for on-axis translation hitting the limits.
|
||||||
|
*
|
||||||
|
* @param softnessLimLin the desired softness (default=1)
|
||||||
|
*/
|
||||||
public void setSoftnessLimLin(float softnessLimLin) {
|
public void setSoftnessLimLin(float softnessLimLin) {
|
||||||
setSoftnessLimLin(objectId, softnessLimLin);
|
setSoftnessLimLin(objectId, softnessLimLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setSoftnessLimLin(long objectId, float value);
|
private native void setSoftnessLimLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's restitution for on-axis translation hitting the limits.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitutionLimLin() {
|
public float getRestitutionLimLin() {
|
||||||
return getRestitutionLimLin(objectId);
|
return getRestitutionLimLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getRestitutionLimLin(long objectId);
|
private native float getRestitutionLimLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's restitution for on-axis translation hitting the limits.
|
||||||
|
*
|
||||||
|
* @param restitutionLimLin the desired restitution (bounce) factor
|
||||||
|
* (default=0.7)
|
||||||
|
*/
|
||||||
public void setRestitutionLimLin(float restitutionLimLin) {
|
public void setRestitutionLimLin(float restitutionLimLin) {
|
||||||
setRestitutionLimLin(objectId, restitutionLimLin);
|
setRestitutionLimLin(objectId, restitutionLimLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setRestitutionLimLin(long objectId, float value);
|
private native void setRestitutionLimLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping for on-axis translation hitting the limits.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDampingLimLin() {
|
public float getDampingLimLin() {
|
||||||
return getDampingLimLin(objectId);
|
return getDampingLimLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDampingLimLin(long objectId);
|
private native float getDampingLimLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping for on-axis translation hitting the limits.
|
||||||
|
*
|
||||||
|
* @param dampingLimLin the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDampingLimLin(float dampingLimLin) {
|
public void setDampingLimLin(float dampingLimLin) {
|
||||||
setDampingLimLin(objectId, dampingLimLin);
|
setDampingLimLin(objectId, dampingLimLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDampingLimLin(long objectId, float value);
|
private native void setDampingLimLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's softness for on-axis rotation hitting the limits.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getSoftnessLimAng() {
|
public float getSoftnessLimAng() {
|
||||||
return getSoftnessLimAng(objectId);
|
return getSoftnessLimAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getSoftnessLimAng(long objectId);
|
private native float getSoftnessLimAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's softness for on-axis rotation hitting the limits.
|
||||||
|
*
|
||||||
|
* @param softnessLimAng the desired softness (default=1)
|
||||||
|
*/
|
||||||
public void setSoftnessLimAng(float softnessLimAng) {
|
public void setSoftnessLimAng(float softnessLimAng) {
|
||||||
setSoftnessLimAng(objectId, softnessLimAng);
|
setSoftnessLimAng(objectId, softnessLimAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setSoftnessLimAng(long objectId, float value);
|
private native void setSoftnessLimAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's restitution for on-axis rotation hitting the limits.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitutionLimAng() {
|
public float getRestitutionLimAng() {
|
||||||
return getRestitutionLimAng(objectId);
|
return getRestitutionLimAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getRestitutionLimAng(long objectId);
|
private native float getRestitutionLimAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's restitution for on-axis rotation hitting the limits.
|
||||||
|
*
|
||||||
|
* @param restitutionLimAng the desired restitution (bounce) factor
|
||||||
|
* (default=0.7)
|
||||||
|
*/
|
||||||
public void setRestitutionLimAng(float restitutionLimAng) {
|
public void setRestitutionLimAng(float restitutionLimAng) {
|
||||||
setRestitutionLimAng(objectId, restitutionLimAng);
|
setRestitutionLimAng(objectId, restitutionLimAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setRestitutionLimAng(long objectId, float value);
|
private native void setRestitutionLimAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping for on-axis rotation hitting the limits.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDampingLimAng() {
|
public float getDampingLimAng() {
|
||||||
return getDampingLimAng(objectId);
|
return getDampingLimAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDampingLimAng(long objectId);
|
private native float getDampingLimAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping for on-axis rotation hitting the limits.
|
||||||
|
*
|
||||||
|
* @param dampingLimAng the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDampingLimAng(float dampingLimAng) {
|
public void setDampingLimAng(float dampingLimAng) {
|
||||||
setDampingLimAng(objectId, dampingLimAng);
|
setDampingLimAng(objectId, dampingLimAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDampingLimAng(long objectId, float value);
|
private native void setDampingLimAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's softness for off-axis translation.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getSoftnessOrthoLin() {
|
public float getSoftnessOrthoLin() {
|
||||||
return getSoftnessOrthoLin(objectId);
|
return getSoftnessOrthoLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getSoftnessOrthoLin(long objectId);
|
private native float getSoftnessOrthoLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's softness for off-axis translation.
|
||||||
|
*
|
||||||
|
* @param softnessOrthoLin the desired softness (default=1)
|
||||||
|
*/
|
||||||
public void setSoftnessOrthoLin(float softnessOrthoLin) {
|
public void setSoftnessOrthoLin(float softnessOrthoLin) {
|
||||||
setSoftnessOrthoLin(objectId, softnessOrthoLin);
|
setSoftnessOrthoLin(objectId, softnessOrthoLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setSoftnessOrthoLin(long objectId, float value);
|
private native void setSoftnessOrthoLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's restitution for off-axis translation.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitutionOrthoLin() {
|
public float getRestitutionOrthoLin() {
|
||||||
return getRestitutionOrthoLin(objectId);
|
return getRestitutionOrthoLin(objectId);
|
||||||
}
|
}
|
||||||
@ -292,7 +513,8 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
/**
|
/**
|
||||||
* Alter the joint's restitution for off-axis translation.
|
* Alter the joint's restitution for off-axis translation.
|
||||||
*
|
*
|
||||||
* @param restitutionOrthoLin the desired restitution (default=0.7)
|
* @param restitutionOrthoLin the desired restitution (bounce) factor
|
||||||
|
* (default=0.7)
|
||||||
*/
|
*/
|
||||||
public void setRestitutionOrthoLin(float restitutionOrthoLin) {
|
public void setRestitutionOrthoLin(float restitutionOrthoLin) {
|
||||||
setRestitutionOrthoLin(objectId, restitutionOrthoLin);
|
setRestitutionOrthoLin(objectId, restitutionOrthoLin);
|
||||||
@ -300,126 +522,240 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
|
|
||||||
private native void setRestitutionOrthoLin(long objectId, float value);
|
private native void setRestitutionOrthoLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping for off-axis translation.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDampingOrthoLin() {
|
public float getDampingOrthoLin() {
|
||||||
return getDampingOrthoLin(objectId);
|
return getDampingOrthoLin(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDampingOrthoLin(long objectId);
|
private native float getDampingOrthoLin(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping for off-axis translation.
|
||||||
|
*
|
||||||
|
* @param dampingOrthoLin the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDampingOrthoLin(float dampingOrthoLin) {
|
public void setDampingOrthoLin(float dampingOrthoLin) {
|
||||||
setDampingOrthoLin(objectId, dampingOrthoLin);
|
setDampingOrthoLin(objectId, dampingOrthoLin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDampingOrthoLin(long objectId, float value);
|
private native void setDampingOrthoLin(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's softness for off-axis rotation.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getSoftnessOrthoAng() {
|
public float getSoftnessOrthoAng() {
|
||||||
return getSoftnessOrthoAng(objectId);
|
return getSoftnessOrthoAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getSoftnessOrthoAng(long objectId);
|
private native float getSoftnessOrthoAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's softness for off-axis rotation.
|
||||||
|
*
|
||||||
|
* @param softnessOrthoAng the desired softness (default=1)
|
||||||
|
*/
|
||||||
public void setSoftnessOrthoAng(float softnessOrthoAng) {
|
public void setSoftnessOrthoAng(float softnessOrthoAng) {
|
||||||
setSoftnessOrthoAng(objectId, softnessOrthoAng);
|
setSoftnessOrthoAng(objectId, softnessOrthoAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setSoftnessOrthoAng(long objectId, float value);
|
private native void setSoftnessOrthoAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's restitution for off-axis rotation.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitutionOrthoAng() {
|
public float getRestitutionOrthoAng() {
|
||||||
return getRestitutionOrthoAng(objectId);
|
return getRestitutionOrthoAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getRestitutionOrthoAng(long objectId);
|
private native float getRestitutionOrthoAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's restitution for off-axis rotation.
|
||||||
|
*
|
||||||
|
* @param restitutionOrthoAng the desired restitution (bounce) factor
|
||||||
|
* (default=0.7)
|
||||||
|
*/
|
||||||
public void setRestitutionOrthoAng(float restitutionOrthoAng) {
|
public void setRestitutionOrthoAng(float restitutionOrthoAng) {
|
||||||
setRestitutionOrthoAng(objectId, restitutionOrthoAng);
|
setRestitutionOrthoAng(objectId, restitutionOrthoAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setRestitutionOrthoAng(long objectId, float value);
|
private native void setRestitutionOrthoAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the joint's damping for off-axis rotation.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDampingOrthoAng() {
|
public float getDampingOrthoAng() {
|
||||||
return getDampingOrthoAng(objectId);
|
return getDampingOrthoAng(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDampingOrthoAng(long objectId);
|
private native float getDampingOrthoAng(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the joint's damping for off-axis rotation.
|
||||||
|
*
|
||||||
|
* @param dampingOrthoAng the desired viscous damping ratio (0→no
|
||||||
|
* damping, 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDampingOrthoAng(float dampingOrthoAng) {
|
public void setDampingOrthoAng(float dampingOrthoAng) {
|
||||||
setDampingOrthoAng(objectId, dampingOrthoAng);
|
setDampingOrthoAng(objectId, dampingOrthoAng);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDampingOrthoAng(long objectId, float value);
|
private native void setDampingOrthoAng(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the translation motor is powered.
|
||||||
|
*
|
||||||
|
* @return true if powered, otherwise false
|
||||||
|
*/
|
||||||
public boolean isPoweredLinMotor() {
|
public boolean isPoweredLinMotor() {
|
||||||
return isPoweredLinMotor(objectId);
|
return isPoweredLinMotor(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native boolean isPoweredLinMotor(long objectId);
|
private native boolean isPoweredLinMotor(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether the translation motor is powered.
|
||||||
|
*
|
||||||
|
* @param poweredLinMotor true to power the motor, false to de-power it
|
||||||
|
* (default=false)
|
||||||
|
*/
|
||||||
public void setPoweredLinMotor(boolean poweredLinMotor) {
|
public void setPoweredLinMotor(boolean poweredLinMotor) {
|
||||||
setPoweredLinMotor(objectId, poweredLinMotor);
|
setPoweredLinMotor(objectId, poweredLinMotor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setPoweredLinMotor(long objectId, boolean value);
|
private native void setPoweredLinMotor(long objectId, boolean value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the velocity target of the translation motor.
|
||||||
|
*
|
||||||
|
* @return the velocity target
|
||||||
|
*/
|
||||||
public float getTargetLinMotorVelocity() {
|
public float getTargetLinMotorVelocity() {
|
||||||
return getTargetLinMotorVelocity(objectId);
|
return getTargetLinMotorVelocity(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getTargetLinMotorVelocity(long objectId);
|
private native float getTargetLinMotorVelocity(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the velocity target of the translation motor.
|
||||||
|
*
|
||||||
|
* @param targetLinMotorVelocity the desired velocity target (default=0)
|
||||||
|
*/
|
||||||
public void setTargetLinMotorVelocity(float targetLinMotorVelocity) {
|
public void setTargetLinMotorVelocity(float targetLinMotorVelocity) {
|
||||||
setTargetLinMotorVelocity(objectId, targetLinMotorVelocity);
|
setTargetLinMotorVelocity(objectId, targetLinMotorVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setTargetLinMotorVelocity(long objectId, float value);
|
private native void setTargetLinMotorVelocity(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the maximum force of the translation motor.
|
||||||
|
*
|
||||||
|
* @return the maximum force
|
||||||
|
*/
|
||||||
public float getMaxLinMotorForce() {
|
public float getMaxLinMotorForce() {
|
||||||
return getMaxLinMotorForce(objectId);
|
return getMaxLinMotorForce(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMaxLinMotorForce(long objectId);
|
private native float getMaxLinMotorForce(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the maximum force of the translation motor.
|
||||||
|
*
|
||||||
|
* @param maxLinMotorForce the desired maximum force (default=0)
|
||||||
|
*/
|
||||||
public void setMaxLinMotorForce(float maxLinMotorForce) {
|
public void setMaxLinMotorForce(float maxLinMotorForce) {
|
||||||
setMaxLinMotorForce(objectId, maxLinMotorForce);
|
setMaxLinMotorForce(objectId, maxLinMotorForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setMaxLinMotorForce(long objectId, float value);
|
private native void setMaxLinMotorForce(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the rotation motor is powered.
|
||||||
|
*
|
||||||
|
* @return true if powered, otherwise false
|
||||||
|
*/
|
||||||
public boolean isPoweredAngMotor() {
|
public boolean isPoweredAngMotor() {
|
||||||
return isPoweredAngMotor(objectId);
|
return isPoweredAngMotor(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native boolean isPoweredAngMotor(long objectId);
|
private native boolean isPoweredAngMotor(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether the rotation motor is powered.
|
||||||
|
*
|
||||||
|
* @param poweredAngMotor true to power the motor, false to de-power it
|
||||||
|
* (default=false)
|
||||||
|
*/
|
||||||
public void setPoweredAngMotor(boolean poweredAngMotor) {
|
public void setPoweredAngMotor(boolean poweredAngMotor) {
|
||||||
setPoweredAngMotor(objectId, poweredAngMotor);
|
setPoweredAngMotor(objectId, poweredAngMotor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setPoweredAngMotor(long objectId, boolean value);
|
private native void setPoweredAngMotor(long objectId, boolean value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the velocity target of the rotation motor.
|
||||||
|
*
|
||||||
|
* @return the velocity target (in radians per second)
|
||||||
|
*/
|
||||||
public float getTargetAngMotorVelocity() {
|
public float getTargetAngMotorVelocity() {
|
||||||
return getTargetAngMotorVelocity(objectId);
|
return getTargetAngMotorVelocity(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getTargetAngMotorVelocity(long objectId);
|
private native float getTargetAngMotorVelocity(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the velocity target of the rotation motor.
|
||||||
|
*
|
||||||
|
* @param targetAngMotorVelocity the desired velocity target (in radians per
|
||||||
|
* second, default=0)
|
||||||
|
*/
|
||||||
public void setTargetAngMotorVelocity(float targetAngMotorVelocity) {
|
public void setTargetAngMotorVelocity(float targetAngMotorVelocity) {
|
||||||
setTargetAngMotorVelocity(objectId, targetAngMotorVelocity);
|
setTargetAngMotorVelocity(objectId, targetAngMotorVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setTargetAngMotorVelocity(long objectId, float value);
|
private native void setTargetAngMotorVelocity(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the maximum force of the rotation motor.
|
||||||
|
*
|
||||||
|
* @return the maximum force
|
||||||
|
*/
|
||||||
public float getMaxAngMotorForce() {
|
public float getMaxAngMotorForce() {
|
||||||
return getMaxAngMotorForce(objectId);
|
return getMaxAngMotorForce(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMaxAngMotorForce(long objectId);
|
private native float getMaxAngMotorForce(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the maximum force of the rotation motor.
|
||||||
|
*
|
||||||
|
* @param maxAngMotorForce the desired maximum force (default=0)
|
||||||
|
*/
|
||||||
public void setMaxAngMotorForce(float maxAngMotorForce) {
|
public void setMaxAngMotorForce(float maxAngMotorForce) {
|
||||||
setMaxAngMotorForce(objectId, maxAngMotorForce);
|
setMaxAngMotorForce(objectId, maxAngMotorForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setMaxAngMotorForce(long objectId, float value);
|
private native void setMaxAngMotorForce(long objectId, float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this joint, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
@ -460,6 +796,12 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
capsule.write(useLinearReferenceFrameA, "useLinearReferenceFrameA", false);
|
capsule.write(useLinearReferenceFrameA, "useLinearReferenceFrameA", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this joint, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
super.read(im);
|
super.read(im);
|
||||||
@ -533,6 +875,9 @@ public class SliderJoint extends PhysicsJoint {
|
|||||||
setUpperLinLimit(upperLinLimit);
|
setUpperLinLimit(upperLinLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate the configured constraint in Bullet.
|
||||||
|
*/
|
||||||
protected void createJoint() {
|
protected void createJoint() {
|
||||||
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, rotA, pivotB, rotB, useLinearReferenceFrameA);
|
objectId = createJoint(nodeA.getObjectId(), nodeB.getObjectId(), pivotA, rotA, pivotB, rotB, useLinearReferenceFrameA);
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created Joint {0}", Long.toHexString(objectId));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,135 +32,253 @@
|
|||||||
package com.jme3.bullet.joints.motors;
|
package com.jme3.bullet.joints.motors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A motor based on Bullet's btRotationalLimitMotor. Motors are used to drive
|
||||||
|
* joints.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class RotationalLimitMotor {
|
public class RotationalLimitMotor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier of the btRotationalLimitMotor. The constructor sets
|
||||||
|
* this to a non-zero value.
|
||||||
|
*/
|
||||||
private long motorId = 0;
|
private long motorId = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a motor for the identified btRotationalLimitMotor.
|
||||||
|
*
|
||||||
|
* @param motor the unique identifier (not zero)
|
||||||
|
*/
|
||||||
public RotationalLimitMotor(long motor) {
|
public RotationalLimitMotor(long motor) {
|
||||||
this.motorId = motor;
|
this.motorId = motor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the id of the btRotationalLimitMotor.
|
||||||
|
*
|
||||||
|
* @return the identifier of the btRotationalLimitMotor (not zero)
|
||||||
|
*/
|
||||||
public long getMotor() {
|
public long getMotor() {
|
||||||
return motorId;
|
return motorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's constraint lower limit.
|
||||||
|
*
|
||||||
|
* @return the limit value
|
||||||
|
*/
|
||||||
public float getLoLimit() {
|
public float getLoLimit() {
|
||||||
return getLoLimit(motorId);
|
return getLoLimit(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLoLimit(long motorId);
|
private native float getLoLimit(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's constraint lower limit.
|
||||||
|
*
|
||||||
|
* @param loLimit the desired limit value
|
||||||
|
*/
|
||||||
public void setLoLimit(float loLimit) {
|
public void setLoLimit(float loLimit) {
|
||||||
setLoLimit(motorId, loLimit);
|
setLoLimit(motorId, loLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLoLimit(long motorId, float loLimit);
|
private native void setLoLimit(long motorId, float loLimit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's constraint upper limit.
|
||||||
|
*
|
||||||
|
* @return the limit value
|
||||||
|
*/
|
||||||
public float getHiLimit() {
|
public float getHiLimit() {
|
||||||
return getHiLimit(motorId);
|
return getHiLimit(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getHiLimit(long motorId);
|
private native float getHiLimit(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's constraint upper limit.
|
||||||
|
*
|
||||||
|
* @param hiLimit the desired limit value
|
||||||
|
*/
|
||||||
public void setHiLimit(float hiLimit) {
|
public void setHiLimit(float hiLimit) {
|
||||||
setHiLimit(motorId, hiLimit);
|
setHiLimit(motorId, hiLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setHiLimit(long motorId, float hiLimit);
|
private native void setHiLimit(long motorId, float hiLimit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's target velocity.
|
||||||
|
*
|
||||||
|
* @return the target velocity (in radians per second)
|
||||||
|
*/
|
||||||
public float getTargetVelocity() {
|
public float getTargetVelocity() {
|
||||||
return getTargetVelocity(motorId);
|
return getTargetVelocity(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getTargetVelocity(long motorId);
|
private native float getTargetVelocity(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's target velocity.
|
||||||
|
*
|
||||||
|
* @param targetVelocity the desired target velocity (in radians per second)
|
||||||
|
*/
|
||||||
public void setTargetVelocity(float targetVelocity) {
|
public void setTargetVelocity(float targetVelocity) {
|
||||||
setTargetVelocity(motorId, targetVelocity);
|
setTargetVelocity(motorId, targetVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setTargetVelocity(long motorId, float targetVelocity);
|
private native void setTargetVelocity(long motorId, float targetVelocity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's maximum force.
|
||||||
|
*
|
||||||
|
* @return the maximum force
|
||||||
|
*/
|
||||||
public float getMaxMotorForce() {
|
public float getMaxMotorForce() {
|
||||||
return getMaxMotorForce(motorId);
|
return getMaxMotorForce(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMaxMotorForce(long motorId);
|
private native float getMaxMotorForce(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's maximum force.
|
||||||
|
*
|
||||||
|
* @param maxMotorForce the desired maximum force on the motor
|
||||||
|
*/
|
||||||
public void setMaxMotorForce(float maxMotorForce) {
|
public void setMaxMotorForce(float maxMotorForce) {
|
||||||
setMaxMotorForce(motorId, maxMotorForce);
|
setMaxMotorForce(motorId, maxMotorForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setMaxMotorForce(long motorId, float maxMotorForce);
|
private native void setMaxMotorForce(long motorId, float maxMotorForce);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the limit's maximum force.
|
||||||
|
*
|
||||||
|
* @return the maximum force on the limit
|
||||||
|
*/
|
||||||
public float getMaxLimitForce() {
|
public float getMaxLimitForce() {
|
||||||
return getMaxLimitForce(motorId);
|
return getMaxLimitForce(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMaxLimitForce(long motorId);
|
private native float getMaxLimitForce(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the limit's maximum force.
|
||||||
|
*
|
||||||
|
* @param maxLimitForce the desired maximum force on the limit
|
||||||
|
*/
|
||||||
public void setMaxLimitForce(float maxLimitForce) {
|
public void setMaxLimitForce(float maxLimitForce) {
|
||||||
setMaxLimitForce(motorId, maxLimitForce);
|
setMaxLimitForce(motorId, maxLimitForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setMaxLimitForce(long motorId, float maxLimitForce);
|
private native void setMaxLimitForce(long motorId, float maxLimitForce);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's damping.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDamping() {
|
public float getDamping() {
|
||||||
return getDamping(motorId);
|
return getDamping(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDamping(long motorId);
|
private native float getDamping(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's damping.
|
||||||
|
*
|
||||||
|
* @param damping the desired viscous damping ratio (0→no damping,
|
||||||
|
* 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDamping(float damping) {
|
public void setDamping(float damping) {
|
||||||
setDamping(motorId, damping);
|
setDamping(motorId, damping);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDamping(long motorId, float damping);
|
private native void setDamping(long motorId, float damping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's limit softness.
|
||||||
|
*
|
||||||
|
* @return the limit softness
|
||||||
|
*/
|
||||||
public float getLimitSoftness() {
|
public float getLimitSoftness() {
|
||||||
return getLimitSoftness(motorId);
|
return getLimitSoftness(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLimitSoftness(long motorId);
|
private native float getLimitSoftness(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's limit softness.
|
||||||
|
*
|
||||||
|
* @param limitSoftness the desired limit softness
|
||||||
|
*/
|
||||||
public void setLimitSoftness(float limitSoftness) {
|
public void setLimitSoftness(float limitSoftness) {
|
||||||
setLimitSoftness(motorId, limitSoftness);
|
setLimitSoftness(motorId, limitSoftness);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLimitSoftness(long motorId, float limitSoftness);
|
private native void setLimitSoftness(long motorId, float limitSoftness);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's error tolerance at limits.
|
||||||
|
*
|
||||||
|
* @return the error tolerance (>0)
|
||||||
|
*/
|
||||||
public float getERP() {
|
public float getERP() {
|
||||||
return getERP(motorId);
|
return getERP(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getERP(long motorId);
|
private native float getERP(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's error tolerance at limits.
|
||||||
|
*
|
||||||
|
* @param ERP the desired error tolerance (>0)
|
||||||
|
*/
|
||||||
public void setERP(float ERP) {
|
public void setERP(float ERP) {
|
||||||
setERP(motorId, ERP);
|
setERP(motorId, ERP);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setERP(long motorId, float ERP);
|
private native void setERP(long motorId, float ERP);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's bounce.
|
||||||
|
*
|
||||||
|
* @return the bounce (restitution factor)
|
||||||
|
*/
|
||||||
public float getBounce() {
|
public float getBounce() {
|
||||||
return getBounce(motorId);
|
return getBounce(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getBounce(long motorId);
|
private native float getBounce(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's bounce.
|
||||||
|
*
|
||||||
|
* @param bounce the desired bounce (restitution factor)
|
||||||
|
*/
|
||||||
public void setBounce(float bounce) {
|
public void setBounce(float bounce) {
|
||||||
setBounce(motorId, bounce);
|
setBounce(motorId, bounce);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setBounce(long motorId, float limitSoftness);
|
private native void setBounce(long motorId, float limitSoftness);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this motor is enabled.
|
||||||
|
*
|
||||||
|
* @return true if enabled, otherwise false
|
||||||
|
*/
|
||||||
public boolean isEnableMotor() {
|
public boolean isEnableMotor() {
|
||||||
return isEnableMotor(motorId);
|
return isEnableMotor(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native boolean isEnableMotor(long motorId);
|
private native boolean isEnableMotor(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable this motor.
|
||||||
|
*
|
||||||
|
* @param enableMotor true→enable, false→disable
|
||||||
|
*/
|
||||||
public void setEnableMotor(boolean enableMotor) {
|
public void setEnableMotor(boolean enableMotor) {
|
||||||
setEnableMotor(motorId, enableMotor);
|
setEnableMotor(motorId, enableMotor);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,21 +34,42 @@ package com.jme3.bullet.joints.motors;
|
|||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A motor based on Bullet's btTranslationalLimitMotor. Motors are used to drive
|
||||||
|
* joints.
|
||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class TranslationalLimitMotor {
|
public class TranslationalLimitMotor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier of the btTranslationalLimitMotor. The constructor sets
|
||||||
|
* this to a non-zero value. After that, the id never changes.
|
||||||
|
*/
|
||||||
private long motorId = 0;
|
private long motorId = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a motor for the identified btTranslationalLimitMotor.
|
||||||
|
*
|
||||||
|
* @param motor the unique identifier (not zero)
|
||||||
|
*/
|
||||||
public TranslationalLimitMotor(long motor) {
|
public TranslationalLimitMotor(long motor) {
|
||||||
this.motorId = motor;
|
this.motorId = motor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the id of the btTranslationalLimitMotor.
|
||||||
|
*
|
||||||
|
* @return the unique identifier (not zero)
|
||||||
|
*/
|
||||||
public long getMotor() {
|
public long getMotor() {
|
||||||
return motorId;
|
return motorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this motor's constraint lower limits.
|
||||||
|
*
|
||||||
|
* @return a new vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getLowerLimit() {
|
public Vector3f getLowerLimit() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
getLowerLimit(motorId, vec);
|
getLowerLimit(motorId, vec);
|
||||||
@ -57,12 +78,22 @@ public class TranslationalLimitMotor {
|
|||||||
|
|
||||||
private native void getLowerLimit(long motorId, Vector3f vector);
|
private native void getLowerLimit(long motorId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the constraint lower limits.
|
||||||
|
*
|
||||||
|
* @param lowerLimit (unaffected, not null)
|
||||||
|
*/
|
||||||
public void setLowerLimit(Vector3f lowerLimit) {
|
public void setLowerLimit(Vector3f lowerLimit) {
|
||||||
setLowerLimit(motorId, lowerLimit);
|
setLowerLimit(motorId, lowerLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLowerLimit(long motorId, Vector3f vector);
|
private native void setLowerLimit(long motorId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this motor's constraint upper limits.
|
||||||
|
*
|
||||||
|
* @return a new vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getUpperLimit() {
|
public Vector3f getUpperLimit() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
getUpperLimit(motorId, vec);
|
getUpperLimit(motorId, vec);
|
||||||
@ -71,12 +102,22 @@ public class TranslationalLimitMotor {
|
|||||||
|
|
||||||
private native void getUpperLimit(long motorId, Vector3f vector);
|
private native void getUpperLimit(long motorId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the constraint upper limits.
|
||||||
|
*
|
||||||
|
* @param upperLimit (unaffected, not null)
|
||||||
|
*/
|
||||||
public void setUpperLimit(Vector3f upperLimit) {
|
public void setUpperLimit(Vector3f upperLimit) {
|
||||||
setUpperLimit(motorId, upperLimit);
|
setUpperLimit(motorId, upperLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setUpperLimit(long motorId, Vector3f vector);
|
private native void setUpperLimit(long motorId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the accumulated impulse.
|
||||||
|
*
|
||||||
|
* @return a new vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getAccumulatedImpulse() {
|
public Vector3f getAccumulatedImpulse() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
getAccumulatedImpulse(motorId, vec);
|
getAccumulatedImpulse(motorId, vec);
|
||||||
@ -85,42 +126,79 @@ public class TranslationalLimitMotor {
|
|||||||
|
|
||||||
private native void getAccumulatedImpulse(long motorId, Vector3f vector);
|
private native void getAccumulatedImpulse(long motorId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the accumulated impulse.
|
||||||
|
*
|
||||||
|
* @param accumulatedImpulse the desired vector (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setAccumulatedImpulse(Vector3f accumulatedImpulse) {
|
public void setAccumulatedImpulse(Vector3f accumulatedImpulse) {
|
||||||
setAccumulatedImpulse(motorId, accumulatedImpulse);
|
setAccumulatedImpulse(motorId, accumulatedImpulse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setAccumulatedImpulse(long motorId, Vector3f vector);
|
private native void setAccumulatedImpulse(long motorId, Vector3f vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's limit softness.
|
||||||
|
*
|
||||||
|
* @return the softness
|
||||||
|
*/
|
||||||
public float getLimitSoftness() {
|
public float getLimitSoftness() {
|
||||||
return getLimitSoftness(motorId);
|
return getLimitSoftness(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLimitSoftness(long motorId);
|
private native float getLimitSoftness(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the limit softness.
|
||||||
|
*
|
||||||
|
* @param limitSoftness the desired limit softness (default=0.5)
|
||||||
|
*/
|
||||||
public void setLimitSoftness(float limitSoftness) {
|
public void setLimitSoftness(float limitSoftness) {
|
||||||
setLimitSoftness(motorId, limitSoftness);
|
setLimitSoftness(motorId, limitSoftness);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLimitSoftness(long motorId, float limitSoftness);
|
private native void setLimitSoftness(long motorId, float limitSoftness);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's damping.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getDamping() {
|
public float getDamping() {
|
||||||
return getDamping(motorId);
|
return getDamping(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getDamping(long motorId);
|
private native float getDamping(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's damping.
|
||||||
|
*
|
||||||
|
* @param damping the desired viscous damping ratio (0→no damping,
|
||||||
|
* 1→critically damped, default=1)
|
||||||
|
*/
|
||||||
public void setDamping(float damping) {
|
public void setDamping(float damping) {
|
||||||
setDamping(motorId, damping);
|
setDamping(motorId, damping);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setDamping(long motorId, float damping);
|
private native void setDamping(long motorId, float damping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this motor's restitution.
|
||||||
|
*
|
||||||
|
* @return the restitution (bounce) factor
|
||||||
|
*/
|
||||||
public float getRestitution() {
|
public float getRestitution() {
|
||||||
return getRestitution(motorId);
|
return getRestitution(motorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getRestitution(long motorId);
|
private native float getRestitution(long motorId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this motor's restitution.
|
||||||
|
*
|
||||||
|
* @param restitution the desired restitution (bounce) factor
|
||||||
|
*/
|
||||||
public void setRestitution(float restitution) {
|
public void setRestitution(float restitution) {
|
||||||
setRestitution(motorId, restitution);
|
setRestitution(motorId, restitution);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -44,11 +44,19 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic Bullet Character
|
* A collision object for simplified character simulation, based on Bullet's
|
||||||
|
* btKinematicCharacterController.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsCharacter extends PhysicsCollisionObject {
|
public class PhysicsCharacter extends PhysicsCollisionObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier of btKinematicCharacterController (as opposed to its
|
||||||
|
* collision object, which is a ghost). Constructors are responsible for
|
||||||
|
* setting this to a non-zero value. The id might change if the character
|
||||||
|
* gets rebuilt.
|
||||||
|
*/
|
||||||
protected long characterId = 0;
|
protected long characterId = 0;
|
||||||
protected float stepHeight;
|
protected float stepHeight;
|
||||||
protected Vector3f walkDirection = new Vector3f();
|
protected Vector3f walkDirection = new Vector3f();
|
||||||
@ -59,12 +67,19 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
//TEMP VARIABLES
|
//TEMP VARIABLES
|
||||||
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public PhysicsCharacter() {
|
public PhysicsCharacter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param shape The CollisionShape (no Mesh or CompoundCollisionShapes)
|
* Instantiate a character with the specified collision shape and step
|
||||||
* @param stepHeight The quantization size for vertical movement
|
* height.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
* @param stepHeight the quantization size for vertical movement
|
||||||
*/
|
*/
|
||||||
public PhysicsCharacter(CollisionShape shape, float stepHeight) {
|
public PhysicsCharacter(CollisionShape shape, float stepHeight) {
|
||||||
this.collisionShape = shape;
|
this.collisionShape = shape;
|
||||||
@ -75,6 +90,9 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
buildObject();
|
buildObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the configured character in Bullet.
|
||||||
|
*/
|
||||||
protected void buildObject() {
|
protected void buildObject() {
|
||||||
if (objectId == 0) {
|
if (objectId == 0) {
|
||||||
objectId = createGhostObject();
|
objectId = createGhostObject();
|
||||||
@ -98,8 +116,9 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native long createCharacterObject(long objectId, long shapeId, float stepHeight);
|
private native long createCharacterObject(long objectId, long shapeId, float stepHeight);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the location of this physics character
|
* Directly alter the location of this character's center of mass.
|
||||||
* @param location
|
*
|
||||||
|
* @param location the desired physics location (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void warp(Vector3f location) {
|
public void warp(Vector3f location) {
|
||||||
warp(characterId, location);
|
warp(characterId, location);
|
||||||
@ -108,11 +127,11 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void warp(long characterId, Vector3f location);
|
private native void warp(long characterId, Vector3f location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the walk direction, works continuously.
|
* Alter the walk offset. The offset will continue to be applied until
|
||||||
* This should probably be called setPositionIncrementPerSimulatorStep.
|
* altered again.
|
||||||
* 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 desired position increment for each physics tick (not
|
||||||
* @param vec the walk direction to set
|
* null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setWalkDirection(Vector3f vec) {
|
public void setWalkDirection(Vector3f vec) {
|
||||||
walkDirection.set(vec);
|
walkDirection.set(vec);
|
||||||
@ -122,7 +141,9 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void setWalkDirection(long characterId, Vector3f vec);
|
private native void setWalkDirection(long characterId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the currently set walkDirection
|
* Access the walk offset.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public Vector3f getWalkDirection() {
|
public Vector3f getWalkDirection() {
|
||||||
return walkDirection;
|
return walkDirection;
|
||||||
@ -130,6 +151,7 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated in bullet 2.86.1 use setUp(Vector3f) instead
|
* @deprecated Deprecated in bullet 2.86.1 use setUp(Vector3f) instead
|
||||||
|
* @param axis which axis: 0→X, 1→Y, 2→Z
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setUpAxis(int axis) {
|
public void setUpAxis(int axis) {
|
||||||
@ -147,6 +169,11 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's "up" direction.
|
||||||
|
*
|
||||||
|
* @param axis the desired direction (not null, not zero, unaffected)
|
||||||
|
*/
|
||||||
public void setUp(Vector3f axis) {
|
public void setUp(Vector3f axis) {
|
||||||
setUp(characterId, axis);
|
setUp(characterId, axis);
|
||||||
}
|
}
|
||||||
@ -154,6 +181,11 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setUp(long characterId, Vector3f axis);
|
private native void setUp(long characterId, Vector3f axis);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's angular velocity.
|
||||||
|
*
|
||||||
|
* @param v the desired angular velocity vector (not null, unaffected)
|
||||||
|
*/
|
||||||
|
|
||||||
public void setAngularVelocity(Vector3f v){
|
public void setAngularVelocity(Vector3f v){
|
||||||
setAngularVelocity(characterId,v);
|
setAngularVelocity(characterId,v);
|
||||||
@ -161,7 +193,13 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setAngularVelocity(long characterId, Vector3f v);
|
private native void setAngularVelocity(long characterId, Vector3f v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this character's angular velocity.
|
||||||
|
*
|
||||||
|
* @param out storage for the result (modified if not null)
|
||||||
|
* @return the velocity vector (either the provided storage or a new vector,
|
||||||
|
* not null)
|
||||||
|
*/
|
||||||
public Vector3f getAngularVelocity(Vector3f out){
|
public Vector3f getAngularVelocity(Vector3f out){
|
||||||
if(out==null)out=new Vector3f();
|
if(out==null)out=new Vector3f();
|
||||||
getAngularVelocity(characterId,out);
|
getAngularVelocity(characterId,out);
|
||||||
@ -171,13 +209,23 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void getAngularVelocity(long characterId, Vector3f out);
|
private native void getAngularVelocity(long characterId, Vector3f out);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the linear velocity of this character's center of mass.
|
||||||
|
*
|
||||||
|
* @param v the desired velocity vector (not null)
|
||||||
|
*/
|
||||||
public void setLinearVelocity(Vector3f v){
|
public void setLinearVelocity(Vector3f v){
|
||||||
setLinearVelocity(characterId,v);
|
setLinearVelocity(characterId,v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLinearVelocity(long characterId, Vector3f v);
|
private native void setLinearVelocity(long characterId, Vector3f v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the linear velocity of this character's center of mass.
|
||||||
|
*
|
||||||
|
* @param out storage for the result (modified if not null)
|
||||||
|
* @return a vector (either the provided storage or a new vector, not null)
|
||||||
|
*/
|
||||||
public Vector3f getLinearVelocity(Vector3f out){
|
public Vector3f getLinearVelocity(Vector3f out){
|
||||||
if(out==null)out=new Vector3f();
|
if(out==null)out=new Vector3f();
|
||||||
getLinearVelocity(characterId,out);
|
getLinearVelocity(characterId,out);
|
||||||
@ -187,10 +235,20 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void getLinearVelocity(long characterId, Vector3f out);
|
private native void getLinearVelocity(long characterId, Vector3f out);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the index of the "up" axis.
|
||||||
|
*
|
||||||
|
* @return which axis: 0→X, 1→Y, 2→Z
|
||||||
|
*/
|
||||||
public int getUpAxis() {
|
public int getUpAxis() {
|
||||||
return upAxis;
|
return upAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's fall speed.
|
||||||
|
*
|
||||||
|
* @param fallSpeed the desired speed (default=55)
|
||||||
|
*/
|
||||||
public void setFallSpeed(float fallSpeed) {
|
public void setFallSpeed(float fallSpeed) {
|
||||||
this.fallSpeed = fallSpeed;
|
this.fallSpeed = fallSpeed;
|
||||||
setFallSpeed(characterId, fallSpeed);
|
setFallSpeed(characterId, fallSpeed);
|
||||||
@ -198,10 +256,20 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setFallSpeed(long characterId, float fallSpeed);
|
private native void setFallSpeed(long characterId, float fallSpeed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's fall speed.
|
||||||
|
*
|
||||||
|
* @return speed
|
||||||
|
*/
|
||||||
public float getFallSpeed() {
|
public float getFallSpeed() {
|
||||||
return fallSpeed;
|
return fallSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's jump speed.
|
||||||
|
*
|
||||||
|
* @param jumpSpeed the desired speed (default=10)
|
||||||
|
*/
|
||||||
public void setJumpSpeed(float jumpSpeed) {
|
public void setJumpSpeed(float jumpSpeed) {
|
||||||
this.jumpSpeed = jumpSpeed;
|
this.jumpSpeed = jumpSpeed;
|
||||||
setJumpSpeed(characterId, jumpSpeed);
|
setJumpSpeed(characterId, jumpSpeed);
|
||||||
@ -209,18 +277,30 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setJumpSpeed(long characterId, float jumpSpeed);
|
private native void setJumpSpeed(long characterId, float jumpSpeed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's jump speed.
|
||||||
|
*
|
||||||
|
* @return speed
|
||||||
|
*/
|
||||||
public float getJumpSpeed() {
|
public float getJumpSpeed() {
|
||||||
return jumpSpeed;
|
return jumpSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated in bullet 2.86.1. Use setGravity(Vector3f) instead.
|
* @deprecated Deprecated in bullet 2.86.1. Use setGravity(Vector3f) instead.
|
||||||
|
* @param value the desired upward component of the acceleration (typically
|
||||||
|
* negative)
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setGravity(float value) {
|
public void setGravity(float value) {
|
||||||
setGravity(new Vector3f(0,value,0));
|
setGravity(new Vector3f(0,value,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's gravitational acceleration.
|
||||||
|
*
|
||||||
|
* @param value the desired acceleration vector (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setGravity(Vector3f value) {
|
public void setGravity(Vector3f value) {
|
||||||
setGravity(characterId, value);
|
setGravity(characterId, value);
|
||||||
}
|
}
|
||||||
@ -229,12 +309,20 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated in bullet 2.86.1. Use getGravity(Vector3f) instead.
|
* @deprecated Deprecated in bullet 2.86.1. Use getGravity(Vector3f) instead.
|
||||||
|
* @return the upward component of the acceleration (typically negative)
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public float getGravity() {
|
public float getGravity() {
|
||||||
return getGravity(null).y;
|
return getGravity(null).y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this character's gravitational acceleration.
|
||||||
|
*
|
||||||
|
* @param out storage for the result (modified if not null)
|
||||||
|
* @return the acceleration vector (either the provided storage or a new
|
||||||
|
* vector, not null)
|
||||||
|
*/
|
||||||
public Vector3f getGravity(Vector3f out) {
|
public Vector3f getGravity(Vector3f out) {
|
||||||
if(out==null)out=new Vector3f();
|
if(out==null)out=new Vector3f();
|
||||||
getGravity(characterId,out);
|
getGravity(characterId,out);
|
||||||
@ -244,12 +332,24 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void getGravity(long characterId,Vector3f out);
|
private native void getGravity(long characterId,Vector3f out);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's linear damping.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getLinearDamping(){
|
public float getLinearDamping(){
|
||||||
return getLinearDamping(characterId);
|
return getLinearDamping(characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLinearDamping(long characterId);
|
private native float getLinearDamping(long characterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's linear damping.
|
||||||
|
*
|
||||||
|
* @param v the desired viscous damping ratio (0→no damping,
|
||||||
|
* 1→critically damped)
|
||||||
|
*/
|
||||||
|
|
||||||
public void setLinearDamping(float v ){
|
public void setLinearDamping(float v ){
|
||||||
setLinearDamping(characterId,v );
|
setLinearDamping(characterId,v );
|
||||||
@ -258,13 +358,24 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void setLinearDamping(long characterId,float v);
|
private native void setLinearDamping(long characterId,float v);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's angular damping.
|
||||||
|
*
|
||||||
|
* @return the viscous damping ratio (0→no damping, 1→critically
|
||||||
|
* damped)
|
||||||
|
*/
|
||||||
public float getAngularDamping(){
|
public float getAngularDamping(){
|
||||||
return getAngularDamping(characterId);
|
return getAngularDamping(characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getAngularDamping(long characterId);
|
private native float getAngularDamping(long characterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's angular damping.
|
||||||
|
*
|
||||||
|
* @param v the desired viscous damping ratio (0→no damping,
|
||||||
|
* 1→critically damped, default=0)
|
||||||
|
*/
|
||||||
public void setAngularDamping(float v ){
|
public void setAngularDamping(float v ){
|
||||||
setAngularDamping(characterId,v );
|
setAngularDamping(characterId,v );
|
||||||
}
|
}
|
||||||
@ -272,13 +383,22 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void setAngularDamping(long characterId,float v);
|
private native void setAngularDamping(long characterId,float v);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's step height.
|
||||||
|
*
|
||||||
|
* @return the height (in physics-space units)
|
||||||
|
*/
|
||||||
public float getStepHeight(){
|
public float getStepHeight(){
|
||||||
return getStepHeight(characterId);
|
return getStepHeight(characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getStepHeight(long characterId);
|
private native float getStepHeight(long characterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's step height.
|
||||||
|
*
|
||||||
|
* @param v the desired height (in physics-space units)
|
||||||
|
*/
|
||||||
public void setStepHeight(float v ){
|
public void setStepHeight(float v ){
|
||||||
setStepHeight(characterId,v );
|
setStepHeight(characterId,v );
|
||||||
}
|
}
|
||||||
@ -286,13 +406,22 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void setStepHeight(long characterId,float v);
|
private native void setStepHeight(long characterId,float v);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's maximum penetration depth.
|
||||||
|
*
|
||||||
|
* @return the depth (in physics-space units)
|
||||||
|
*/
|
||||||
public float getMaxPenetrationDepth(){
|
public float getMaxPenetrationDepth(){
|
||||||
return getMaxPenetrationDepth(characterId);
|
return getMaxPenetrationDepth(characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMaxPenetrationDepth(long characterId);
|
private native float getMaxPenetrationDepth(long characterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's maximum penetration depth.
|
||||||
|
*
|
||||||
|
* @param v the desired depth (in physics-space units)
|
||||||
|
*/
|
||||||
public void setMaxPenetrationDepth(float v ){
|
public void setMaxPenetrationDepth(float v ){
|
||||||
setMaxPenetrationDepth(characterId,v );
|
setMaxPenetrationDepth(characterId,v );
|
||||||
}
|
}
|
||||||
@ -303,18 +432,33 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's maximum slope angle.
|
||||||
|
*
|
||||||
|
* @param slopeRadians the desired angle (in radians)
|
||||||
|
*/
|
||||||
public void setMaxSlope(float slopeRadians) {
|
public void setMaxSlope(float slopeRadians) {
|
||||||
setMaxSlope(characterId, slopeRadians);
|
setMaxSlope(characterId, slopeRadians);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setMaxSlope(long characterId, float slopeRadians);
|
private native void setMaxSlope(long characterId, float slopeRadians);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this character's maximum slope angle.
|
||||||
|
*
|
||||||
|
* @return the angle (in radians)
|
||||||
|
*/
|
||||||
public float getMaxSlope() {
|
public float getMaxSlope() {
|
||||||
return getMaxSlope(characterId);
|
return getMaxSlope(characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getMaxSlope(long characterId);
|
private native float getMaxSlope(long characterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this character is on the ground.
|
||||||
|
*
|
||||||
|
* @return true if on the ground, otherwise false
|
||||||
|
*/
|
||||||
public boolean onGround() {
|
public boolean onGround() {
|
||||||
return onGround(characterId);
|
return onGround(characterId);
|
||||||
}
|
}
|
||||||
@ -330,12 +474,24 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jump in the specified direction.
|
||||||
|
*
|
||||||
|
* @param dir desired jump direction (not null, unaffected)
|
||||||
|
*/
|
||||||
public void jump(Vector3f dir) {
|
public void jump(Vector3f dir) {
|
||||||
jump(characterId,dir);
|
jump(characterId,dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void jump(long characterId,Vector3f v);
|
private native void jump(long characterId,Vector3f v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the specified CollisionShape to this character. Note that the
|
||||||
|
* character should not be in any physics space while changing shape; the
|
||||||
|
* character gets rebuilt on the physics side.
|
||||||
|
*
|
||||||
|
* @param collisionShape the shape to apply (not null, alias created)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setCollisionShape(CollisionShape collisionShape) {
|
public void setCollisionShape(CollisionShape collisionShape) {
|
||||||
// if (!(collisionShape.getObjectId() instanceof ConvexShape)) {
|
// if (!(collisionShape.getObjectId() instanceof ConvexShape)) {
|
||||||
@ -350,15 +506,21 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the physics location (same as warp())
|
* Directly alter this character's location. (Same as
|
||||||
* @param location the location of the actual physics object
|
* {@link #warp(com.jme3.math.Vector3f)}).)
|
||||||
|
*
|
||||||
|
* @param location the desired location (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsLocation(Vector3f location) {
|
public void setPhysicsLocation(Vector3f location) {
|
||||||
warp(location);
|
warp(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy the location of this character's center of mass.
|
||||||
|
*
|
||||||
|
* @param trans storage for the result (modified if not null)
|
||||||
|
* @return the location vector (either the provided storage or a new vector,
|
||||||
|
* not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getPhysicsLocation(Vector3f trans) {
|
public Vector3f getPhysicsLocation(Vector3f trans) {
|
||||||
if (trans == null) {
|
if (trans == null) {
|
||||||
@ -371,36 +533,72 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsLocation(long objectId, Vector3f vec);
|
private native void getPhysicsLocation(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy the location of this character's center of mass.
|
||||||
|
*
|
||||||
|
* @return a new location vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getPhysicsLocation() {
|
public Vector3f getPhysicsLocation() {
|
||||||
return getPhysicsLocation(null);
|
return getPhysicsLocation(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this character's continuous collision detection (CCD) swept sphere
|
||||||
|
* radius.
|
||||||
|
*
|
||||||
|
* @param radius (≥0, default=0)
|
||||||
|
*/
|
||||||
public void setCcdSweptSphereRadius(float radius) {
|
public void setCcdSweptSphereRadius(float radius) {
|
||||||
setCcdSweptSphereRadius(objectId, radius);
|
setCcdSweptSphereRadius(objectId, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setCcdSweptSphereRadius(long objectId, float radius);
|
private native void setCcdSweptSphereRadius(long objectId, float radius);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the amount of motion required to activate continuous collision
|
||||||
|
* detection (CCD).
|
||||||
|
* <p>
|
||||||
|
* This addresses the issue of fast objects passing through other objects
|
||||||
|
* with no collision detected.
|
||||||
|
*
|
||||||
|
* @param threshold the desired threshold velocity (>0) or zero to
|
||||||
|
* disable CCD (default=0)
|
||||||
|
*/
|
||||||
public void setCcdMotionThreshold(float threshold) {
|
public void setCcdMotionThreshold(float threshold) {
|
||||||
setCcdMotionThreshold(objectId, threshold);
|
setCcdMotionThreshold(objectId, threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setCcdMotionThreshold(long objectId, float threshold);
|
private native void setCcdMotionThreshold(long objectId, float threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of the sphere used for continuous collision detection
|
||||||
|
* (CCD).
|
||||||
|
*
|
||||||
|
* @return radius (≥0)
|
||||||
|
*/
|
||||||
public float getCcdSweptSphereRadius() {
|
public float getCcdSweptSphereRadius() {
|
||||||
return getCcdSweptSphereRadius(objectId);
|
return getCcdSweptSphereRadius(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdSweptSphereRadius(long objectId);
|
private native float getCcdSweptSphereRadius(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate this character's continuous collision detection (CCD) motion
|
||||||
|
* threshold.
|
||||||
|
*
|
||||||
|
* @return the threshold velocity (≥0)
|
||||||
|
*/
|
||||||
public float getCcdMotionThreshold() {
|
public float getCcdMotionThreshold() {
|
||||||
return getCcdMotionThreshold(objectId);
|
return getCcdMotionThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdMotionThreshold(long objectId);
|
private native float getCcdMotionThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the square of this character's continuous collision detection
|
||||||
|
* (CCD) motion threshold.
|
||||||
|
*
|
||||||
|
* @return the threshold velocity squared (≥0)
|
||||||
|
*/
|
||||||
public float getCcdSquareMotionThreshold() {
|
public float getCcdSquareMotionThreshold() {
|
||||||
return getCcdSquareMotionThreshold(objectId);
|
return getCcdSquareMotionThreshold(objectId);
|
||||||
}
|
}
|
||||||
@ -409,14 +607,25 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* used internally
|
* used internally
|
||||||
|
*
|
||||||
|
* @return the Bullet id
|
||||||
*/
|
*/
|
||||||
public long getControllerId() {
|
public long getControllerId() {
|
||||||
return characterId;
|
return characterId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has no effect.
|
||||||
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this character, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param e exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter e) throws IOException {
|
public void write(JmeExporter e) throws IOException {
|
||||||
super.write(e);
|
super.write(e);
|
||||||
@ -432,6 +641,13 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f());
|
capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this character from the specified importer, for example when
|
||||||
|
* loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param e importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
super.read(e);
|
super.read(e);
|
||||||
@ -448,6 +664,12 @@ public class PhysicsCharacter extends PhysicsCollisionObject {
|
|||||||
setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f()));
|
setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this physics character just before it is destroyed. Should be
|
||||||
|
* invoked only by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -48,11 +48,14 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A collision object for intangibles, based on Bullet's
|
||||||
|
* btPairCachingGhostObject. This is useful for creating a character controller,
|
||||||
|
* collision sensors/triggers, explosions etc.
|
||||||
|
* <p>
|
||||||
* <i>From Bullet manual:</i><br>
|
* <i>From Bullet manual:</i><br>
|
||||||
* GhostObject can keep track of all objects that are overlapping.
|
* btGhostObject is a special btCollisionObject, useful for fast localized
|
||||||
* By default, this overlap is based on the AABB.
|
* collision queries.
|
||||||
* This is useful for creating a character controller,
|
*
|
||||||
* collision sensors/triggers, explosions etc.<br>
|
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsGhostObject extends PhysicsCollisionObject {
|
public class PhysicsGhostObject extends PhysicsCollisionObject {
|
||||||
@ -61,9 +64,18 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||||
private List<PhysicsCollisionObject> overlappingObjects = new LinkedList<PhysicsCollisionObject>();
|
private List<PhysicsCollisionObject> overlappingObjects = new LinkedList<PhysicsCollisionObject>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public PhysicsGhostObject() {
|
public PhysicsGhostObject() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate an object with the specified collision shape.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
*/
|
||||||
public PhysicsGhostObject(CollisionShape shape) {
|
public PhysicsGhostObject(CollisionShape shape) {
|
||||||
collisionShape = shape;
|
collisionShape = shape;
|
||||||
buildObject();
|
buildObject();
|
||||||
@ -74,6 +86,9 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
buildObject();
|
buildObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the configured object in Bullet.
|
||||||
|
*/
|
||||||
protected void buildObject() {
|
protected void buildObject() {
|
||||||
if (objectId == 0) {
|
if (objectId == 0) {
|
||||||
// gObject = new PairCachingGhostObject();
|
// gObject = new PairCachingGhostObject();
|
||||||
@ -93,6 +108,13 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setGhostFlags(long objectId);
|
private native void setGhostFlags(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the specified CollisionShape to this object. Note that the object
|
||||||
|
* should not be in any physics space while changing shape; the object gets
|
||||||
|
* rebuilt on the physics side.
|
||||||
|
*
|
||||||
|
* @param collisionShape the shape to apply (not null, alias created)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setCollisionShape(CollisionShape collisionShape) {
|
public void setCollisionShape(CollisionShape collisionShape) {
|
||||||
super.setCollisionShape(collisionShape);
|
super.setCollisionShape(collisionShape);
|
||||||
@ -104,8 +126,9 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics object location
|
* Directly alter the location of this object's center.
|
||||||
* @param location the location of the actual physics object
|
*
|
||||||
|
* @param location the desired location (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsLocation(Vector3f location) {
|
public void setPhysicsLocation(Vector3f location) {
|
||||||
setPhysicsLocation(objectId, location);
|
setPhysicsLocation(objectId, location);
|
||||||
@ -114,8 +137,10 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native void setPhysicsLocation(long objectId, Vector3f location);
|
private native void setPhysicsLocation(long objectId, Vector3f location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics object rotation
|
* Directly alter this object's orientation.
|
||||||
* @param rotation the rotation of the actual physics object
|
*
|
||||||
|
* @param rotation the desired orientation (rotation matrix, not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsRotation(Matrix3f rotation) {
|
public void setPhysicsRotation(Matrix3f rotation) {
|
||||||
setPhysicsRotation(objectId, rotation);
|
setPhysicsRotation(objectId, rotation);
|
||||||
@ -124,8 +149,10 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native void setPhysicsRotation(long objectId, Matrix3f rotation);
|
private native void setPhysicsRotation(long objectId, Matrix3f rotation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics object rotation
|
* Directly alter this object's orientation.
|
||||||
* @param rotation the rotation of the actual physics object
|
*
|
||||||
|
* @param rotation the desired orientation (quaternion, not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsRotation(Quaternion rotation) {
|
public void setPhysicsRotation(Quaternion rotation) {
|
||||||
setPhysicsRotation(objectId, rotation);
|
setPhysicsRotation(objectId, rotation);
|
||||||
@ -134,7 +161,11 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native void setPhysicsRotation(long objectId, Quaternion rotation);
|
private native void setPhysicsRotation(long objectId, Quaternion rotation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy the location of this object's center.
|
||||||
|
*
|
||||||
|
* @param trans storage for the result (modified if not null)
|
||||||
|
* @return the physics location (either the provided storage or a new
|
||||||
|
* vector, not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getPhysicsLocation(Vector3f trans) {
|
public Vector3f getPhysicsLocation(Vector3f trans) {
|
||||||
if (trans == null) {
|
if (trans == null) {
|
||||||
@ -147,7 +178,11 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsLocation(long objectId, Vector3f vector);
|
private native void getPhysicsLocation(long objectId, Vector3f vector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy this object's orientation to a quaternion.
|
||||||
|
*
|
||||||
|
* @param rot storage for the result (modified if not null)
|
||||||
|
* @return the physics orientation (either the provided storage or a new
|
||||||
|
* quaternion, not null)
|
||||||
*/
|
*/
|
||||||
public Quaternion getPhysicsRotation(Quaternion rot) {
|
public Quaternion getPhysicsRotation(Quaternion rot) {
|
||||||
if (rot == null) {
|
if (rot == null) {
|
||||||
@ -160,7 +195,11 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsRotation(long objectId, Quaternion rot);
|
private native void getPhysicsRotation(long objectId, Quaternion rot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy this object's orientation to a matrix.
|
||||||
|
*
|
||||||
|
* @param rot storage for the result (modified if not null)
|
||||||
|
* @return the orientation (either the provided storage or a new matrix, not
|
||||||
|
* null)
|
||||||
*/
|
*/
|
||||||
public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
|
public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
|
||||||
if (rot == null) {
|
if (rot == null) {
|
||||||
@ -173,7 +212,9 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot);
|
private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy the location of this object's center.
|
||||||
|
*
|
||||||
|
* @return a new location vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getPhysicsLocation() {
|
public Vector3f getPhysicsLocation() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
@ -182,7 +223,9 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy this object's orientation to a quaternion.
|
||||||
|
*
|
||||||
|
* @return a new quaternion (not null)
|
||||||
*/
|
*/
|
||||||
public Quaternion getPhysicsRotation() {
|
public Quaternion getPhysicsRotation() {
|
||||||
Quaternion quat = new Quaternion();
|
Quaternion quat = new Quaternion();
|
||||||
@ -190,6 +233,11 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
return quat;
|
return quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this object's orientation to a matrix.
|
||||||
|
*
|
||||||
|
* @return a new matrix (not null)
|
||||||
|
*/
|
||||||
public Matrix3f getPhysicsRotationMatrix() {
|
public Matrix3f getPhysicsRotationMatrix() {
|
||||||
Matrix3f mtx = new Matrix3f();
|
Matrix3f mtx = new Matrix3f();
|
||||||
getPhysicsRotationMatrix(objectId, mtx);
|
getPhysicsRotationMatrix(objectId, mtx);
|
||||||
@ -203,16 +251,18 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
// return gObject;
|
// return gObject;
|
||||||
// }
|
// }
|
||||||
/**
|
/**
|
||||||
* destroys this PhysicsGhostNode and removes it from memory
|
* Has no effect.
|
||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Another Object is overlapping with this GhostNode,
|
* Access a list of overlapping objects.
|
||||||
* if and if only there CollisionShapes overlaps.
|
* <p>
|
||||||
* They could be both regular PhysicsRigidBodys or PhysicsGhostObjects.
|
* Another object overlaps with this one if and if only their
|
||||||
* @return All CollisionObjects overlapping with this GhostNode.
|
* CollisionShapes overlap.
|
||||||
|
*
|
||||||
|
* @return an internal list which may get reused (not null)
|
||||||
*/
|
*/
|
||||||
public List<PhysicsCollisionObject> getOverlappingObjects() {
|
public List<PhysicsCollisionObject> getOverlappingObjects() {
|
||||||
overlappingObjects.clear();
|
overlappingObjects.clear();
|
||||||
@ -225,13 +275,19 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
protected native void getOverlappingObjects(long objectId);
|
protected native void getOverlappingObjects(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is invoked from native code.
|
||||||
|
*
|
||||||
|
* @param co the collision object to add
|
||||||
|
*/
|
||||||
private void addOverlappingObject_native(PhysicsCollisionObject co) {
|
private void addOverlappingObject_native(PhysicsCollisionObject co) {
|
||||||
overlappingObjects.add(co);
|
overlappingObjects.add(co);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Count how many CollisionObjects this object overlaps.
|
||||||
*
|
*
|
||||||
* @return With how many other CollisionObjects this GhostNode is currently overlapping.
|
* @return count (≥0)
|
||||||
*/
|
*/
|
||||||
public int getOverlappingCount() {
|
public int getOverlappingCount() {
|
||||||
return getOverlappingCount(objectId);
|
return getOverlappingCount(objectId);
|
||||||
@ -240,44 +296,84 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
private native int getOverlappingCount(long objectId);
|
private native int getOverlappingCount(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Access an overlapping collision object by its position in the list.
|
||||||
*
|
*
|
||||||
* @param index The index of the overlapping Node to retrieve.
|
* @param index which list position (≥0, <count)
|
||||||
* @return The Overlapping CollisionObject at the given index.
|
* @return the pre-existing object
|
||||||
*/
|
*/
|
||||||
public PhysicsCollisionObject getOverlapping(int index) {
|
public PhysicsCollisionObject getOverlapping(int index) {
|
||||||
return overlappingObjects.get(index);
|
return overlappingObjects.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the continuous collision detection (CCD) swept sphere radius for
|
||||||
|
* this object.
|
||||||
|
*
|
||||||
|
* @param radius (≥0)
|
||||||
|
*/
|
||||||
public void setCcdSweptSphereRadius(float radius) {
|
public void setCcdSweptSphereRadius(float radius) {
|
||||||
setCcdSweptSphereRadius(objectId, radius);
|
setCcdSweptSphereRadius(objectId, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setCcdSweptSphereRadius(long objectId, float radius);
|
private native void setCcdSweptSphereRadius(long objectId, float radius);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the amount of motion required to trigger continuous collision
|
||||||
|
* detection (CCD).
|
||||||
|
* <p>
|
||||||
|
* This addresses the issue of fast objects passing through other objects
|
||||||
|
* with no collision detected.
|
||||||
|
*
|
||||||
|
* @param threshold the desired threshold value (squared velocity, >0) or
|
||||||
|
* zero to disable CCD (default=0)
|
||||||
|
*/
|
||||||
public void setCcdMotionThreshold(float threshold) {
|
public void setCcdMotionThreshold(float threshold) {
|
||||||
setCcdMotionThreshold(objectId, threshold);
|
setCcdMotionThreshold(objectId, threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setCcdMotionThreshold(long objectId, float threshold);
|
private native void setCcdMotionThreshold(long objectId, float threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of the sphere used for continuous collision detection
|
||||||
|
* (CCD).
|
||||||
|
*
|
||||||
|
* @return radius (≥0)
|
||||||
|
*/
|
||||||
public float getCcdSweptSphereRadius() {
|
public float getCcdSweptSphereRadius() {
|
||||||
return getCcdSweptSphereRadius(objectId);
|
return getCcdSweptSphereRadius(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdSweptSphereRadius(long objectId);
|
private native float getCcdSweptSphereRadius(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the continuous collision detection (CCD) motion threshold for this
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @return threshold value (squared velocity, ≥0)
|
||||||
|
*/
|
||||||
public float getCcdMotionThreshold() {
|
public float getCcdMotionThreshold() {
|
||||||
return getCcdMotionThreshold(objectId);
|
return getCcdMotionThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdMotionThreshold(long objectId);
|
private native float getCcdMotionThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the CCD square motion threshold for this object.
|
||||||
|
*
|
||||||
|
* @return threshold value (≥0)
|
||||||
|
*/
|
||||||
public float getCcdSquareMotionThreshold() {
|
public float getCcdSquareMotionThreshold() {
|
||||||
return getCcdSquareMotionThreshold(objectId);
|
return getCcdSquareMotionThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdSquareMotionThreshold(long objectId);
|
private native float getCcdSquareMotionThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this object, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param e exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter e) throws IOException {
|
public void write(JmeExporter e) throws IOException {
|
||||||
super.write(e);
|
super.write(e);
|
||||||
@ -288,6 +384,13 @@ public class PhysicsGhostObject extends PhysicsCollisionObject {
|
|||||||
capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0);
|
capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this object from the specified importer, for example when
|
||||||
|
* loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param e importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
super.read(e);
|
super.read(e);
|
||||||
|
@ -51,29 +51,56 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>PhysicsRigidBody - Basic physics object</p>
|
* A collision object for a rigid body, based on Bullet's btRigidBody.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsRigidBody extends PhysicsCollisionObject {
|
public class PhysicsRigidBody extends PhysicsCollisionObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* motion state
|
||||||
|
*/
|
||||||
protected RigidBodyMotionState motionState = new RigidBodyMotionState();
|
protected RigidBodyMotionState motionState = new RigidBodyMotionState();
|
||||||
|
/**
|
||||||
|
* copy of mass (>0) of a dynamic body, or 0 for a static body
|
||||||
|
* (default=1)
|
||||||
|
*/
|
||||||
protected float mass = 1.0f;
|
protected float mass = 1.0f;
|
||||||
|
/**
|
||||||
|
* copy of kinematic flag: true→set kinematic mode (spatial controls
|
||||||
|
* body), false→dynamic/static mode (body controls spatial)
|
||||||
|
* (default=false)
|
||||||
|
*/
|
||||||
protected boolean kinematic = false;
|
protected boolean kinematic = false;
|
||||||
|
/**
|
||||||
|
* joint list
|
||||||
|
*/
|
||||||
protected ArrayList<PhysicsJoint> joints = new ArrayList<PhysicsJoint>();
|
protected ArrayList<PhysicsJoint> joints = new ArrayList<PhysicsJoint>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public PhysicsRigidBody() {
|
public PhysicsRigidBody() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PhysicsRigidBody with the supplied collision shape
|
* Instantiate a dynamic body with mass=1 and the specified collision shape.
|
||||||
* @param child
|
*
|
||||||
* @param shape
|
* @param shape the desired shape (not null, alias created)
|
||||||
*/
|
*/
|
||||||
public PhysicsRigidBody(CollisionShape shape) {
|
public PhysicsRigidBody(CollisionShape shape) {
|
||||||
collisionShape = shape;
|
collisionShape = shape;
|
||||||
rebuildRigidBody();
|
rebuildRigidBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a body with the specified collision shape and mass.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
* @param mass if 0, a static body is created; otherwise a dynamic body is
|
||||||
|
* created (≥0)
|
||||||
|
*/
|
||||||
public PhysicsRigidBody(CollisionShape shape, float mass) {
|
public PhysicsRigidBody(CollisionShape shape, float mass) {
|
||||||
collisionShape = shape;
|
collisionShape = shape;
|
||||||
this.mass = mass;
|
this.mass = mass;
|
||||||
@ -81,7 +108,7 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds/rebuilds the phyiscs body when parameters have changed
|
* Build/rebuild this body after parameters have changed.
|
||||||
*/
|
*/
|
||||||
protected void rebuildRigidBody() {
|
protected void rebuildRigidBody() {
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
@ -105,11 +132,17 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use by subclasses.
|
||||||
|
*/
|
||||||
protected void preRebuild() {
|
protected void preRebuild() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private native long createRigidBody(float mass, long motionStateId, long collisionShapeId);
|
private native long createRigidBody(float mass, long motionStateId, long collisionShapeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use by subclasses.
|
||||||
|
*/
|
||||||
protected void postRebuild() {
|
protected void postRebuild() {
|
||||||
if (mass == 0.0f) {
|
if (mass == 0.0f) {
|
||||||
setStatic(objectId, true);
|
setStatic(objectId, true);
|
||||||
@ -120,12 +153,19 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the motionState
|
* Access this body's motion state.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public RigidBodyMotionState getMotionState() {
|
public RigidBodyMotionState getMotionState() {
|
||||||
return motionState;
|
return motionState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this body is in a physics space.
|
||||||
|
*
|
||||||
|
* @return true→in a space, false→not in a space
|
||||||
|
*/
|
||||||
public boolean isInWorld() {
|
public boolean isInWorld() {
|
||||||
return isInWorld(objectId);
|
return isInWorld(objectId);
|
||||||
}
|
}
|
||||||
@ -133,8 +173,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native boolean isInWorld(long objectId);
|
private native boolean isInWorld(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics object location
|
* Directly alter the location of this body's center of mass.
|
||||||
* @param location the location of the actual physics object
|
*
|
||||||
|
* @param location the desired location (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsLocation(Vector3f location) {
|
public void setPhysicsLocation(Vector3f location) {
|
||||||
setPhysicsLocation(objectId, location);
|
setPhysicsLocation(objectId, location);
|
||||||
@ -143,8 +184,10 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setPhysicsLocation(long objectId, Vector3f location);
|
private native void setPhysicsLocation(long objectId, Vector3f location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics object rotation
|
* Directly alter this body's orientation.
|
||||||
* @param rotation the rotation of the actual physics object
|
*
|
||||||
|
* @param rotation the desired orientation (rotation matrix, not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsRotation(Matrix3f rotation) {
|
public void setPhysicsRotation(Matrix3f rotation) {
|
||||||
setPhysicsRotation(objectId, rotation);
|
setPhysicsRotation(objectId, rotation);
|
||||||
@ -153,8 +196,10 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setPhysicsRotation(long objectId, Matrix3f rotation);
|
private native void setPhysicsRotation(long objectId, Matrix3f rotation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics object rotation
|
* Directly alter this body's orientation.
|
||||||
* @param rotation the rotation of the actual physics object
|
*
|
||||||
|
* @param rotation the desired orientation (quaternion, not null,
|
||||||
|
* unaffected)
|
||||||
*/
|
*/
|
||||||
public void setPhysicsRotation(Quaternion rotation) {
|
public void setPhysicsRotation(Quaternion rotation) {
|
||||||
setPhysicsRotation(objectId, rotation);
|
setPhysicsRotation(objectId, rotation);
|
||||||
@ -163,7 +208,11 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setPhysicsRotation(long objectId, Quaternion rotation);
|
private native void setPhysicsRotation(long objectId, Quaternion rotation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy the location of this body's center of mass.
|
||||||
|
*
|
||||||
|
* @param trans storage for the result (modified if not null)
|
||||||
|
* @return the location (either the provided storage or a new vector, not
|
||||||
|
* null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getPhysicsLocation(Vector3f trans) {
|
public Vector3f getPhysicsLocation(Vector3f trans) {
|
||||||
if (trans == null) {
|
if (trans == null) {
|
||||||
@ -176,7 +225,11 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsLocation(long objectId, Vector3f vector);
|
private native void getPhysicsLocation(long objectId, Vector3f vector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy this body's orientation to a quaternion.
|
||||||
|
*
|
||||||
|
* @param rot storage for the result (modified if not null)
|
||||||
|
* @return the orientation (either the provided storage or a new quaternion,
|
||||||
|
* not null)
|
||||||
*/
|
*/
|
||||||
public Quaternion getPhysicsRotation(Quaternion rot) {
|
public Quaternion getPhysicsRotation(Quaternion rot) {
|
||||||
if (rot == null) {
|
if (rot == null) {
|
||||||
@ -185,12 +238,23 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
getPhysicsRotation(objectId, rot);
|
getPhysicsRotation(objectId, rot);
|
||||||
return rot;
|
return rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the principal components of the local inertia tensor.
|
||||||
|
*
|
||||||
|
* @param gravity (not null, unaffected)
|
||||||
|
*/
|
||||||
public void setInverseInertiaLocal(Vector3f gravity) {
|
public void setInverseInertiaLocal(Vector3f gravity) {
|
||||||
setInverseInertiaLocal(objectId, gravity);
|
setInverseInertiaLocal(objectId, gravity);
|
||||||
}
|
}
|
||||||
private native void setInverseInertiaLocal(long objectId, Vector3f gravity);
|
private native void setInverseInertiaLocal(long objectId, Vector3f gravity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the principal components of the local inverse inertia tensor.
|
||||||
|
*
|
||||||
|
* @param trans storage for the result (modified if not null)
|
||||||
|
* @return a vector (either the provided storage or a new vector, not null)
|
||||||
|
*/
|
||||||
public Vector3f getInverseInertiaLocal(Vector3f trans) {
|
public Vector3f getInverseInertiaLocal(Vector3f trans) {
|
||||||
if (trans == null) {
|
if (trans == null) {
|
||||||
trans = new Vector3f();
|
trans = new Vector3f();
|
||||||
@ -204,7 +268,11 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsRotation(long objectId, Quaternion rot);
|
private native void getPhysicsRotation(long objectId, Quaternion rot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy this body's orientation to a matrix.
|
||||||
|
*
|
||||||
|
* @param rot storage for the result (modified if not null)
|
||||||
|
* @return the orientation (either the provided storage or a new matrix, not
|
||||||
|
* null)
|
||||||
*/
|
*/
|
||||||
public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
|
public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
|
||||||
if (rot == null) {
|
if (rot == null) {
|
||||||
@ -217,7 +285,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot);
|
private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy the location of this body's center of mass.
|
||||||
|
*
|
||||||
|
* @return a new location vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getPhysicsLocation() {
|
public Vector3f getPhysicsLocation() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
@ -226,7 +296,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the physicsLocation
|
* Copy this body's orientation to a quaternion.
|
||||||
|
*
|
||||||
|
* @return a new quaternion (not null)
|
||||||
*/
|
*/
|
||||||
public Quaternion getPhysicsRotation() {
|
public Quaternion getPhysicsRotation() {
|
||||||
Quaternion quat = new Quaternion();
|
Quaternion quat = new Quaternion();
|
||||||
@ -234,6 +306,11 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
return quat;
|
return quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this body's orientation to a matrix.
|
||||||
|
*
|
||||||
|
* @return a new matrix (not null)
|
||||||
|
*/
|
||||||
public Matrix3f getPhysicsRotationMatrix() {
|
public Matrix3f getPhysicsRotationMatrix() {
|
||||||
Matrix3f mtx = new Matrix3f();
|
Matrix3f mtx = new Matrix3f();
|
||||||
getPhysicsRotationMatrix(objectId, mtx);
|
getPhysicsRotationMatrix(objectId, mtx);
|
||||||
@ -264,10 +341,14 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
// return Converter.convert(tempTrans.basis, rotation);
|
// return Converter.convert(tempTrans.basis, rotation);
|
||||||
// }
|
// }
|
||||||
/**
|
/**
|
||||||
* Sets the node to kinematic mode. in this mode the node is not affected by physics
|
* Put this body into kinematic mode or take it out of kinematic mode.
|
||||||
* but affects other physics objects. Its kinetic force is calculated by the amount
|
* <p>
|
||||||
* of movement it is exposed to and its weight.
|
* In kinematic mode, the body is not influenced by physics but can affect
|
||||||
* @param kinematic
|
* other physics objects. Its kinetic force is calculated based on its
|
||||||
|
* movement and weight.
|
||||||
|
*
|
||||||
|
* @param kinematic true→set kinematic mode, false→set
|
||||||
|
* dynamic/static mode (default=false)
|
||||||
*/
|
*/
|
||||||
public void setKinematic(boolean kinematic) {
|
public void setKinematic(boolean kinematic) {
|
||||||
this.kinematic = kinematic;
|
this.kinematic = kinematic;
|
||||||
@ -276,10 +357,25 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setKinematic(long objectId, boolean kinematic);
|
private native void setKinematic(long objectId, boolean kinematic);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this body is in kinematic mode.
|
||||||
|
* <p>
|
||||||
|
* In kinematic mode, the body is not influenced by physics but can affect
|
||||||
|
* other physics objects. Its kinetic force is calculated based on its
|
||||||
|
* movement and weight.
|
||||||
|
*
|
||||||
|
* @return true if in kinematic mode, otherwise false (dynamic/static mode)
|
||||||
|
*/
|
||||||
public boolean isKinematic() {
|
public boolean isKinematic() {
|
||||||
return kinematic;
|
return kinematic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the radius of the swept sphere used for continuous collision
|
||||||
|
* detection (CCD).
|
||||||
|
*
|
||||||
|
* @param radius the desired radius (≥0, default=0)
|
||||||
|
*/
|
||||||
public void setCcdSweptSphereRadius(float radius) {
|
public void setCcdSweptSphereRadius(float radius) {
|
||||||
setCcdSweptSphereRadius(objectId, radius);
|
setCcdSweptSphereRadius(objectId, radius);
|
||||||
}
|
}
|
||||||
@ -287,9 +383,14 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setCcdSweptSphereRadius(long objectId, float radius);
|
private native void setCcdSweptSphereRadius(long objectId, float radius);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the amount of motion that has to happen in one physics tick to trigger the continuous motion detection<br/>
|
* Alter the amount of motion required to activate continuous collision
|
||||||
* This avoids the problem of fast objects moving through other objects, set to zero to disable (default)
|
* detection (CCD).
|
||||||
* @param threshold
|
* <p>
|
||||||
|
* This addresses the issue of fast objects passing through other objects
|
||||||
|
* with no collision detected.
|
||||||
|
*
|
||||||
|
* @param threshold the desired threshold velocity (>0) or zero to
|
||||||
|
* disable CCD (default=0)
|
||||||
*/
|
*/
|
||||||
public void setCcdMotionThreshold(float threshold) {
|
public void setCcdMotionThreshold(float threshold) {
|
||||||
setCcdMotionThreshold(objectId, threshold);
|
setCcdMotionThreshold(objectId, threshold);
|
||||||
@ -297,31 +398,56 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setCcdMotionThreshold(long objectId, float threshold);
|
private native void setCcdMotionThreshold(long objectId, float threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of the swept sphere used for continuous collision
|
||||||
|
* detection (CCD).
|
||||||
|
*
|
||||||
|
* @return radius (≥0)
|
||||||
|
*/
|
||||||
public float getCcdSweptSphereRadius() {
|
public float getCcdSweptSphereRadius() {
|
||||||
return getCcdSweptSphereRadius(objectId);
|
return getCcdSweptSphereRadius(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdSweptSphereRadius(long objectId);
|
private native float getCcdSweptSphereRadius(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate this body's continuous collision detection (CCD) motion
|
||||||
|
* threshold.
|
||||||
|
*
|
||||||
|
* @return the threshold velocity (≥0)
|
||||||
|
*/
|
||||||
public float getCcdMotionThreshold() {
|
public float getCcdMotionThreshold() {
|
||||||
return getCcdMotionThreshold(objectId);
|
return getCcdMotionThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdMotionThreshold(long objectId);
|
private native float getCcdMotionThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the square of this body's continuous collision detection (CCD)
|
||||||
|
* motion threshold.
|
||||||
|
*
|
||||||
|
* @return the threshold velocity squared (≥0)
|
||||||
|
*/
|
||||||
public float getCcdSquareMotionThreshold() {
|
public float getCcdSquareMotionThreshold() {
|
||||||
return getCcdSquareMotionThreshold(objectId);
|
return getCcdSquareMotionThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getCcdSquareMotionThreshold(long objectId);
|
private native float getCcdSquareMotionThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's mass.
|
||||||
|
*
|
||||||
|
* @return the mass (>0) or zero for a static body
|
||||||
|
*/
|
||||||
public float getMass() {
|
public float getMass() {
|
||||||
return mass;
|
return mass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the mass of this PhysicsRigidBody, objects with mass=0 are static.
|
* Alter this body's mass. Bodies with mass=0 are static. For dynamic
|
||||||
* @param mass
|
* bodies, it is best to keep the mass around 1.
|
||||||
|
*
|
||||||
|
* @param mass the desired mass (>0) or 0 for a static body (default=1)
|
||||||
*/
|
*/
|
||||||
public void setMass(float mass) {
|
public void setMass(float mass) {
|
||||||
this.mass = mass;
|
this.mass = mass;
|
||||||
@ -344,10 +470,22 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native long updateMassProps(long objectId, long collisionShapeId, float mass);
|
private native long updateMassProps(long objectId, long collisionShapeId, float mass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this body's gravitational acceleration.
|
||||||
|
*
|
||||||
|
* @return a new acceleration vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getGravity() {
|
public Vector3f getGravity() {
|
||||||
return getGravity(null);
|
return getGravity(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this body's gravitational acceleration.
|
||||||
|
*
|
||||||
|
* @param gravity storage for the result (modified if not null)
|
||||||
|
* @return an acceleration vector (either the provided storage or a new
|
||||||
|
* vector, not null)
|
||||||
|
*/
|
||||||
public Vector3f getGravity(Vector3f gravity) {
|
public Vector3f getGravity(Vector3f gravity) {
|
||||||
if (gravity == null) {
|
if (gravity == null) {
|
||||||
gravity = new Vector3f();
|
gravity = new Vector3f();
|
||||||
@ -359,16 +497,23 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void getGravity(long objectId, Vector3f gravity);
|
private native void getGravity(long objectId, Vector3f gravity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the local gravity of this PhysicsRigidBody<br/>
|
* Alter this body's gravitational acceleration.
|
||||||
* Set this after adding the node to the PhysicsSpace,
|
* <p>
|
||||||
* the PhysicsSpace assigns its current gravity to the physics node when its added.
|
* Invoke this after adding the body to a PhysicsSpace. Adding a body to a
|
||||||
* @param gravity the gravity vector to set
|
* PhysicsSpace alters its gravity.
|
||||||
|
*
|
||||||
|
* @param gravity the desired acceleration vector (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setGravity(Vector3f gravity) {
|
public void setGravity(Vector3f gravity) {
|
||||||
setGravity(objectId, gravity);
|
setGravity(objectId, gravity);
|
||||||
}
|
}
|
||||||
private native void setGravity(long objectId, Vector3f gravity);
|
private native void setGravity(long objectId, Vector3f gravity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's friction.
|
||||||
|
*
|
||||||
|
* @return friction value
|
||||||
|
*/
|
||||||
public float getFriction() {
|
public float getFriction() {
|
||||||
return getFriction(objectId);
|
return getFriction(objectId);
|
||||||
}
|
}
|
||||||
@ -376,8 +521,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native float getFriction(long objectId);
|
private native float getFriction(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the friction of this physics object
|
* Alter this body's friction.
|
||||||
* @param friction the friction of this physics object
|
*
|
||||||
|
* @param friction the desired friction value (default=0.5)
|
||||||
*/
|
*/
|
||||||
public void setFriction(float friction) {
|
public void setFriction(float friction) {
|
||||||
setFriction(objectId, friction);
|
setFriction(objectId, friction);
|
||||||
@ -385,6 +531,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setFriction(long objectId, float friction);
|
private native void setFriction(long objectId, float friction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's damping.
|
||||||
|
*
|
||||||
|
* @param linearDamping the desired linear damping value (default=0)
|
||||||
|
* @param angularDamping the desired angular damping value (default=0)
|
||||||
|
*/
|
||||||
public void setDamping(float linearDamping, float angularDamping) {
|
public void setDamping(float linearDamping, float angularDamping) {
|
||||||
setDamping(objectId, linearDamping, angularDamping);
|
setDamping(objectId, linearDamping, angularDamping);
|
||||||
}
|
}
|
||||||
@ -400,27 +552,52 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
//
|
//
|
||||||
// private native void setRestitution(long objectId, float factor);
|
// private native void setRestitution(long objectId, float factor);
|
||||||
//
|
//
|
||||||
|
/**
|
||||||
|
* Alter this body's linear damping.
|
||||||
|
*
|
||||||
|
* @param linearDamping the desired linear damping value (default=0)
|
||||||
|
*/
|
||||||
public void setLinearDamping(float linearDamping) {
|
public void setLinearDamping(float linearDamping) {
|
||||||
setDamping(objectId, linearDamping, getAngularDamping());
|
setDamping(objectId, linearDamping, getAngularDamping());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's angular damping.
|
||||||
|
*
|
||||||
|
* @param angularDamping the desired angular damping value (default=0)
|
||||||
|
*/
|
||||||
public void setAngularDamping(float angularDamping) {
|
public void setAngularDamping(float angularDamping) {
|
||||||
setAngularDamping(objectId, angularDamping);
|
setAngularDamping(objectId, angularDamping);
|
||||||
}
|
}
|
||||||
private native void setAngularDamping(long objectId, float factor);
|
private native void setAngularDamping(long objectId, float factor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's linear damping.
|
||||||
|
*
|
||||||
|
* @return damping value
|
||||||
|
*/
|
||||||
public float getLinearDamping() {
|
public float getLinearDamping() {
|
||||||
return getLinearDamping(objectId);
|
return getLinearDamping(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLinearDamping(long objectId);
|
private native float getLinearDamping(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's angular damping.
|
||||||
|
*
|
||||||
|
* @return damping value
|
||||||
|
*/
|
||||||
public float getAngularDamping() {
|
public float getAngularDamping() {
|
||||||
return getAngularDamping(objectId);
|
return getAngularDamping(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getAngularDamping(long objectId);
|
private native float getAngularDamping(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's restitution (bounciness).
|
||||||
|
*
|
||||||
|
* @return restitution value
|
||||||
|
*/
|
||||||
public float getRestitution() {
|
public float getRestitution() {
|
||||||
return getRestitution(objectId);
|
return getRestitution(objectId);
|
||||||
}
|
}
|
||||||
@ -428,8 +605,10 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native float getRestitution(long objectId);
|
private native float getRestitution(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "bouncyness" of the PhysicsRigidBody, best performance if restitution=0
|
* Alter this body's restitution (bounciness). For best performance, set
|
||||||
* @param restitution
|
* restitution=0.
|
||||||
|
*
|
||||||
|
* @param restitution the desired value (default=0)
|
||||||
*/
|
*/
|
||||||
public void setRestitution(float restitution) {
|
public void setRestitution(float restitution) {
|
||||||
setRestitution(objectId, restitution);
|
setRestitution(objectId, restitution);
|
||||||
@ -438,8 +617,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setRestitution(long objectId, float factor);
|
private native void setRestitution(long objectId, float factor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current angular velocity of this PhysicsRigidBody
|
* Copy this body's angular velocity.
|
||||||
* @return the current linear velocity
|
*
|
||||||
|
* @return a new velocity vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getAngularVelocity() {
|
public Vector3f getAngularVelocity() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
@ -450,16 +630,18 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void getAngularVelocity(long objectId, Vector3f vec);
|
private native void getAngularVelocity(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current angular velocity of this PhysicsRigidBody
|
* Copy this body's angular velocity.
|
||||||
* @param vec the vector to store the velocity in
|
*
|
||||||
|
* @param vec storage for the result (not null, modified)
|
||||||
*/
|
*/
|
||||||
public void getAngularVelocity(Vector3f vec) {
|
public void getAngularVelocity(Vector3f vec) {
|
||||||
getAngularVelocity(objectId, vec);
|
getAngularVelocity(objectId, vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the angular velocity of this PhysicsRigidBody
|
* Alter this body's angular velocity.
|
||||||
* @param vec the angular velocity of this PhysicsRigidBody
|
*
|
||||||
|
* @param vec the desired angular velocity vector (not null, unaffected)
|
||||||
*/
|
*/
|
||||||
public void setAngularVelocity(Vector3f vec) {
|
public void setAngularVelocity(Vector3f vec) {
|
||||||
setAngularVelocity(objectId, vec);
|
setAngularVelocity(objectId, vec);
|
||||||
@ -469,8 +651,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setAngularVelocity(long objectId, Vector3f vec);
|
private native void setAngularVelocity(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current linear velocity of this PhysicsRigidBody
|
* Copy the linear velocity of this body's center of mass.
|
||||||
* @return the current linear velocity
|
*
|
||||||
|
* @return a new velocity vector (not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getLinearVelocity() {
|
public Vector3f getLinearVelocity() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
@ -481,16 +664,18 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void getLinearVelocity(long objectId, Vector3f vec);
|
private native void getLinearVelocity(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current linear velocity of this PhysicsRigidBody
|
* Copy the linear velocity of this body's center of mass.
|
||||||
* @param vec the vector to store the velocity in
|
*
|
||||||
|
* @param vec storage for the result (not null, modified)
|
||||||
*/
|
*/
|
||||||
public void getLinearVelocity(Vector3f vec) {
|
public void getLinearVelocity(Vector3f vec) {
|
||||||
getLinearVelocity(objectId, vec);
|
getLinearVelocity(objectId, vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the linear velocity of this PhysicsRigidBody
|
* Alter the linear velocity of this body's center of mass.
|
||||||
* @param vec the linear velocity of this PhysicsRigidBody
|
*
|
||||||
|
* @param vec the desired velocity vector (not null)
|
||||||
*/
|
*/
|
||||||
public void setLinearVelocity(Vector3f vec) {
|
public void setLinearVelocity(Vector3f vec) {
|
||||||
setLinearVelocity(objectId, vec);
|
setLinearVelocity(objectId, vec);
|
||||||
@ -500,9 +685,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setLinearVelocity(long objectId, Vector3f vec);
|
private native void setLinearVelocity(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a force to the PhysicsRigidBody, only applies force if the next physics update call
|
* Apply a force to the PhysicsRigidBody. Effective only if the next physics
|
||||||
* updates the physics space.<br>
|
* update steps the physics space.
|
||||||
* To apply an impulse, use applyImpulse, use applyContinuousForce to apply continuous force.
|
* <p>
|
||||||
|
* To apply an impulse, use applyImpulse, use applyContinuousForce to apply
|
||||||
|
* continuous force.
|
||||||
|
*
|
||||||
* @param force the force
|
* @param force the force
|
||||||
* @param location the location of the force
|
* @param location the location of the force
|
||||||
*/
|
*/
|
||||||
@ -514,10 +702,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void applyForce(long objectId, Vector3f force, Vector3f location);
|
private native void applyForce(long objectId, Vector3f force, Vector3f location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a force to the PhysicsRigidBody, only applies force if the next physics update call
|
* Apply a force to the PhysicsRigidBody. Effective only if the next physics
|
||||||
* updates the physics space.<br>
|
* update steps the physics space.
|
||||||
* To apply an impulse, use applyImpulse.
|
* <p>
|
||||||
*
|
* To apply an impulse, use
|
||||||
|
* {@link #applyImpulse(com.jme3.math.Vector3f, com.jme3.math.Vector3f)}.
|
||||||
|
*
|
||||||
* @param force the force
|
* @param force the force
|
||||||
*/
|
*/
|
||||||
public void applyCentralForce(Vector3f force) {
|
public void applyCentralForce(Vector3f force) {
|
||||||
@ -528,10 +718,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void applyCentralForce(long objectId, Vector3f force);
|
private native void applyCentralForce(long objectId, Vector3f force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a force to the PhysicsRigidBody, only applies force if the next physics update call
|
* Apply a force to the PhysicsRigidBody. Effective only if the next physics
|
||||||
* updates the physics space.<br>
|
* update steps the physics space.
|
||||||
* To apply an impulse, use applyImpulse.
|
* <p>
|
||||||
*
|
* To apply an impulse, use
|
||||||
|
* {@link #applyImpulse(com.jme3.math.Vector3f, com.jme3.math.Vector3f)}.
|
||||||
|
*
|
||||||
* @param torque the torque
|
* @param torque the torque
|
||||||
*/
|
*/
|
||||||
public void applyTorque(Vector3f torque) {
|
public void applyTorque(Vector3f torque) {
|
||||||
@ -542,7 +734,8 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void applyTorque(long objectId, Vector3f vec);
|
private native void applyTorque(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an impulse to the PhysicsRigidBody in the next physics update.
|
* Apply an impulse to the body the next physics update.
|
||||||
|
*
|
||||||
* @param impulse applied impulse
|
* @param impulse applied impulse
|
||||||
* @param rel_pos location relative to object
|
* @param rel_pos location relative to object
|
||||||
*/
|
*/
|
||||||
@ -554,8 +747,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void applyImpulse(long objectId, Vector3f impulse, Vector3f rel_pos);
|
private native void applyImpulse(long objectId, Vector3f impulse, Vector3f rel_pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a torque impulse to the PhysicsRigidBody in the next physics update.
|
* Apply a torque impulse to the body in the next physics update.
|
||||||
* @param vec
|
*
|
||||||
|
* @param vec the torque to apply
|
||||||
*/
|
*/
|
||||||
public void applyTorqueImpulse(Vector3f vec) {
|
public void applyTorqueImpulse(Vector3f vec) {
|
||||||
applyTorqueImpulse(objectId, vec);
|
applyTorqueImpulse(objectId, vec);
|
||||||
@ -565,8 +759,7 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void applyTorqueImpulse(long objectId, Vector3f vec);
|
private native void applyTorqueImpulse(long objectId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all forces from the PhysicsRigidBody
|
* Clear all forces acting on this body.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void clearForces() {
|
public void clearForces() {
|
||||||
clearForces(objectId);
|
clearForces(objectId);
|
||||||
@ -574,6 +767,14 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void clearForces(long objectId);
|
private native void clearForces(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the specified CollisionShape to this body.
|
||||||
|
* <p>
|
||||||
|
* Note that the body should not be in any physics space while changing
|
||||||
|
* shape; the body gets rebuilt on the physics side.
|
||||||
|
*
|
||||||
|
* @param collisionShape the shape to apply (not null, alias created)
|
||||||
|
*/
|
||||||
public void setCollisionShape(CollisionShape collisionShape) {
|
public void setCollisionShape(CollisionShape collisionShape) {
|
||||||
super.setCollisionShape(collisionShape);
|
super.setCollisionShape(collisionShape);
|
||||||
if (collisionShape instanceof MeshCollisionShape && mass != 0) {
|
if (collisionShape instanceof MeshCollisionShape && mass != 0) {
|
||||||
@ -590,7 +791,7 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native void setCollisionShape(long objectId, long collisionShapeId);
|
private native void setCollisionShape(long objectId, long collisionShapeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reactivates this PhysicsRigidBody when it has been deactivated because it was not moving
|
* Reactivates this body if it has been deactivated due to lack of motion.
|
||||||
*/
|
*/
|
||||||
public void activate() {
|
public void activate() {
|
||||||
activate(objectId);
|
activate(objectId);
|
||||||
@ -598,6 +799,11 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void activate(long objectId);
|
private native void activate(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this body has been deactivated due to lack of motion.
|
||||||
|
*
|
||||||
|
* @return true if still active, false if deactivated
|
||||||
|
*/
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return isActive(objectId);
|
return isActive(objectId);
|
||||||
}
|
}
|
||||||
@ -605,10 +811,13 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native boolean isActive(long objectId);
|
private native boolean isActive(long objectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the sleeping thresholds, these define when the object gets deactivated
|
* Alter this body's sleeping thresholds.
|
||||||
* to save ressources. Low values keep the object active when it barely moves
|
* <p>
|
||||||
* @param linear the linear sleeping threshold
|
* These thresholds determine when the body can be deactivated to save
|
||||||
* @param angular the angular sleeping threshold
|
* resources. Low values keep the body active when it barely moves.
|
||||||
|
*
|
||||||
|
* @param linear the desired linear sleeping threshold (≥0, default=0.8)
|
||||||
|
* @param angular the desired angular sleeping threshold (≥0, default=1)
|
||||||
*/
|
*/
|
||||||
public void setSleepingThresholds(float linear, float angular) {
|
public void setSleepingThresholds(float linear, float angular) {
|
||||||
setSleepingThresholds(objectId, linear, angular);
|
setSleepingThresholds(objectId, linear, angular);
|
||||||
@ -616,36 +825,67 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void setSleepingThresholds(long objectId, float linear, float angular);
|
private native void setSleepingThresholds(long objectId, float linear, float angular);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's linear sleeping threshold.
|
||||||
|
*
|
||||||
|
* @param linearSleepingThreshold the desired threshold (≥0, default=0.8)
|
||||||
|
*/
|
||||||
public void setLinearSleepingThreshold(float linearSleepingThreshold) {
|
public void setLinearSleepingThreshold(float linearSleepingThreshold) {
|
||||||
setLinearSleepingThreshold(objectId, linearSleepingThreshold);
|
setLinearSleepingThreshold(objectId, linearSleepingThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setLinearSleepingThreshold(long objectId, float linearSleepingThreshold);
|
private native void setLinearSleepingThreshold(long objectId, float linearSleepingThreshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's angular sleeping threshold.
|
||||||
|
*
|
||||||
|
* @param angularSleepingThreshold the desired threshold (≥0, default=1)
|
||||||
|
*/
|
||||||
public void setAngularSleepingThreshold(float angularSleepingThreshold) {
|
public void setAngularSleepingThreshold(float angularSleepingThreshold) {
|
||||||
setAngularSleepingThreshold(objectId, angularSleepingThreshold);
|
setAngularSleepingThreshold(objectId, angularSleepingThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setAngularSleepingThreshold(long objectId, float angularSleepingThreshold);
|
private native void setAngularSleepingThreshold(long objectId, float angularSleepingThreshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's linear sleeping threshold.
|
||||||
|
*
|
||||||
|
* @return the linear sleeping threshold (≥0)
|
||||||
|
*/
|
||||||
public float getLinearSleepingThreshold() {
|
public float getLinearSleepingThreshold() {
|
||||||
return getLinearSleepingThreshold(objectId);
|
return getLinearSleepingThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getLinearSleepingThreshold(long objectId);
|
private native float getLinearSleepingThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this body's angular sleeping threshold.
|
||||||
|
*
|
||||||
|
* @return the angular sleeping threshold (≥0)
|
||||||
|
*/
|
||||||
public float getAngularSleepingThreshold() {
|
public float getAngularSleepingThreshold() {
|
||||||
return getAngularSleepingThreshold(objectId);
|
return getAngularSleepingThreshold(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getAngularSleepingThreshold(long objectId);
|
private native float getAngularSleepingThreshold(long objectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the X-component of this body's angular factor.
|
||||||
|
*
|
||||||
|
* @return the X-component of the angular factor
|
||||||
|
*/
|
||||||
public float getAngularFactor() {
|
public float getAngularFactor() {
|
||||||
return getAngularFactor(null).getX();
|
return getAngularFactor(null).getX();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this body's angular factors.
|
||||||
|
*
|
||||||
|
* @param store storage for the result (modified if not null)
|
||||||
|
* @return a vector (either the provided storage or a new vector, not null)
|
||||||
|
*/
|
||||||
public Vector3f getAngularFactor(Vector3f store) {
|
public Vector3f getAngularFactor(Vector3f store) {
|
||||||
// doing like this prevent from breaking the API
|
// Done this way to prevent breaking the API.
|
||||||
if (store == null) {
|
if (store == null) {
|
||||||
store = new Vector3f();
|
store = new Vector3f();
|
||||||
}
|
}
|
||||||
@ -655,16 +895,33 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void getAngularFactor(long objectId, Vector3f vec);
|
private native void getAngularFactor(long objectId, Vector3f vec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's angular factor.
|
||||||
|
*
|
||||||
|
* @param factor the desired angular factor for all axes (not null,
|
||||||
|
* unaffected, default=1)
|
||||||
|
*/
|
||||||
public void setAngularFactor(float factor) {
|
public void setAngularFactor(float factor) {
|
||||||
setAngularFactor(objectId, new Vector3f(factor, factor, factor));
|
setAngularFactor(objectId, new Vector3f(factor, factor, factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's angular factors.
|
||||||
|
*
|
||||||
|
* @param factor the desired angular factor for each axis (not null,
|
||||||
|
* unaffected, default=(1,1,1))
|
||||||
|
*/
|
||||||
public void setAngularFactor(Vector3f factor) {
|
public void setAngularFactor(Vector3f factor) {
|
||||||
setAngularFactor(objectId, factor);
|
setAngularFactor(objectId, factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setAngularFactor(long objectId, Vector3f factor);
|
private native void setAngularFactor(long objectId, Vector3f factor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy this body's linear factors.
|
||||||
|
*
|
||||||
|
* @return a new vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getLinearFactor() {
|
public Vector3f getLinearFactor() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
getLinearFactor(objectId, vec);
|
getLinearFactor(objectId, vec);
|
||||||
@ -673,6 +930,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
private native void getLinearFactor(long objectId, Vector3f vec);
|
private native void getLinearFactor(long objectId, Vector3f vec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter this body's linear factors.
|
||||||
|
*
|
||||||
|
* @param factor the desired linear factor for each axis (not null,
|
||||||
|
* unaffected, default=(1,1,1))
|
||||||
|
*/
|
||||||
public void setLinearFactor(Vector3f factor) {
|
public void setLinearFactor(Vector3f factor) {
|
||||||
setLinearFactor(objectId, factor);
|
setLinearFactor(objectId, factor);
|
||||||
}
|
}
|
||||||
@ -681,7 +944,9 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do not use manually, joints are added automatically
|
* Do not invoke directly! Joints are added automatically when created.
|
||||||
|
*
|
||||||
|
* @param joint the joint to add (not null)
|
||||||
*/
|
*/
|
||||||
public void addJoint(PhysicsJoint joint) {
|
public void addJoint(PhysicsJoint joint) {
|
||||||
if (!joints.contains(joint)) {
|
if (!joints.contains(joint)) {
|
||||||
@ -690,21 +955,32 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Do not invoke directly! Joints are removed automatically when destroyed.
|
||||||
|
*
|
||||||
|
* @param joint the joint to remove (not null)
|
||||||
*/
|
*/
|
||||||
public void removeJoint(PhysicsJoint joint) {
|
public void removeJoint(PhysicsJoint joint) {
|
||||||
joints.remove(joint);
|
joints.remove(joint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of connected joints. This list is only filled when
|
* Access the list of joints connected with this body.
|
||||||
* the PhysicsRigidBody is actually added to the physics space or loaded from disk.
|
* <p>
|
||||||
* @return list of active joints connected to this PhysicsRigidBody
|
* This list is only filled when the PhysicsRigidBody is added to a physics
|
||||||
|
* space.
|
||||||
|
*
|
||||||
|
* @return the pre-existing list (not null)
|
||||||
*/
|
*/
|
||||||
public List<PhysicsJoint> getJoints() {
|
public List<PhysicsJoint> getJoints() {
|
||||||
return joints;
|
return joints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this body, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param e exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter e) throws IOException {
|
public void write(JmeExporter e) throws IOException {
|
||||||
super.write(e);
|
super.write(e);
|
||||||
@ -738,6 +1014,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
capsule.writeSavableArrayList(joints, "joints", null);
|
capsule.writeSavableArrayList(joints, "joints", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this body, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param e importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
super.read(e);
|
super.read(e);
|
||||||
|
@ -46,34 +46,68 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>PhysicsVehicleNode - Special PhysicsNode that implements vehicle functions</p>
|
* A collision object for simplified vehicle simulation based on Bullet's
|
||||||
|
* btRaycastVehicle.
|
||||||
* <p>
|
* <p>
|
||||||
* <i>From bullet manual:</i><br>
|
* <i>From Bullet manual:</i><br>
|
||||||
* For most vehicle simulations, it is recommended to use the simplified Bullet
|
* For arcade style vehicle simulations, it is recommended to use the simplified
|
||||||
* vehicle model as provided in btRaycastVehicle. Instead of simulation each wheel
|
* Bullet vehicle model as provided in btRaycastVehicle. Instead of simulation
|
||||||
* and chassis as separate rigid bodies, connected by constraints, it uses a simplified model.
|
* each wheel and chassis as separate rigid bodies, connected by constraints, it
|
||||||
* This simplified model has many benefits, and is widely used in commercial driving games.<br>
|
* uses a simplified model. This simplified model has many benefits, and is
|
||||||
* The entire vehicle is represented as a single rigidbody, the chassis.
|
* widely used in commercial driving games.
|
||||||
* The collision detection of the wheels is approximated by ray casts,
|
* <p>
|
||||||
* and the tire friction is a basic anisotropic friction model.
|
* The entire vehicle is represented as a single rigidbody, the chassis. The
|
||||||
* </p>
|
* collision detection of the wheels is approximated by ray casts, and the tire
|
||||||
|
* friction is a basic anisotropic friction model.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class PhysicsVehicle extends PhysicsRigidBody {
|
public class PhysicsVehicle extends PhysicsRigidBody {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier of the btRaycastVehicle. The constructor sets this to a
|
||||||
|
* non-zero value.
|
||||||
|
*/
|
||||||
protected long vehicleId = 0;
|
protected long vehicleId = 0;
|
||||||
|
/**
|
||||||
|
* Unique identifier of the ray caster.
|
||||||
|
*/
|
||||||
protected long rayCasterId = 0;
|
protected long rayCasterId = 0;
|
||||||
|
/**
|
||||||
|
* tuning parameters
|
||||||
|
*/
|
||||||
protected VehicleTuning tuning = new VehicleTuning();
|
protected VehicleTuning tuning = new VehicleTuning();
|
||||||
|
/**
|
||||||
|
* list of wheels
|
||||||
|
*/
|
||||||
protected ArrayList<VehicleWheel> wheels = new ArrayList<VehicleWheel>();
|
protected ArrayList<VehicleWheel> wheels = new ArrayList<VehicleWheel>();
|
||||||
|
/**
|
||||||
|
* physics space where this vehicle is added, or null if none
|
||||||
|
*/
|
||||||
protected PhysicsSpace physicsSpace;
|
protected PhysicsSpace physicsSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public PhysicsVehicle() {
|
public PhysicsVehicle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a vehicle with the specified collision shape and mass=1.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
*/
|
||||||
public PhysicsVehicle(CollisionShape shape) {
|
public PhysicsVehicle(CollisionShape shape) {
|
||||||
super(shape);
|
super(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a vehicle with the specified collision shape and mass.
|
||||||
|
*
|
||||||
|
* @param shape the desired shape (not null, alias created)
|
||||||
|
* @param mass (>0)
|
||||||
|
*/
|
||||||
public PhysicsVehicle(CollisionShape shape, float mass) {
|
public PhysicsVehicle(CollisionShape shape, float mass) {
|
||||||
super(shape, mass);
|
super(shape, mass);
|
||||||
}
|
}
|
||||||
@ -111,7 +145,10 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally, creates the actual vehicle constraint when vehicle is added to phyicsspace
|
* Used internally, creates the actual vehicle constraint when vehicle is
|
||||||
|
* added to physics space.
|
||||||
|
*
|
||||||
|
* @param space which physics space
|
||||||
*/
|
*/
|
||||||
public void createVehicle(PhysicsSpace space) {
|
public void createVehicle(PhysicsSpace space) {
|
||||||
physicsSpace = space;
|
physicsSpace = space;
|
||||||
@ -145,14 +182,20 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
private native int addWheel(long objectId, Vector3f location, Vector3f direction, Vector3f axle, float restLength, float radius, VehicleTuning tuning, boolean frontWheel);
|
private native int addWheel(long objectId, Vector3f location, Vector3f direction, Vector3f axle, float restLength, float radius, VehicleTuning tuning, boolean frontWheel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a wheel to this vehicle
|
* Add a wheel to this vehicle.
|
||||||
* @param connectionPoint The starting point of the ray, where the suspension connects to the chassis (chassis space)
|
*
|
||||||
* @param direction the direction of the wheel (should be -Y / 0,-1,0 for a normal car)
|
* @param connectionPoint the location where the suspension connects to the
|
||||||
* @param axle The axis of the wheel, pointing right in vehicle direction (should be -X / -1,0,0 for a normal car)
|
* chassis (in chassis coordinates, not null, unaffected)
|
||||||
* @param suspensionRestLength The current length of the suspension (metres)
|
* @param direction the suspension direction (in chassis coordinates, not
|
||||||
* @param wheelRadius the wheel radius
|
* null, unaffected, typically down/0,-1,0)
|
||||||
* @param isFrontWheel sets if this wheel is a front wheel (steering)
|
* @param axle the axis direction (in chassis coordinates, not null,
|
||||||
* @return the PhysicsVehicleWheel object to get/set infos on the wheel
|
* unaffected, typically -1,0,0)
|
||||||
|
* @param suspensionRestLength the rest length of the suspension (in
|
||||||
|
* physics-space units)
|
||||||
|
* @param wheelRadius the wheel radius (in physics-space units, >0)
|
||||||
|
* @param isFrontWheel true→front (steering) wheel,
|
||||||
|
* false→non-front wheel
|
||||||
|
* @return a new VehicleWheel for access (not null)
|
||||||
*/
|
*/
|
||||||
public VehicleWheel addWheel(Vector3f connectionPoint, Vector3f direction, Vector3f axle, float suspensionRestLength, float wheelRadius, boolean isFrontWheel) {
|
public VehicleWheel addWheel(Vector3f connectionPoint, Vector3f direction, Vector3f axle, float suspensionRestLength, float wheelRadius, boolean isFrontWheel) {
|
||||||
return addWheel(null, connectionPoint, direction, axle, suspensionRestLength, wheelRadius, isFrontWheel);
|
return addWheel(null, connectionPoint, direction, axle, suspensionRestLength, wheelRadius, isFrontWheel);
|
||||||
@ -160,14 +203,20 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a wheel to this vehicle
|
* Add a wheel to this vehicle
|
||||||
* @param spat the wheel Geometry
|
*
|
||||||
* @param connectionPoint The starting point of the ray, where the suspension connects to the chassis (chassis space)
|
* @param spat the associated spatial, or null if none
|
||||||
* @param direction the direction of the wheel (should be -Y / 0,-1,0 for a normal car)
|
* @param connectionPoint the location where the suspension connects to the
|
||||||
* @param axle The axis of the wheel, pointing right in vehicle direction (should be -X / -1,0,0 for a normal car)
|
* chassis (in chassis coordinates, not null, unaffected)
|
||||||
* @param suspensionRestLength The current length of the suspension (metres)
|
* @param direction the suspension direction (in chassis coordinates, not
|
||||||
* @param wheelRadius the wheel radius
|
* null, unaffected, typically down/0,-1,0)
|
||||||
* @param isFrontWheel sets if this wheel is a front wheel (steering)
|
* @param axle the axis direction (in chassis coordinates, not null,
|
||||||
* @return the PhysicsVehicleWheel object to get/set infos on the wheel
|
* unaffected, typically -1,0,0)
|
||||||
|
* @param suspensionRestLength the rest length of the suspension (in
|
||||||
|
* physics-space units)
|
||||||
|
* @param wheelRadius the wheel radius (in physics-space units, >0)
|
||||||
|
* @param isFrontWheel true→front (steering) wheel,
|
||||||
|
* false→non-front wheel
|
||||||
|
* @return a new VehicleWheel for access (not null)
|
||||||
*/
|
*/
|
||||||
public VehicleWheel addWheel(Spatial spat, Vector3f connectionPoint, Vector3f direction, Vector3f axle, float suspensionRestLength, float wheelRadius, boolean isFrontWheel) {
|
public VehicleWheel addWheel(Spatial spat, Vector3f connectionPoint, Vector3f direction, Vector3f axle, float suspensionRestLength, float wheelRadius, boolean isFrontWheel) {
|
||||||
VehicleWheel wheel = null;
|
VehicleWheel wheel = null;
|
||||||
@ -190,8 +239,9 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This rebuilds the vehicle as there is no way in bullet to remove a wheel.
|
* Remove a wheel.
|
||||||
* @param wheel
|
*
|
||||||
|
* @param wheel the index of the wheel to remove (≥0)
|
||||||
*/
|
*/
|
||||||
public void removeWheel(int wheel) {
|
public void removeWheel(int wheel) {
|
||||||
wheels.remove(wheel);
|
wheels.remove(wheel);
|
||||||
@ -200,195 +250,276 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You can get access to the single wheels via this method.
|
* Access the indexed wheel of this vehicle.
|
||||||
* @param wheel the wheel index
|
*
|
||||||
* @return the WheelInfo of the selected wheel
|
* @param wheel the index of the wheel to access (≥0, <count)
|
||||||
|
* @return the pre-existing instance
|
||||||
*/
|
*/
|
||||||
public VehicleWheel getWheel(int wheel) {
|
public VehicleWheel getWheel(int wheel) {
|
||||||
return wheels.get(wheel);
|
return wheels.get(wheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the number of wheels on this vehicle.
|
||||||
|
*
|
||||||
|
* @return count (≥0)
|
||||||
|
*/
|
||||||
public int getNumWheels() {
|
public int getNumWheels() {
|
||||||
return wheels.size();
|
return wheels.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the frictionSlip
|
* Read the initial friction for new wheels.
|
||||||
|
*
|
||||||
|
* @return the coefficient of friction between tyre and ground
|
||||||
|
* (0.8→realistic car, 10000→kart racer)
|
||||||
*/
|
*/
|
||||||
public float getFrictionSlip() {
|
public float getFrictionSlip() {
|
||||||
return tuning.frictionSlip;
|
return tuning.frictionSlip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before adding wheels, this is the default used when adding wheels.
|
* Alter the initial friction for new wheels. Effective only before adding
|
||||||
* After adding the wheel, use direct wheel access.<br>
|
* wheels. After adding a wheel, use {@link #setFrictionSlip(int, float)}.
|
||||||
* The coefficient of friction between the tyre and the ground.
|
* <p>
|
||||||
* Should be about 0.8 for realistic cars, but can increased for better handling.
|
* For better handling, increase the friction.
|
||||||
* Set large (10000.0) for kart racers
|
*
|
||||||
* @param frictionSlip the frictionSlip to set
|
* @param frictionSlip the desired coefficient of friction between tyre and
|
||||||
|
* ground (0.8→realistic car, 10000→kart racer, default=10.5)
|
||||||
*/
|
*/
|
||||||
public void setFrictionSlip(float frictionSlip) {
|
public void setFrictionSlip(float frictionSlip) {
|
||||||
tuning.frictionSlip = frictionSlip;
|
tuning.frictionSlip = frictionSlip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The coefficient of friction between the tyre and the ground.
|
* Alter the friction of the indexed wheel.
|
||||||
* Should be about 0.8 for realistic cars, but can increased for better handling.
|
* <p>
|
||||||
* Set large (10000.0) for kart racers
|
* For better handling, increase the friction.
|
||||||
* @param wheel
|
*
|
||||||
* @param frictionSlip
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param frictionSlip the desired coefficient of friction between tyre and
|
||||||
|
* ground (0.8→realistic car, 10000→kart racer)
|
||||||
*/
|
*/
|
||||||
public void setFrictionSlip(int wheel, float frictionSlip) {
|
public void setFrictionSlip(int wheel, float frictionSlip) {
|
||||||
wheels.get(wheel).setFrictionSlip(frictionSlip);
|
wheels.get(wheel).setFrictionSlip(frictionSlip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the rolling torque applied from the wheels that cause the vehicle to roll over.
|
* Alter the roll influence of the indexed wheel.
|
||||||
* This is a bit of a hack, but it's quite effective. 0.0 = no roll, 1.0 = physical behaviour.
|
* <p>
|
||||||
* If m_frictionSlip is too high, you'll need to reduce this to stop the vehicle rolling over.
|
* The roll-influence factor reduces (or magnifies) any torque contributed
|
||||||
* You should also try lowering the vehicle's centre of mass
|
* by the wheel that would tend to cause the vehicle to roll over. This is a
|
||||||
|
* bit of a hack, but it's quite effective.
|
||||||
|
* <p>
|
||||||
|
* If the friction between the tyres and the ground is too high, you may
|
||||||
|
* reduce this factor to prevent the vehicle from rolling over. You should
|
||||||
|
* also try lowering the vehicle's center of mass.
|
||||||
|
*
|
||||||
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param rollInfluence the desired roll-influence factor (0→no roll
|
||||||
|
* torque, 1→realistic behavior, default=1)
|
||||||
*/
|
*/
|
||||||
public void setRollInfluence(int wheel, float rollInfluence) {
|
public void setRollInfluence(int wheel, float rollInfluence) {
|
||||||
wheels.get(wheel).setRollInfluence(rollInfluence);
|
wheels.get(wheel).setRollInfluence(rollInfluence);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the maxSuspensionTravelCm
|
* Read the initial maximum suspension travel distance for new wheels.
|
||||||
|
*
|
||||||
|
* @return the maximum distance the suspension can be compressed (in
|
||||||
|
* centimeters)
|
||||||
*/
|
*/
|
||||||
public float getMaxSuspensionTravelCm() {
|
public float getMaxSuspensionTravelCm() {
|
||||||
return tuning.maxSuspensionTravelCm;
|
return tuning.maxSuspensionTravelCm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before adding wheels, this is the default used when adding wheels.
|
* Alter the initial maximum suspension travel distance for new wheels.
|
||||||
* After adding the wheel, use direct wheel access.<br>
|
* Effective only before adding wheels. After adding a wheel, use
|
||||||
* The maximum distance the suspension can be compressed (centimetres)
|
* {@link #setMaxSuspensionTravelCm(int, float)}.
|
||||||
* @param maxSuspensionTravelCm the maxSuspensionTravelCm to set
|
*
|
||||||
|
* @param maxSuspensionTravelCm the desired maximum distance the suspension
|
||||||
|
* can be compressed (in centimeters, default=500)
|
||||||
*/
|
*/
|
||||||
public void setMaxSuspensionTravelCm(float maxSuspensionTravelCm) {
|
public void setMaxSuspensionTravelCm(float maxSuspensionTravelCm) {
|
||||||
tuning.maxSuspensionTravelCm = maxSuspensionTravelCm;
|
tuning.maxSuspensionTravelCm = maxSuspensionTravelCm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum distance the suspension can be compressed (centimetres)
|
* Alter the maximum suspension travel distance for the indexed wheel.
|
||||||
* @param wheel
|
*
|
||||||
* @param maxSuspensionTravelCm
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param maxSuspensionTravelCm the desired maximum distance the suspension
|
||||||
|
* can be compressed (in centimeters)
|
||||||
*/
|
*/
|
||||||
public void setMaxSuspensionTravelCm(int wheel, float maxSuspensionTravelCm) {
|
public void setMaxSuspensionTravelCm(int wheel, float maxSuspensionTravelCm) {
|
||||||
wheels.get(wheel).setMaxSuspensionTravelCm(maxSuspensionTravelCm);
|
wheels.get(wheel).setMaxSuspensionTravelCm(maxSuspensionTravelCm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the initial maximum suspension force for new wheels.
|
||||||
|
*
|
||||||
|
* @return the maximum force per wheel
|
||||||
|
*/
|
||||||
public float getMaxSuspensionForce() {
|
public float getMaxSuspensionForce() {
|
||||||
return tuning.maxSuspensionForce;
|
return tuning.maxSuspensionForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This value caps the maximum suspension force, raise this above the default 6000 if your suspension cannot
|
* Alter the initial maximum suspension force for new wheels. Effective only
|
||||||
* handle the weight of your vehicle.
|
* before adding wheels. After adding a wheel, use
|
||||||
* @param maxSuspensionForce
|
* {@link #setMaxSuspensionForce(int, float)}.
|
||||||
|
* <p>
|
||||||
|
* If the suspension cannot handle the vehicle's weight, increase this
|
||||||
|
* limit.
|
||||||
|
*
|
||||||
|
* @param maxSuspensionForce the desired maximum force per wheel
|
||||||
|
* (default=6000)
|
||||||
*/
|
*/
|
||||||
public void setMaxSuspensionForce(float maxSuspensionForce) {
|
public void setMaxSuspensionForce(float maxSuspensionForce) {
|
||||||
tuning.maxSuspensionForce = maxSuspensionForce;
|
tuning.maxSuspensionForce = maxSuspensionForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This value caps the maximum suspension force, raise this above the default 6000 if your suspension cannot
|
* Alter the maximum suspension force for the specified wheel.
|
||||||
* handle the weight of your vehicle.
|
* <p>
|
||||||
* @param wheel
|
* If the suspension cannot handle the vehicle's weight, increase this
|
||||||
* @param maxSuspensionForce
|
* limit.
|
||||||
|
*
|
||||||
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param maxSuspensionForce the desired maximum force per wheel
|
||||||
|
* (default=6000)
|
||||||
*/
|
*/
|
||||||
public void setMaxSuspensionForce(int wheel, float maxSuspensionForce) {
|
public void setMaxSuspensionForce(int wheel, float maxSuspensionForce) {
|
||||||
wheels.get(wheel).setMaxSuspensionForce(maxSuspensionForce);
|
wheels.get(wheel).setMaxSuspensionForce(maxSuspensionForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the suspensionCompression
|
* Read the initial damping (when the suspension is compressed) for new
|
||||||
|
* wheels.
|
||||||
|
*
|
||||||
|
* @return the damping coefficient
|
||||||
*/
|
*/
|
||||||
public float getSuspensionCompression() {
|
public float getSuspensionCompression() {
|
||||||
return tuning.suspensionCompression;
|
return tuning.suspensionCompression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before adding wheels, this is the default used when adding wheels.
|
* Alter the initial damping (when the suspension is compressed) for new
|
||||||
* After adding the wheel, use direct wheel access.<br>
|
* wheels. Effective only before adding wheels. After adding a wheel, use
|
||||||
* The damping coefficient for when the suspension is compressed.
|
* {@link #setSuspensionCompression(int, float)}.
|
||||||
* Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.<br>
|
* <p>
|
||||||
* k = 0.0 undamped & bouncy, k = 1.0 critical damping<br>
|
* Set to k * 2 * FastMath.sqrt(m_suspensionStiffness) where k is the
|
||||||
* 0.1 to 0.3 are good values
|
* damping ratio:
|
||||||
* @param suspensionCompression the suspensionCompression to set
|
* <p>
|
||||||
|
* k = 0.0 undamped and bouncy, k = 1.0 critical damping, k between 0.1 and
|
||||||
|
* 0.3 are good values
|
||||||
|
*
|
||||||
|
* @param suspensionCompression the desired damping coefficient
|
||||||
|
* (default=0.83)
|
||||||
*/
|
*/
|
||||||
public void setSuspensionCompression(float suspensionCompression) {
|
public void setSuspensionCompression(float suspensionCompression) {
|
||||||
tuning.suspensionCompression = suspensionCompression;
|
tuning.suspensionCompression = suspensionCompression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The damping coefficient for when the suspension is compressed.
|
* Alter the damping (when the suspension is compressed) for the indexed
|
||||||
* Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.<br>
|
* wheel.
|
||||||
* k = 0.0 undamped & bouncy, k = 1.0 critical damping<br>
|
* <p>
|
||||||
* 0.1 to 0.3 are good values
|
* Set to k * 2 * FastMath.sqrt(m_suspensionStiffness) where k is the
|
||||||
* @param wheel
|
* damping ratio:
|
||||||
* @param suspensionCompression
|
* <p>
|
||||||
|
* k = 0.0 undamped and bouncy, k = 1.0 critical damping, k between 0.1 and
|
||||||
|
* 0.3 are good values
|
||||||
|
*
|
||||||
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param suspensionCompression the desired damping coefficient
|
||||||
*/
|
*/
|
||||||
public void setSuspensionCompression(int wheel, float suspensionCompression) {
|
public void setSuspensionCompression(int wheel, float suspensionCompression) {
|
||||||
wheels.get(wheel).setWheelsDampingCompression(suspensionCompression);
|
wheels.get(wheel).setWheelsDampingCompression(suspensionCompression);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the suspensionDamping
|
* Read the initial damping (when the suspension is expanded) for new
|
||||||
|
* wheels.
|
||||||
|
*
|
||||||
|
* @return the damping coefficient
|
||||||
*/
|
*/
|
||||||
public float getSuspensionDamping() {
|
public float getSuspensionDamping() {
|
||||||
return tuning.suspensionDamping;
|
return tuning.suspensionDamping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before adding wheels, this is the default used when adding wheels.
|
* Alter the initial damping (when the suspension is expanded) for new
|
||||||
* After adding the wheel, use direct wheel access.<br>
|
* wheels. Effective only before adding wheels. After adding a wheel, use
|
||||||
* The damping coefficient for when the suspension is expanding.
|
* {@link #setSuspensionCompression(int, float)}.
|
||||||
* See the comments for setSuspensionCompression for how to set k.
|
* <p>
|
||||||
* @param suspensionDamping the suspensionDamping to set
|
* Set to k * 2 * FastMath.sqrt(m_suspensionStiffness) where k is the
|
||||||
|
* damping ratio:
|
||||||
|
* <p>
|
||||||
|
* k = 0.0 undamped and bouncy, k = 1.0 critical damping, k between 0.1 and
|
||||||
|
* 0.3 are good values
|
||||||
|
*
|
||||||
|
* @param suspensionDamping the desired damping coefficient (default=0.88)
|
||||||
*/
|
*/
|
||||||
public void setSuspensionDamping(float suspensionDamping) {
|
public void setSuspensionDamping(float suspensionDamping) {
|
||||||
tuning.suspensionDamping = suspensionDamping;
|
tuning.suspensionDamping = suspensionDamping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The damping coefficient for when the suspension is expanding.
|
* Alter the damping (when the suspension is expanded) for the indexed
|
||||||
* See the comments for setSuspensionCompression for how to set k.
|
* wheel.
|
||||||
* @param wheel
|
* <p>
|
||||||
* @param suspensionDamping
|
* Set to k * 2 * FastMath.sqrt(m_suspensionStiffness) where k is the
|
||||||
|
* damping ratio:
|
||||||
|
* <p>
|
||||||
|
* k = 0.0 undamped and bouncy, k = 1.0 critical damping, k between 0.1 and
|
||||||
|
* 0.3 are good values
|
||||||
|
*
|
||||||
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param suspensionDamping the desired damping coefficient
|
||||||
*/
|
*/
|
||||||
public void setSuspensionDamping(int wheel, float suspensionDamping) {
|
public void setSuspensionDamping(int wheel, float suspensionDamping) {
|
||||||
wheels.get(wheel).setWheelsDampingRelaxation(suspensionDamping);
|
wheels.get(wheel).setWheelsDampingRelaxation(suspensionDamping);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the suspensionStiffness
|
* Read the initial suspension stiffness for new wheels.
|
||||||
|
*
|
||||||
|
* @return the stiffness constant (10→off-road buggy, 50→sports
|
||||||
|
* car, 200→Formula-1 race car)
|
||||||
*/
|
*/
|
||||||
public float getSuspensionStiffness() {
|
public float getSuspensionStiffness() {
|
||||||
return tuning.suspensionStiffness;
|
return tuning.suspensionStiffness;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before adding wheels, this is the default used when adding wheels.
|
* Alter the initial suspension stiffness for new wheels. Effective only
|
||||||
* After adding the wheel, use direct wheel access.<br>
|
* before adding wheels. After adding a wheel, use
|
||||||
* The stiffness constant for the suspension. 10.0 - Offroad buggy, 50.0 - Sports car, 200.0 - F1 Car
|
* {@link #setSuspensionStiffness(int, float)}.
|
||||||
* @param suspensionStiffness
|
*
|
||||||
|
* @param suspensionStiffness the desired stiffness coefficient
|
||||||
|
* (10→off-road buggy, 50→sports car, 200→Formula-1 race car,
|
||||||
|
* default=5.88)
|
||||||
*/
|
*/
|
||||||
public void setSuspensionStiffness(float suspensionStiffness) {
|
public void setSuspensionStiffness(float suspensionStiffness) {
|
||||||
tuning.suspensionStiffness = suspensionStiffness;
|
tuning.suspensionStiffness = suspensionStiffness;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The stiffness constant for the suspension. 10.0 - Offroad buggy, 50.0 - Sports car, 200.0 - F1 Car
|
* Alter the suspension stiffness of the indexed wheel.
|
||||||
* @param wheel
|
*
|
||||||
* @param suspensionStiffness
|
* @param wheel the index of the wheel to modify (≥0)
|
||||||
|
* @param suspensionStiffness the desired stiffness coefficient
|
||||||
|
* (10→off-road buggy, 50→sports car, 200→Formula-1 race car,
|
||||||
|
* default=5.88)
|
||||||
*/
|
*/
|
||||||
public void setSuspensionStiffness(int wheel, float suspensionStiffness) {
|
public void setSuspensionStiffness(int wheel, float suspensionStiffness) {
|
||||||
wheels.get(wheel).setSuspensionStiffness(suspensionStiffness);
|
wheels.get(wheel).setSuspensionStiffness(suspensionStiffness);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the suspension
|
* Reset this vehicle's suspension.
|
||||||
*/
|
*/
|
||||||
public void resetSuspension() {
|
public void resetSuspension() {
|
||||||
resetSuspension(vehicleId);
|
resetSuspension(vehicleId);
|
||||||
@ -397,8 +528,9 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
private native void resetSuspension(long vehicleId);
|
private native void resetSuspension(long vehicleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given engine force to all wheels, works continuously
|
* Apply the specified engine force to all wheels. Works continuously.
|
||||||
* @param force the force
|
*
|
||||||
|
* @param force the desired amount of force
|
||||||
*/
|
*/
|
||||||
public void accelerate(float force) {
|
public void accelerate(float force) {
|
||||||
for (int i = 0; i < wheels.size(); i++) {
|
for (int i = 0; i < wheels.size(); i++) {
|
||||||
@ -407,9 +539,10 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given engine force, works continuously
|
* Apply the given engine force to the indexed wheel. Works continuously.
|
||||||
* @param wheel the wheel to apply the force on
|
*
|
||||||
* @param force the force
|
* @param wheel the index of the wheel to apply the force to (≥0)
|
||||||
|
* @param force the desired amount of force
|
||||||
*/
|
*/
|
||||||
public void accelerate(int wheel, float force) {
|
public void accelerate(int wheel, float force) {
|
||||||
applyEngineForce(vehicleId, wheel, force);
|
applyEngineForce(vehicleId, wheel, force);
|
||||||
@ -419,8 +552,9 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
private native void applyEngineForce(long vehicleId, int wheel, float force);
|
private native void applyEngineForce(long vehicleId, int wheel, float force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the given steering value to all front wheels (0 = forward)
|
* Alter the steering angle of all front wheels.
|
||||||
* @param value the steering angle of the front wheels (Pi = 360deg)
|
*
|
||||||
|
* @param value the desired steering angle (in radians, 0=straight)
|
||||||
*/
|
*/
|
||||||
public void steer(float value) {
|
public void steer(float value) {
|
||||||
for (int i = 0; i < wheels.size(); i++) {
|
for (int i = 0; i < wheels.size(); i++) {
|
||||||
@ -431,9 +565,10 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the given steering value to the given wheel (0 = forward)
|
* Alter the steering angle of the indexed wheel.
|
||||||
* @param wheel the wheel to set the steering on
|
*
|
||||||
* @param value the steering angle of the front wheels (Pi = 360deg)
|
* @param wheel the index of the wheel to steer (≥0)
|
||||||
|
* @param value the desired steering angle (in radians, 0=straight)
|
||||||
*/
|
*/
|
||||||
public void steer(int wheel, float value) {
|
public void steer(int wheel, float value) {
|
||||||
steer(vehicleId, wheel, value);
|
steer(vehicleId, wheel, value);
|
||||||
@ -442,8 +577,9 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
private native void steer(long vehicleId, int wheel, float value);
|
private native void steer(long vehicleId, int wheel, float value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given brake force to all wheels, works continuously
|
* Apply the given brake force to all wheels. Works continuously.
|
||||||
* @param force the force
|
*
|
||||||
|
* @param force the desired amount of force
|
||||||
*/
|
*/
|
||||||
public void brake(float force) {
|
public void brake(float force) {
|
||||||
for (int i = 0; i < wheels.size(); i++) {
|
for (int i = 0; i < wheels.size(); i++) {
|
||||||
@ -452,9 +588,10 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given brake force, works continuously
|
* Apply the given brake force to the indexed wheel. Works continuously.
|
||||||
* @param wheel the wheel to apply the force on
|
*
|
||||||
* @param force the force
|
* @param wheel the index of the wheel to apply the force to (≥0)
|
||||||
|
* @param force the desired amount of force
|
||||||
*/
|
*/
|
||||||
public void brake(int wheel, float force) {
|
public void brake(int wheel, float force) {
|
||||||
brake(vehicleId, wheel, force);
|
brake(vehicleId, wheel, force);
|
||||||
@ -463,8 +600,9 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
private native void brake(long vehicleId, int wheel, float force);
|
private native void brake(long vehicleId, int wheel, float force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current speed of the vehicle in km/h
|
* Read the vehicle's speed in km/h.
|
||||||
* @return
|
*
|
||||||
|
* @return speed (in kilometers per hour)
|
||||||
*/
|
*/
|
||||||
public float getCurrentVehicleSpeedKmHour() {
|
public float getCurrentVehicleSpeedKmHour() {
|
||||||
return getCurrentVehicleSpeedKmHour(vehicleId);
|
return getCurrentVehicleSpeedKmHour(vehicleId);
|
||||||
@ -473,9 +611,11 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
private native float getCurrentVehicleSpeedKmHour(long vehicleId);
|
private native float getCurrentVehicleSpeedKmHour(long vehicleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current forward vector of the vehicle in world coordinates
|
* Copy the vehicle's forward direction.
|
||||||
* @param vector
|
*
|
||||||
* @return
|
* @param vector storage for the result (modified if not null)
|
||||||
|
* @return a direction vector (in physics-space coordinates, either the
|
||||||
|
* provided storage or a new vector)
|
||||||
*/
|
*/
|
||||||
public Vector3f getForwardVector(Vector3f vector) {
|
public Vector3f getForwardVector(Vector3f vector) {
|
||||||
if (vector == null) {
|
if (vector == null) {
|
||||||
@ -489,11 +629,19 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* used internally
|
* used internally
|
||||||
|
*
|
||||||
|
* @return the unique identifier
|
||||||
*/
|
*/
|
||||||
public long getVehicleId() {
|
public long getVehicleId() {
|
||||||
return vehicleId;
|
return vehicleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this vehicle, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -509,6 +657,12 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
super.read(im);
|
super.read(im);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this vehicle, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule capsule = ex.getCapsule(this);
|
OutputCapsule capsule = ex.getCapsule(this);
|
||||||
@ -522,6 +676,12 @@ public class PhysicsVehicle extends PhysicsRigidBody {
|
|||||||
super.write(ex);
|
super.write(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this vehicle just before it is destroyed. Should be invoked only
|
||||||
|
* by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -40,42 +40,142 @@ import com.jme3.scene.Spatial;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores info about one wheel of a PhysicsVehicle
|
* Information about one wheel of a PhysicsVehicle.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class VehicleWheel implements Savable {
|
public class VehicleWheel implements Savable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unique identifier of the btRaycastVehicle
|
||||||
|
*/
|
||||||
protected long wheelId = 0;
|
protected long wheelId = 0;
|
||||||
|
/**
|
||||||
|
* 0-origin index among the vehicle's wheels (≥0)
|
||||||
|
*/
|
||||||
protected int wheelIndex = 0;
|
protected int wheelIndex = 0;
|
||||||
|
/**
|
||||||
|
* copy of wheel type: true→front (steering) wheel,
|
||||||
|
* false→non-front wheel
|
||||||
|
*/
|
||||||
protected boolean frontWheel;
|
protected boolean frontWheel;
|
||||||
|
/**
|
||||||
|
* location where the suspension connects to the chassis (in chassis
|
||||||
|
* coordinates)
|
||||||
|
*/
|
||||||
protected Vector3f location = new Vector3f();
|
protected Vector3f location = new Vector3f();
|
||||||
|
/**
|
||||||
|
* suspension direction (in chassis coordinates, typically down/0,-1,0)
|
||||||
|
*/
|
||||||
protected Vector3f direction = new Vector3f();
|
protected Vector3f direction = new Vector3f();
|
||||||
|
/**
|
||||||
|
* axis direction (in chassis coordinates, typically to the right/-1,0,0)
|
||||||
|
*/
|
||||||
protected Vector3f axle = new Vector3f();
|
protected Vector3f axle = new Vector3f();
|
||||||
|
/**
|
||||||
|
* copy of suspension stiffness constant (10→off-road buggy,
|
||||||
|
* 50→sports car, 200→Formula-1 race car, default=20)
|
||||||
|
*/
|
||||||
protected float suspensionStiffness = 20.0f;
|
protected float suspensionStiffness = 20.0f;
|
||||||
|
/**
|
||||||
|
* copy of suspension damping when expanded (0→no damping, default=2.3)
|
||||||
|
*/
|
||||||
protected float wheelsDampingRelaxation = 2.3f;
|
protected float wheelsDampingRelaxation = 2.3f;
|
||||||
|
/**
|
||||||
|
* copy of suspension damping when compressed (0→no damping,
|
||||||
|
* default=4.4)
|
||||||
|
*/
|
||||||
protected float wheelsDampingCompression = 4.4f;
|
protected float wheelsDampingCompression = 4.4f;
|
||||||
|
/**
|
||||||
|
* copy of coefficient of friction between tyre and ground
|
||||||
|
* (0.8→realistic car, 10000→kart racer, default=10.5)
|
||||||
|
*/
|
||||||
protected float frictionSlip = 10.5f;
|
protected float frictionSlip = 10.5f;
|
||||||
|
/**
|
||||||
|
* copy of roll-influence factor (0→no roll torque, 1→realistic
|
||||||
|
* behavior, default=1)
|
||||||
|
*/
|
||||||
protected float rollInfluence = 1.0f;
|
protected float rollInfluence = 1.0f;
|
||||||
|
/**
|
||||||
|
* copy of maximum suspension travel distance (in centimeters, default=500)
|
||||||
|
*/
|
||||||
protected float maxSuspensionTravelCm = 500f;
|
protected float maxSuspensionTravelCm = 500f;
|
||||||
|
/**
|
||||||
|
* copy of maximum force exerted by the suspension (default=6000)
|
||||||
|
*/
|
||||||
protected float maxSuspensionForce = 6000f;
|
protected float maxSuspensionForce = 6000f;
|
||||||
|
/**
|
||||||
|
* copy of wheel radius (in physics-space units, >0)
|
||||||
|
*/
|
||||||
protected float radius = 0.5f;
|
protected float radius = 0.5f;
|
||||||
|
/**
|
||||||
|
* copy of rest length of the suspension (in physics-space units)
|
||||||
|
*/
|
||||||
protected float restLength = 1f;
|
protected float restLength = 1f;
|
||||||
|
/**
|
||||||
|
* wheel location in physics-space coordinates
|
||||||
|
*/
|
||||||
protected Vector3f wheelWorldLocation = new Vector3f();
|
protected Vector3f wheelWorldLocation = new Vector3f();
|
||||||
|
/**
|
||||||
|
* wheel orientation in physics-space coordinates
|
||||||
|
*/
|
||||||
protected Quaternion wheelWorldRotation = new Quaternion();
|
protected Quaternion wheelWorldRotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* associated spatial, or null if none
|
||||||
|
*/
|
||||||
protected Spatial wheelSpatial;
|
protected Spatial wheelSpatial;
|
||||||
protected Matrix3f tmp_Matrix = new com.jme3.math.Matrix3f();
|
protected Matrix3f tmp_Matrix = new com.jme3.math.Matrix3f();
|
||||||
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||||
|
/**
|
||||||
|
* true → physics coordinates match local transform, false →
|
||||||
|
* physics coordinates match world transform
|
||||||
|
*/
|
||||||
private boolean applyLocal = false;
|
private boolean applyLocal = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor needed by SavableClassUtil. Do not invoke
|
||||||
|
* directly!
|
||||||
|
*/
|
||||||
public VehicleWheel() {
|
public VehicleWheel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a wheel.
|
||||||
|
*
|
||||||
|
* @param spat the associated spatial, or null if none
|
||||||
|
* @param location the location where the suspension connects to the chassis
|
||||||
|
* (in chassis coordinates, not null, unaffected)
|
||||||
|
* @param direction the suspension direction (in chassis coordinates, not
|
||||||
|
* null, unaffected, typically down/0,-1,0)
|
||||||
|
* @param axle the axis direction (in chassis coordinates, not null,
|
||||||
|
* unaffected, typically right/-1,0,0)
|
||||||
|
* @param restLength the rest length of the suspension (in physics-space
|
||||||
|
* units)
|
||||||
|
* @param radius the wheel's radius (in physics-space units, ≥0)
|
||||||
|
* @param frontWheel true→front (steering) wheel, false→non-front
|
||||||
|
* wheel
|
||||||
|
*/
|
||||||
public VehicleWheel(Spatial spat, Vector3f location, Vector3f direction, Vector3f axle,
|
public VehicleWheel(Spatial spat, Vector3f location, Vector3f direction, Vector3f axle,
|
||||||
float restLength, float radius, boolean frontWheel) {
|
float restLength, float radius, boolean frontWheel) {
|
||||||
this(location, direction, axle, restLength, radius, frontWheel);
|
this(location, direction, axle, restLength, radius, frontWheel);
|
||||||
wheelSpatial = spat;
|
wheelSpatial = spat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a wheel without an associated spatial.
|
||||||
|
*
|
||||||
|
* @param location the location where the suspension connects to the chassis
|
||||||
|
* (in chassis coordinates, not null, unaffected)
|
||||||
|
* @param direction the suspension direction (in chassis coordinates, not
|
||||||
|
* null, unaffected, typically down/0,-1,0)
|
||||||
|
* @param axle the axis direction (in chassis coordinates, not null,
|
||||||
|
* unaffected, typically right/-1,0,0)
|
||||||
|
* @param restLength the rest length of the suspension (in physics-space
|
||||||
|
* units)
|
||||||
|
* @param radius the wheel's radius (in physics-space units, ≥0)
|
||||||
|
* @param frontWheel true→front (steering) wheel, false→non-front
|
||||||
|
* wheel
|
||||||
|
*/
|
||||||
public VehicleWheel(Vector3f location, Vector3f direction, Vector3f axle,
|
public VehicleWheel(Vector3f location, Vector3f direction, Vector3f axle,
|
||||||
float restLength, float radius, boolean frontWheel) {
|
float restLength, float radius, boolean frontWheel) {
|
||||||
this.location.set(location);
|
this.location.set(location);
|
||||||
@ -86,6 +186,9 @@ public class VehicleWheel implements Savable {
|
|||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this wheel's location and orientation in physics space.
|
||||||
|
*/
|
||||||
public void updatePhysicsState() {
|
public void updatePhysicsState() {
|
||||||
getWheelLocation(wheelId, wheelIndex, wheelWorldLocation);
|
getWheelLocation(wheelId, wheelIndex, wheelWorldLocation);
|
||||||
getWheelRotation(wheelId, wheelIndex, tmp_Matrix);
|
getWheelRotation(wheelId, wheelIndex, tmp_Matrix);
|
||||||
@ -96,6 +199,10 @@ public class VehicleWheel implements Savable {
|
|||||||
|
|
||||||
private native void getWheelRotation(long vehicleId, int wheelId, Matrix3f location);
|
private native void getWheelRotation(long vehicleId, int wheelId, Matrix3f location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this wheel's physics location and orientation to its associated
|
||||||
|
* spatial, if any.
|
||||||
|
*/
|
||||||
public void applyWheelTransform() {
|
public void applyWheelTransform() {
|
||||||
if (wheelSpatial == null) {
|
if (wheelSpatial == null) {
|
||||||
return;
|
return;
|
||||||
@ -118,132 +225,232 @@ public class VehicleWheel implements Savable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the id of the btRaycastVehicle.
|
||||||
|
*
|
||||||
|
* @return the unique identifier (not zero)
|
||||||
|
*/
|
||||||
public long getWheelId() {
|
public long getWheelId() {
|
||||||
return wheelId;
|
return wheelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign this wheel to a vehicle.
|
||||||
|
*
|
||||||
|
* @param vehicleId the id of the btRaycastVehicle (not zero)
|
||||||
|
* @param wheelIndex index among the vehicle's wheels (≥0)
|
||||||
|
*/
|
||||||
public void setVehicleId(long vehicleId, int wheelIndex) {
|
public void setVehicleId(long vehicleId, int wheelIndex) {
|
||||||
this.wheelId = vehicleId;
|
this.wheelId = vehicleId;
|
||||||
this.wheelIndex = wheelIndex;
|
this.wheelIndex = wheelIndex;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this wheel is a front wheel.
|
||||||
|
*
|
||||||
|
* @return true if front wheel, otherwise false
|
||||||
|
*/
|
||||||
public boolean isFrontWheel() {
|
public boolean isFrontWheel() {
|
||||||
return frontWheel;
|
return frontWheel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether this wheel is a front (steering) wheel.
|
||||||
|
*
|
||||||
|
* @param frontWheel true→front wheel, false→non-front wheel
|
||||||
|
*/
|
||||||
public void setFrontWheel(boolean frontWheel) {
|
public void setFrontWheel(boolean frontWheel) {
|
||||||
this.frontWheel = frontWheel;
|
this.frontWheel = frontWheel;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the location where the suspension connects to the chassis.
|
||||||
|
*
|
||||||
|
* @return the pre-existing location vector (in chassis coordinates, not
|
||||||
|
* null)
|
||||||
|
*/
|
||||||
public Vector3f getLocation() {
|
public Vector3f getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access this wheel's suspension direction.
|
||||||
|
*
|
||||||
|
* @return the pre-existing direction vector (in chassis coordinates, not
|
||||||
|
* null)
|
||||||
|
*/
|
||||||
public Vector3f getDirection() {
|
public Vector3f getDirection() {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access this wheel's axle direction.
|
||||||
|
*
|
||||||
|
* @return the pre-existing direction vector (not null)
|
||||||
|
*/
|
||||||
public Vector3f getAxle() {
|
public Vector3f getAxle() {
|
||||||
return axle;
|
return axle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the stiffness constant for this wheel's suspension.
|
||||||
|
*
|
||||||
|
* @return the stiffness constant
|
||||||
|
*/
|
||||||
public float getSuspensionStiffness() {
|
public float getSuspensionStiffness() {
|
||||||
return suspensionStiffness;
|
return suspensionStiffness;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the stiffness constant for the suspension. 10.0 - Offroad buggy, 50.0 - Sports car, 200.0 - F1 Car
|
* Alter the stiffness constant for this wheel's suspension.
|
||||||
* @param suspensionStiffness
|
*
|
||||||
|
* @param suspensionStiffness the desired stiffness constant
|
||||||
|
* (10→off-road buggy, 50→sports car, 200→Formula-1 race car,
|
||||||
|
* default=20)
|
||||||
*/
|
*/
|
||||||
public void setSuspensionStiffness(float suspensionStiffness) {
|
public void setSuspensionStiffness(float suspensionStiffness) {
|
||||||
this.suspensionStiffness = suspensionStiffness;
|
this.suspensionStiffness = suspensionStiffness;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this wheel's damping when the suspension is expanded.
|
||||||
|
*
|
||||||
|
* @return the damping
|
||||||
|
*/
|
||||||
public float getWheelsDampingRelaxation() {
|
public float getWheelsDampingRelaxation() {
|
||||||
return wheelsDampingRelaxation;
|
return wheelsDampingRelaxation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the damping coefficient for when the suspension is expanding.
|
* Alter this wheel's damping when the suspension is expanded.
|
||||||
* See the comments for setWheelsDampingCompression for how to set k.
|
* <p>
|
||||||
* @param wheelsDampingRelaxation
|
* Set to k * 2 * FastMath.sqrt(m_suspensionStiffness) where k is the
|
||||||
|
* damping ratio:
|
||||||
|
* <p>
|
||||||
|
* k = 0.0 undamped and bouncy, k = 1.0 critical damping, k between 0.1 and
|
||||||
|
* 0.3 are good values
|
||||||
|
*
|
||||||
|
* @param wheelsDampingRelaxation the desired damping (default=2.3)
|
||||||
*/
|
*/
|
||||||
public void setWheelsDampingRelaxation(float wheelsDampingRelaxation) {
|
public void setWheelsDampingRelaxation(float wheelsDampingRelaxation) {
|
||||||
this.wheelsDampingRelaxation = wheelsDampingRelaxation;
|
this.wheelsDampingRelaxation = wheelsDampingRelaxation;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this wheel's damping when the suspension is compressed.
|
||||||
|
*
|
||||||
|
* @return the damping
|
||||||
|
*/
|
||||||
public float getWheelsDampingCompression() {
|
public float getWheelsDampingCompression() {
|
||||||
return wheelsDampingCompression;
|
return wheelsDampingCompression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the damping coefficient for when the suspension is compressed.
|
* Alter this wheel's damping when the suspension is compressed.
|
||||||
* Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.<br>
|
* <p>
|
||||||
* k = 0.0 undamped & bouncy, k = 1.0 critical damping<br>
|
* Set to k * 2 * FastMath.sqrt(m_suspensionStiffness) where k is the
|
||||||
* 0.1 to 0.3 are good values
|
* damping ratio:
|
||||||
* @param wheelsDampingCompression
|
* <p>
|
||||||
|
* k = 0.0 undamped and bouncy, k = 1.0 critical damping, k between 0.1 and
|
||||||
|
* 0.3 are good values
|
||||||
|
*
|
||||||
|
* @param wheelsDampingCompression the desired damping (default=4.4)
|
||||||
*/
|
*/
|
||||||
public void setWheelsDampingCompression(float wheelsDampingCompression) {
|
public void setWheelsDampingCompression(float wheelsDampingCompression) {
|
||||||
this.wheelsDampingCompression = wheelsDampingCompression;
|
this.wheelsDampingCompression = wheelsDampingCompression;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the friction between this wheel's tyre and the ground.
|
||||||
|
*
|
||||||
|
* @return the coefficient of friction
|
||||||
|
*/
|
||||||
public float getFrictionSlip() {
|
public float getFrictionSlip() {
|
||||||
return frictionSlip;
|
return frictionSlip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the coefficient of friction between the tyre and the ground.
|
* Alter the friction between this wheel's tyre and the ground.
|
||||||
* Should be about 0.8 for realistic cars, but can increased for better handling.
|
* <p>
|
||||||
* Set large (10000.0) for kart racers
|
* Should be about 0.8 for realistic cars, but can increased for better
|
||||||
* @param frictionSlip
|
* handling. Set large (10000.0) for kart racers.
|
||||||
|
*
|
||||||
|
* @param frictionSlip the desired coefficient of friction (default=10.5)
|
||||||
*/
|
*/
|
||||||
public void setFrictionSlip(float frictionSlip) {
|
public void setFrictionSlip(float frictionSlip) {
|
||||||
this.frictionSlip = frictionSlip;
|
this.frictionSlip = frictionSlip;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this wheel's roll influence.
|
||||||
|
*
|
||||||
|
* @return the roll-influence factor
|
||||||
|
*/
|
||||||
public float getRollInfluence() {
|
public float getRollInfluence() {
|
||||||
return rollInfluence;
|
return rollInfluence;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reduces the rolling torque applied from the wheels that cause the vehicle to roll over.
|
* Alter this wheel's roll influence.
|
||||||
* This is a bit of a hack, but it's quite effective. 0.0 = no roll, 1.0 = physical behaviour.
|
* <p>
|
||||||
* If m_frictionSlip is too high, you'll need to reduce this to stop the vehicle rolling over.
|
* The roll-influence factor reduces (or magnifies) the torque contributed
|
||||||
* You should also try lowering the vehicle's centre of mass
|
* by this wheel that tends to cause the vehicle to roll over. This is a bit
|
||||||
* @param rollInfluence the rollInfluence to set
|
* of a hack, but it's quite effective.
|
||||||
|
* <p>
|
||||||
|
* If the friction between the tyres and the ground is too high, you may
|
||||||
|
* reduce this factor to prevent the vehicle from rolling over. You should
|
||||||
|
* also try lowering the vehicle's centre of mass.
|
||||||
|
*
|
||||||
|
* @param rollInfluence the desired roll-influence factor (0→no roll
|
||||||
|
* torque, 1→realistic behaviour, default=1)
|
||||||
*/
|
*/
|
||||||
public void setRollInfluence(float rollInfluence) {
|
public void setRollInfluence(float rollInfluence) {
|
||||||
this.rollInfluence = rollInfluence;
|
this.rollInfluence = rollInfluence;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the travel distance for this wheel's suspension.
|
||||||
|
*
|
||||||
|
* @return the maximum travel distance (in centimeters)
|
||||||
|
*/
|
||||||
public float getMaxSuspensionTravelCm() {
|
public float getMaxSuspensionTravelCm() {
|
||||||
return maxSuspensionTravelCm;
|
return maxSuspensionTravelCm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the maximum distance the suspension can be compressed (centimetres)
|
* Alter the travel distance for this wheel's suspension.
|
||||||
* @param maxSuspensionTravelCm
|
*
|
||||||
|
* @param maxSuspensionTravelCm the desired maximum travel distance (in
|
||||||
|
* centimetres, default=500)
|
||||||
*/
|
*/
|
||||||
public void setMaxSuspensionTravelCm(float maxSuspensionTravelCm) {
|
public void setMaxSuspensionTravelCm(float maxSuspensionTravelCm) {
|
||||||
this.maxSuspensionTravelCm = maxSuspensionTravelCm;
|
this.maxSuspensionTravelCm = maxSuspensionTravelCm;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the maximum force exerted by this wheel's suspension.
|
||||||
|
*
|
||||||
|
* @return the maximum force
|
||||||
|
*/
|
||||||
public float getMaxSuspensionForce() {
|
public float getMaxSuspensionForce() {
|
||||||
return maxSuspensionForce;
|
return maxSuspensionForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum suspension force, raise this above the default 6000 if your suspension cannot
|
* Alter the maximum force exerted by this wheel's suspension.
|
||||||
* handle the weight of your vehicle.
|
* <p>
|
||||||
* @param maxSuspensionTravelCm
|
* Increase this if your suspension cannot handle the weight of your
|
||||||
|
* vehicle.
|
||||||
|
*
|
||||||
|
* @param maxSuspensionForce the desired maximum force (default=6000)
|
||||||
*/
|
*/
|
||||||
public void setMaxSuspensionForce(float maxSuspensionForce) {
|
public void setMaxSuspensionForce(float maxSuspensionForce) {
|
||||||
this.maxSuspensionForce = maxSuspensionForce;
|
this.maxSuspensionForce = maxSuspensionForce;
|
||||||
@ -269,19 +476,40 @@ public class VehicleWheel implements Savable {
|
|||||||
boolean frontWheel,
|
boolean frontWheel,
|
||||||
float suspensionRestLength);
|
float suspensionRestLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the radius of this wheel.
|
||||||
|
*
|
||||||
|
* @return the radius (in physics-space units, ≥0)
|
||||||
|
*/
|
||||||
public float getRadius() {
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the radius of this wheel.
|
||||||
|
*
|
||||||
|
* @param radius the desired radius (in physics-space units, ≥0,
|
||||||
|
* default=0.5)
|
||||||
|
*/
|
||||||
public void setRadius(float radius) {
|
public void setRadius(float radius) {
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the rest length of this wheel.
|
||||||
|
*
|
||||||
|
* @return the length
|
||||||
|
*/
|
||||||
public float getRestLength() {
|
public float getRestLength() {
|
||||||
return restLength;
|
return restLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter the rest length of the suspension of this wheel.
|
||||||
|
*
|
||||||
|
* @param restLength the desired length (default=1)
|
||||||
|
*/
|
||||||
public void setRestLength(float restLength) {
|
public void setRestLength(float restLength) {
|
||||||
this.restLength = restLength;
|
this.restLength = restLength;
|
||||||
applyInfo();
|
applyInfo();
|
||||||
@ -303,7 +531,10 @@ public class VehicleWheel implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the location where the wheel collides with the ground (world space)
|
* Copy the location where the wheel touches the ground.
|
||||||
|
*
|
||||||
|
* @param vec storage for the result (not null, modified)
|
||||||
|
* @return a new location vector (in physics-space coordinates, not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getCollisionLocation(Vector3f vec) {
|
public Vector3f getCollisionLocation(Vector3f vec) {
|
||||||
getCollisionLocation(wheelId, wheelIndex, vec);
|
getCollisionLocation(wheelId, wheelIndex, vec);
|
||||||
@ -313,7 +544,9 @@ public class VehicleWheel implements Savable {
|
|||||||
private native void getCollisionLocation(long wheelId, int wheelIndex, Vector3f vec);
|
private native void getCollisionLocation(long wheelId, int wheelIndex, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the location where the wheel collides with the ground (world space)
|
* Copy the location where the wheel collides with the ground.
|
||||||
|
*
|
||||||
|
* @return a new location vector (in physics-space coordinates)
|
||||||
*/
|
*/
|
||||||
public Vector3f getCollisionLocation() {
|
public Vector3f getCollisionLocation() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
@ -322,7 +555,10 @@ public class VehicleWheel implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the normal where the wheel collides with the ground (world space)
|
* Copy the normal where the wheel touches the ground.
|
||||||
|
*
|
||||||
|
* @param vec storage for the result (not null, modified)
|
||||||
|
* @return a unit vector (in physics-space coordinates, not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getCollisionNormal(Vector3f vec) {
|
public Vector3f getCollisionNormal(Vector3f vec) {
|
||||||
getCollisionNormal(wheelId, wheelIndex, vec);
|
getCollisionNormal(wheelId, wheelIndex, vec);
|
||||||
@ -332,7 +568,9 @@ public class VehicleWheel implements Savable {
|
|||||||
private native void getCollisionNormal(long wheelId, int wheelIndex, Vector3f vec);
|
private native void getCollisionNormal(long wheelId, int wheelIndex, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the normal where the wheel collides with the ground (world space)
|
* Copy the normal where the wheel touches the ground.
|
||||||
|
*
|
||||||
|
* @return a new unit vector (in physics-space coordinates, not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getCollisionNormal() {
|
public Vector3f getCollisionNormal() {
|
||||||
Vector3f vec = new Vector3f();
|
Vector3f vec = new Vector3f();
|
||||||
@ -341,8 +579,11 @@ public class VehicleWheel implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns how much the wheel skids on the ground (for skid sounds/smoke etc.)<br>
|
* Calculate to what extent the wheel is skidding (for skid sounds/smoke
|
||||||
* 0.0 = wheels are sliding, 1.0 = wheels have traction.
|
* etc.)
|
||||||
|
*
|
||||||
|
* @return the relative amount of traction (0→wheel is sliding,
|
||||||
|
* 1→wheel has full traction)
|
||||||
*/
|
*/
|
||||||
public float getSkidInfo() {
|
public float getSkidInfo() {
|
||||||
return getSkidInfo(wheelId, wheelIndex);
|
return getSkidInfo(wheelId, wheelIndex);
|
||||||
@ -351,8 +592,9 @@ public class VehicleWheel implements Savable {
|
|||||||
public native float getSkidInfo(long wheelId, int wheelIndex);
|
public native float getSkidInfo(long wheelId, int wheelIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns how many degrees the wheel has turned since the last physics
|
* Calculate how much this wheel has turned since the last physics step.
|
||||||
* step.
|
*
|
||||||
|
* @return the rotation angle (in radians)
|
||||||
*/
|
*/
|
||||||
public float getDeltaRotation() {
|
public float getDeltaRotation() {
|
||||||
return getDeltaRotation(wheelId, wheelIndex);
|
return getDeltaRotation(wheelId, wheelIndex);
|
||||||
@ -360,6 +602,12 @@ public class VehicleWheel implements Savable {
|
|||||||
|
|
||||||
public native float getDeltaRotation(long wheelId, int wheelIndex);
|
public native float getDeltaRotation(long wheelId, int wheelIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serialize this wheel, for example when loading from a J3O file.
|
||||||
|
*
|
||||||
|
* @param im importer (not null)
|
||||||
|
* @throws IOException from importer
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule capsule = im.getCapsule(this);
|
InputCapsule capsule = im.getCapsule(this);
|
||||||
@ -379,6 +627,12 @@ public class VehicleWheel implements Savable {
|
|||||||
restLength = capsule.readFloat("restLength", 1f);
|
restLength = capsule.readFloat("restLength", 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this wheel, for example when saving to a J3O file.
|
||||||
|
*
|
||||||
|
* @param ex exporter (not null)
|
||||||
|
* @throws IOException from exporter
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule capsule = ex.getCapsule(this);
|
OutputCapsule capsule = ex.getCapsule(this);
|
||||||
@ -399,41 +653,59 @@ public class VehicleWheel implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the wheelSpatial
|
* Access the spatial associated with this wheel.
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance, or null
|
||||||
*/
|
*/
|
||||||
public Spatial getWheelSpatial() {
|
public Spatial getWheelSpatial() {
|
||||||
return wheelSpatial;
|
return wheelSpatial;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param wheelSpatial the wheelSpatial to set
|
* Alter which spatial is associated with this wheel.
|
||||||
|
*
|
||||||
|
* @param wheelSpatial the desired spatial, or null for none
|
||||||
*/
|
*/
|
||||||
public void setWheelSpatial(Spatial wheelSpatial) {
|
public void setWheelSpatial(Spatial wheelSpatial) {
|
||||||
this.wheelSpatial = wheelSpatial;
|
this.wheelSpatial = wheelSpatial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether physics coordinates should match the local transform of the
|
||||||
|
* Spatial.
|
||||||
|
*
|
||||||
|
* @return true if matching local transform, false if matching world
|
||||||
|
* transform
|
||||||
|
*/
|
||||||
public boolean isApplyLocal() {
|
public boolean isApplyLocal() {
|
||||||
return applyLocal;
|
return applyLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether physics coordinates should match the local transform of the
|
||||||
|
* Spatial.
|
||||||
|
*
|
||||||
|
* @param applyLocal true→match local transform, false→match world
|
||||||
|
* transform (default=false)
|
||||||
|
*/
|
||||||
public void setApplyLocal(boolean applyLocal) {
|
public void setApplyLocal(boolean applyLocal) {
|
||||||
this.applyLocal = applyLocal;
|
this.applyLocal = applyLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write the content of the wheelWorldRotation into the store
|
* Copy this wheel's physics-space orientation to the specified quaternion.
|
||||||
*
|
*
|
||||||
* @param store
|
* @param store storage for the result (not null, modified)
|
||||||
*/
|
*/
|
||||||
public void getWheelWorldRotation(final Quaternion store) {
|
public void getWheelWorldRotation(final Quaternion store) {
|
||||||
store.set(this.wheelWorldRotation);
|
store.set(this.wheelWorldRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write the content of the wheelWorldLocation into the store
|
* Copy this wheel's physics-space location to the specified vector.
|
||||||
*
|
*
|
||||||
* @param store
|
* @param store storage for the result (not null, modified)
|
||||||
*/
|
*/
|
||||||
public void getWheelWorldLocation(final Vector3f store) {
|
public void getWheelWorldLocation(final Vector3f store) {
|
||||||
store.set(this.wheelWorldLocation);
|
store.set(this.wheelWorldLocation);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -40,8 +40,8 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stores transform info of a PhysicsNode in a threadsafe manner to
|
* The motion state (transform) of a rigid body, with thread-safe access.
|
||||||
* allow multithreaded access from the jme scenegraph and the bullet physicsspace
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class RigidBodyMotionState {
|
public class RigidBodyMotionState {
|
||||||
@ -51,9 +51,16 @@ public class RigidBodyMotionState {
|
|||||||
private Quaternion worldRotationQuat = new Quaternion();
|
private Quaternion worldRotationQuat = new Quaternion();
|
||||||
private Quaternion tmp_inverseWorldRotation = new Quaternion();
|
private Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||||
private PhysicsVehicle vehicle;
|
private PhysicsVehicle vehicle;
|
||||||
|
/**
|
||||||
|
* true → physics coordinates match local transform, false →
|
||||||
|
* physics coordinates match world transform
|
||||||
|
*/
|
||||||
private boolean applyPhysicsLocal = false;
|
private boolean applyPhysicsLocal = false;
|
||||||
// protected LinkedList<PhysicsMotionStateListener> listeners = new LinkedList<PhysicsMotionStateListener>();
|
// protected LinkedList<PhysicsMotionStateListener> listeners = new LinkedList<PhysicsMotionStateListener>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a motion state.
|
||||||
|
*/
|
||||||
public RigidBodyMotionState() {
|
public RigidBodyMotionState() {
|
||||||
this.motionStateId = createMotionState();
|
this.motionStateId = createMotionState();
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created MotionState {0}", Long.toHexString(motionStateId));
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created MotionState {0}", Long.toHexString(motionStateId));
|
||||||
@ -62,8 +69,11 @@ public class RigidBodyMotionState {
|
|||||||
private native long createMotionState();
|
private native long createMotionState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* applies the current transform to the given jme Node if the location has been updated on the physics side
|
* If the motion state has been updated, apply the new transform to the
|
||||||
* @param spatial
|
* specified spatial.
|
||||||
|
*
|
||||||
|
* @param spatial where to apply the physics transform (not null, modified)
|
||||||
|
* @return true if changed
|
||||||
*/
|
*/
|
||||||
public boolean applyTransform(Spatial spatial) {
|
public boolean applyTransform(Spatial spatial) {
|
||||||
Vector3f localLocation = spatial.getLocalTranslation();
|
Vector3f localLocation = spatial.getLocalTranslation();
|
||||||
@ -97,7 +107,10 @@ public class RigidBodyMotionState {
|
|||||||
private native boolean applyTransform(long stateId, Vector3f location, Quaternion rotation);
|
private native boolean applyTransform(long stateId, Vector3f location, Quaternion rotation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the worldLocation
|
* Copy the location from this motion state.
|
||||||
|
*
|
||||||
|
* @return the pre-existing location vector (in physics-space coordinates,
|
||||||
|
* not null)
|
||||||
*/
|
*/
|
||||||
public Vector3f getWorldLocation() {
|
public Vector3f getWorldLocation() {
|
||||||
getWorldLocation(motionStateId, worldLocation);
|
getWorldLocation(motionStateId, worldLocation);
|
||||||
@ -107,7 +120,10 @@ public class RigidBodyMotionState {
|
|||||||
private native void getWorldLocation(long stateId, Vector3f vec);
|
private native void getWorldLocation(long stateId, Vector3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the worldRotation
|
* Read the rotation of this motion state (as a matrix).
|
||||||
|
*
|
||||||
|
* @return the pre-existing rotation matrix (in physics-space coordinates,
|
||||||
|
* not null)
|
||||||
*/
|
*/
|
||||||
public Matrix3f getWorldRotation() {
|
public Matrix3f getWorldRotation() {
|
||||||
getWorldRotation(motionStateId, worldRotation);
|
getWorldRotation(motionStateId, worldRotation);
|
||||||
@ -117,7 +133,10 @@ public class RigidBodyMotionState {
|
|||||||
private native void getWorldRotation(long stateId, Matrix3f vec);
|
private native void getWorldRotation(long stateId, Matrix3f vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the worldRotationQuat
|
* Read the rotation of this motion state (as a quaternion).
|
||||||
|
*
|
||||||
|
* @return the pre-existing instance (in physics-space coordinates, not
|
||||||
|
* null)
|
||||||
*/
|
*/
|
||||||
public Quaternion getWorldRotationQuat() {
|
public Quaternion getWorldRotationQuat() {
|
||||||
getWorldRotationQuat(motionStateId, worldRotationQuat);
|
getWorldRotationQuat(motionStateId, worldRotationQuat);
|
||||||
@ -127,20 +146,39 @@ public class RigidBodyMotionState {
|
|||||||
private native void getWorldRotationQuat(long stateId, Quaternion vec);
|
private native void getWorldRotationQuat(long stateId, Quaternion vec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param vehicle the vehicle to set
|
* @param vehicle which vehicle will use this motion state
|
||||||
*/
|
*/
|
||||||
public void setVehicle(PhysicsVehicle vehicle) {
|
public void setVehicle(PhysicsVehicle vehicle) {
|
||||||
this.vehicle = vehicle;
|
this.vehicle = vehicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether physics-space coordinates should match the spatial's local
|
||||||
|
* coordinates.
|
||||||
|
*
|
||||||
|
* @return true if matching local coordinates, false if matching world
|
||||||
|
* coordinates
|
||||||
|
*/
|
||||||
public boolean isApplyPhysicsLocal() {
|
public boolean isApplyPhysicsLocal() {
|
||||||
return applyPhysicsLocal;
|
return applyPhysicsLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alter whether physics-space coordinates should match the spatial's local
|
||||||
|
* coordinates.
|
||||||
|
*
|
||||||
|
* @param applyPhysicsLocal true→match local coordinates,
|
||||||
|
* false→match world coordinates (default is false)
|
||||||
|
*/
|
||||||
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
|
||||||
this.applyPhysicsLocal = applyPhysicsLocal;
|
this.applyPhysicsLocal = applyPhysicsLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the unique id of the native object.
|
||||||
|
*
|
||||||
|
* @return id (not zero)
|
||||||
|
*/
|
||||||
public long getObjectId(){
|
public long getObjectId(){
|
||||||
return motionStateId;
|
return motionStateId;
|
||||||
}
|
}
|
||||||
@ -152,6 +190,12 @@ public class RigidBodyMotionState {
|
|||||||
// listeners.remove(listener);
|
// listeners.remove(listener);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this motion state just before it is destroyed. Should be invoked
|
||||||
|
* only by a subclass or by the garbage collector.
|
||||||
|
*
|
||||||
|
* @throws Throwable ignored by the garbage collector
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,14 +32,35 @@
|
|||||||
package com.jme3.bullet.objects.infos;
|
package com.jme3.bullet.objects.infos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Typical tuning parameters for a PhysicsVehicle.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class VehicleTuning {
|
public class VehicleTuning {
|
||||||
|
/**
|
||||||
|
* suspension stiffness constant (10→off-road buggy, 50→sports
|
||||||
|
* car, 200→Formula-1 race car, default=5.88)
|
||||||
|
*/
|
||||||
public float suspensionStiffness = 5.88f;
|
public float suspensionStiffness = 5.88f;
|
||||||
|
/**
|
||||||
|
* suspension damping when compressed (0→no damping, default=0.83)
|
||||||
|
*/
|
||||||
public float suspensionCompression = 0.83f;
|
public float suspensionCompression = 0.83f;
|
||||||
|
/**
|
||||||
|
* suspension damping when expanded (0→no damping, default=0.88)
|
||||||
|
*/
|
||||||
public float suspensionDamping = 0.88f;
|
public float suspensionDamping = 0.88f;
|
||||||
|
/**
|
||||||
|
* maximum suspension travel distance (in centimeters, default=500)
|
||||||
|
*/
|
||||||
public float maxSuspensionTravelCm = 500f;
|
public float maxSuspensionTravelCm = 500f;
|
||||||
|
/**
|
||||||
|
* maximum force exerted by each wheel's suspension (default=6000)
|
||||||
|
*/
|
||||||
public float maxSuspensionForce = 6000f;
|
public float maxSuspensionForce = 6000f;
|
||||||
|
/**
|
||||||
|
* coefficient of friction between tyres and ground (0.8→realistic car,
|
||||||
|
* 10000→kart racer, default=10.5)
|
||||||
|
*/
|
||||||
public float frictionSlip = 10.5f;
|
public float frictionSlip = 10.5f;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -44,6 +44,17 @@ public class DebugMeshCallback {
|
|||||||
|
|
||||||
private ArrayList<Vector3f> list = new ArrayList<Vector3f>();
|
private ArrayList<Vector3f> list = new ArrayList<Vector3f>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a vertex to the mesh under construction.
|
||||||
|
* <p>
|
||||||
|
* This method is invoked from native code.
|
||||||
|
*
|
||||||
|
* @param x local X coordinate of new vertex
|
||||||
|
* @param y local Y coordinate of new vertex
|
||||||
|
* @param z local Z coordinate of new vertex
|
||||||
|
* @param part ignored
|
||||||
|
* @param index ignored
|
||||||
|
*/
|
||||||
public void addVector(float x, float y, float z, int part, int index) {
|
public void addVector(float x, float y, float z, int part, int index) {
|
||||||
list.add(new Vector3f(x, y, z));
|
list.add(new Vector3f(x, y, z));
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2017 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -57,10 +57,13 @@ public class DebugShapeFactory {
|
|||||||
// private static final Vector3f aabbMin = new Vector3f(-1e30f, -1e30f, -1e30f);
|
// private static final Vector3f aabbMin = new Vector3f(-1e30f, -1e30f, -1e30f);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a debug shape from the given collision shape. This is mostly used internally.<br>
|
* Create a debug spatial from the specified collision shape.
|
||||||
* To attach a debug shape to a physics object, call <code>attachDebugShape(AssetManager manager);</code> on it.
|
* <p>
|
||||||
* @param collisionShape
|
* This is mostly used internally. To attach a debug shape to a physics
|
||||||
* @return
|
* object, call <code>attachDebugShape(AssetManager manager);</code> on it.
|
||||||
|
*
|
||||||
|
* @param collisionShape the shape to visualize (may be null, unaffected)
|
||||||
|
* @return a new tree of geometries, or null
|
||||||
*/
|
*/
|
||||||
public static Spatial getDebugShape(CollisionShape collisionShape) {
|
public static Spatial getDebugShape(CollisionShape collisionShape) {
|
||||||
if (collisionShape == null) {
|
if (collisionShape == null) {
|
||||||
@ -102,6 +105,12 @@ public class DebugShapeFactory {
|
|||||||
return debugShape;
|
return debugShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a geometry for visualizing the specified shape.
|
||||||
|
*
|
||||||
|
* @param shape (not null, unaffected)
|
||||||
|
* @return a new geometry (not null)
|
||||||
|
*/
|
||||||
private static Geometry createDebugShape(CollisionShape shape) {
|
private static Geometry createDebugShape(CollisionShape shape) {
|
||||||
Geometry geom = new Geometry();
|
Geometry geom = new Geometry();
|
||||||
geom.setMesh(DebugShapeFactory.getDebugMesh(shape));
|
geom.setMesh(DebugShapeFactory.getDebugMesh(shape));
|
||||||
@ -110,6 +119,12 @@ public class DebugShapeFactory {
|
|||||||
return geom;
|
return geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a mesh for visualizing the specified shape.
|
||||||
|
*
|
||||||
|
* @param shape (not null, unaffected)
|
||||||
|
* @return a new mesh (not null)
|
||||||
|
*/
|
||||||
public static Mesh getDebugMesh(CollisionShape shape) {
|
public static Mesh getDebugMesh(CollisionShape shape) {
|
||||||
Mesh mesh = new Mesh();
|
Mesh mesh = new Mesh();
|
||||||
DebugMeshCallback callback = new DebugMeshCallback();
|
DebugMeshCallback callback = new DebugMeshCallback();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user