diff options
Diffstat (limited to 'engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java')
-rw-r--r-- | engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java b/engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java new file mode 100644 index 0000000..11eab60 --- /dev/null +++ b/engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2009-2010 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.bullet.objects; + +import com.jme3.bullet.collision.PhysicsCollisionObject; +import com.jme3.export.*; +import com.jme3.math.Matrix3f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.io.IOException; + +/** + * Stores info about one wheel of a PhysicsVehicle + * @author normenhansen + */ +public class VehicleWheel implements Savable { + + protected long wheelId = 0; + protected int wheelIndex = 0; + protected boolean frontWheel; + protected Vector3f location = new Vector3f(); + protected Vector3f direction = new Vector3f(); + protected Vector3f axle = new Vector3f(); + protected float suspensionStiffness = 20.0f; + protected float wheelsDampingRelaxation = 2.3f; + protected float wheelsDampingCompression = 4.4f; + protected float frictionSlip = 10.5f; + protected float rollInfluence = 1.0f; + protected float maxSuspensionTravelCm = 500f; + protected float maxSuspensionForce = 6000f; + protected float radius = 0.5f; + protected float restLength = 1f; + protected Vector3f wheelWorldLocation = new Vector3f(); + protected Quaternion wheelWorldRotation = new Quaternion(); + protected Spatial wheelSpatial; + protected Matrix3f tmp_Matrix = new com.jme3.math.Matrix3f(); + protected final Quaternion tmp_inverseWorldRotation = new Quaternion(); + private boolean applyLocal = false; + + public VehicleWheel() { + } + + public VehicleWheel(Spatial spat, Vector3f location, Vector3f direction, Vector3f axle, + float restLength, float radius, boolean frontWheel) { + this(location, direction, axle, restLength, radius, frontWheel); + wheelSpatial = spat; + } + + public VehicleWheel(Vector3f location, Vector3f direction, Vector3f axle, + float restLength, float radius, boolean frontWheel) { + this.location.set(location); + this.direction.set(direction); + this.axle.set(axle); + this.frontWheel = frontWheel; + this.restLength = restLength; + this.radius = radius; + } + + public synchronized void updatePhysicsState() { + getWheelLocation(wheelId, wheelIndex, wheelWorldLocation); + getWheelRotation(wheelId, wheelIndex, tmp_Matrix); + wheelWorldRotation.fromRotationMatrix(tmp_Matrix); + } + + private native void getWheelLocation(long vehicleId, int wheelId, Vector3f location); + + private native void getWheelRotation(long vehicleId, int wheelId, Matrix3f location); + + public synchronized void applyWheelTransform() { + if (wheelSpatial == null) { + return; + } + Quaternion localRotationQuat = wheelSpatial.getLocalRotation(); + Vector3f localLocation = wheelSpatial.getLocalTranslation(); + if (!applyLocal && wheelSpatial.getParent() != null) { + localLocation.set(wheelWorldLocation).subtractLocal(wheelSpatial.getParent().getWorldTranslation()); + localLocation.divideLocal(wheelSpatial.getParent().getWorldScale()); + tmp_inverseWorldRotation.set(wheelSpatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation); + + localRotationQuat.set(wheelWorldRotation); + tmp_inverseWorldRotation.set(wheelSpatial.getParent().getWorldRotation()).inverseLocal().mult(localRotationQuat, localRotationQuat); + + wheelSpatial.setLocalTranslation(localLocation); + wheelSpatial.setLocalRotation(localRotationQuat); + } else { + wheelSpatial.setLocalTranslation(wheelWorldLocation); + wheelSpatial.setLocalRotation(wheelWorldRotation); + } + } + + public long getWheelId() { + return wheelId; + } + + public void setVehicleId(long vehicleId, int wheelIndex) { + this.wheelId = vehicleId; + this.wheelIndex = wheelIndex; + applyInfo(); + } + + public boolean isFrontWheel() { + return frontWheel; + } + + public void setFrontWheel(boolean frontWheel) { + this.frontWheel = frontWheel; + applyInfo(); + } + + public Vector3f getLocation() { + return location; + } + + public Vector3f getDirection() { + return direction; + } + + public Vector3f getAxle() { + return axle; + } + + public float getSuspensionStiffness() { + return suspensionStiffness; + } + + /** + * the stiffness constant for the suspension. 10.0 - Offroad buggy, 50.0 - Sports car, 200.0 - F1 Car + * @param suspensionStiffness + */ + public void setSuspensionStiffness(float suspensionStiffness) { + this.suspensionStiffness = suspensionStiffness; + applyInfo(); + } + + public float getWheelsDampingRelaxation() { + return wheelsDampingRelaxation; + } + + /** + * the damping coefficient for when the suspension is expanding. + * See the comments for setWheelsDampingCompression for how to set k. + * @param wheelsDampingRelaxation + */ + public void setWheelsDampingRelaxation(float wheelsDampingRelaxation) { + this.wheelsDampingRelaxation = wheelsDampingRelaxation; + applyInfo(); + } + + public float getWheelsDampingCompression() { + return wheelsDampingCompression; + } + + /** + * the damping coefficient for when the suspension is compressed. + * Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.<br> + * k = 0.0 undamped & bouncy, k = 1.0 critical damping<br> + * 0.1 to 0.3 are good values + * @param wheelsDampingCompression + */ + public void setWheelsDampingCompression(float wheelsDampingCompression) { + this.wheelsDampingCompression = wheelsDampingCompression; + applyInfo(); + } + + public float getFrictionSlip() { + return frictionSlip; + } + + /** + * the coefficient of friction between the tyre and the ground. + * Should be about 0.8 for realistic cars, but can increased for better handling. + * Set large (10000.0) for kart racers + * @param frictionSlip + */ + public void setFrictionSlip(float frictionSlip) { + this.frictionSlip = frictionSlip; + applyInfo(); + } + + public float getRollInfluence() { + return rollInfluence; + } + + /** + * reduces the rolling torque applied from the wheels that cause the vehicle to roll over. + * This is a bit of a hack, but it's quite effective. 0.0 = no roll, 1.0 = physical behaviour. + * If m_frictionSlip is too high, you'll need to reduce this to stop the vehicle rolling over. + * You should also try lowering the vehicle's centre of mass + * @param rollInfluence the rollInfluence to set + */ + public void setRollInfluence(float rollInfluence) { + this.rollInfluence = rollInfluence; + applyInfo(); + } + + public float getMaxSuspensionTravelCm() { + return maxSuspensionTravelCm; + } + + /** + * the maximum distance the suspension can be compressed (centimetres) + * @param maxSuspensionTravelCm + */ + public void setMaxSuspensionTravelCm(float maxSuspensionTravelCm) { + this.maxSuspensionTravelCm = maxSuspensionTravelCm; + applyInfo(); + } + + public float getMaxSuspensionForce() { + return maxSuspensionForce; + } + + /** + * The maximum suspension force, raise this above the default 6000 if your suspension cannot + * handle the weight of your vehcile. + * @param maxSuspensionTravelCm + */ + public void setMaxSuspensionForce(float maxSuspensionForce) { + this.maxSuspensionForce = maxSuspensionForce; + applyInfo(); + } + + private void applyInfo() { + if (wheelId == 0) { + return; + } + applyInfo(wheelId, wheelIndex, suspensionStiffness, wheelsDampingRelaxation, wheelsDampingCompression, frictionSlip, rollInfluence, maxSuspensionTravelCm, maxSuspensionForce, radius, frontWheel, restLength); + } + + private native void applyInfo(long wheelId, int wheelIndex, + float suspensionStiffness, + float wheelsDampingRelaxation, + float wheelsDampingCompression, + float frictionSlip, + float rollInfluence, + float maxSuspensionTravelCm, + float maxSuspensionForce, + float wheelsRadius, + boolean frontWheel, + float suspensionRestLength); + + public float getRadius() { + return radius; + } + + public void setRadius(float radius) { + this.radius = radius; + applyInfo(); + } + + public float getRestLength() { + return restLength; + } + + public void setRestLength(float restLength) { + this.restLength = restLength; + applyInfo(); + } + + /** + * returns the object this wheel is in contact with or null if no contact + * @return the PhysicsCollisionObject (PhysicsRigidBody, PhysicsGhostObject) + */ + public PhysicsCollisionObject getGroundObject() { +// if (wheelInfo.raycastInfo.groundObject == null) { +// return null; +// } else if (wheelInfo.raycastInfo.groundObject instanceof RigidBody) { +// System.out.println("RigidBody"); +// return (PhysicsRigidBody) ((RigidBody) wheelInfo.raycastInfo.groundObject).getUserPointer(); +// } else { + return null; +// } + } + + /** + * returns the location where the wheel collides with the ground (world space) + */ + public Vector3f getCollisionLocation(Vector3f vec) { + getCollisionLocation(wheelId, wheelIndex, vec); + return vec; + } + + private native void getCollisionLocation(long wheelId, int wheelIndex, Vector3f vec); + + /** + * returns the location where the wheel collides with the ground (world space) + */ + public Vector3f getCollisionLocation() { + Vector3f vec = new Vector3f(); + getCollisionLocation(wheelId, wheelIndex, vec); + return vec; + } + + /** + * returns the normal where the wheel collides with the ground (world space) + */ + public Vector3f getCollisionNormal(Vector3f vec) { + getCollisionNormal(wheelId, wheelIndex, vec); + return vec; + } + + private native void getCollisionNormal(long wheelId, int wheelIndex, Vector3f vec); + + /** + * returns the normal where the wheel collides with the ground (world space) + */ + public Vector3f getCollisionNormal() { + Vector3f vec = new Vector3f(); + getCollisionNormal(wheelId, wheelIndex, vec); + return vec; + } + + /** + * returns how much the wheel skids on the ground (for skid sounds/smoke etc.)<br> + * 0.0 = wheels are sliding, 1.0 = wheels have traction. + */ + public float getSkidInfo() { + return getSkidInfo(wheelId, wheelIndex); + } + + public native float getSkidInfo(long wheelId, int wheelIndex); + + /** + * returns how many degrees the wheel has turned since the last physics + * step. + */ + public float getDeltaRotation() { + return getDeltaRotation(wheelId, wheelIndex); + } + + public native float getDeltaRotation(long wheelId, int wheelIndex); + + @Override + public void read(JmeImporter im) throws IOException { + InputCapsule capsule = im.getCapsule(this); + wheelSpatial = (Spatial) capsule.readSavable("wheelSpatial", null); + frontWheel = capsule.readBoolean("frontWheel", false); + location = (Vector3f) capsule.readSavable("wheelLocation", new Vector3f()); + direction = (Vector3f) capsule.readSavable("wheelDirection", new Vector3f()); + axle = (Vector3f) capsule.readSavable("wheelAxle", new Vector3f()); + suspensionStiffness = capsule.readFloat("suspensionStiffness", 20.0f); + wheelsDampingRelaxation = capsule.readFloat("wheelsDampingRelaxation", 2.3f); + wheelsDampingCompression = capsule.readFloat("wheelsDampingCompression", 4.4f); + frictionSlip = capsule.readFloat("frictionSlip", 10.5f); + rollInfluence = capsule.readFloat("rollInfluence", 1.0f); + maxSuspensionTravelCm = capsule.readFloat("maxSuspensionTravelCm", 500f); + maxSuspensionForce = capsule.readFloat("maxSuspensionForce", 6000f); + radius = capsule.readFloat("wheelRadius", 0.5f); + restLength = capsule.readFloat("restLength", 1f); + } + + @Override + public void write(JmeExporter ex) throws IOException { + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(wheelSpatial, "wheelSpatial", null); + capsule.write(frontWheel, "frontWheel", false); + capsule.write(location, "wheelLocation", new Vector3f()); + capsule.write(direction, "wheelDirection", new Vector3f()); + capsule.write(axle, "wheelAxle", new Vector3f()); + capsule.write(suspensionStiffness, "suspensionStiffness", 20.0f); + capsule.write(wheelsDampingRelaxation, "wheelsDampingRelaxation", 2.3f); + capsule.write(wheelsDampingCompression, "wheelsDampingCompression", 4.4f); + capsule.write(frictionSlip, "frictionSlip", 10.5f); + capsule.write(rollInfluence, "rollInfluence", 1.0f); + capsule.write(maxSuspensionTravelCm, "maxSuspensionTravelCm", 500f); + capsule.write(maxSuspensionForce, "maxSuspensionForce", 6000f); + capsule.write(radius, "wheelRadius", 0.5f); + capsule.write(restLength, "restLength", 1f); + } + + /** + * @return the wheelSpatial + */ + public Spatial getWheelSpatial() { + return wheelSpatial; + } + + /** + * @param wheelSpatial the wheelSpatial to set + */ + public void setWheelSpatial(Spatial wheelSpatial) { + this.wheelSpatial = wheelSpatial; + } + + public boolean isApplyLocal() { + return applyLocal; + } + + public void setApplyLocal(boolean applyLocal) { + this.applyLocal = applyLocal; + } + +} |