aboutsummaryrefslogtreecommitdiff
path: root/engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java')
-rw-r--r--engine/src/bullet/com/jme3/bullet/objects/VehicleWheel.java423
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;
+ }
+
+}