All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jme3.bullet.objects.VehicleWheel Maven / Gradle / Ivy

/*
 * Copyright (c) 2009-2018 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jme3.bullet.objects;

import com.bulletphysics.dynamics.RigidBody;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.util.Converter;
import com.jme3.export.*;
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 com.bulletphysics.dynamics.vehicle.WheelInfo wheelInfo;
    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 com.jme3.math.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 void updatePhysicsState() {
        Converter.convert(wheelInfo.worldTransform.origin, wheelWorldLocation);
        Converter.convert(wheelInfo.worldTransform.basis, tmp_Matrix);
        wheelWorldRotation.fromRotationMatrix(tmp_Matrix);
    }

    public 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 com.bulletphysics.dynamics.vehicle.WheelInfo getWheelInfo() {
        return wheelInfo;
    }

    public void setWheelInfo(com.bulletphysics.dynamics.vehicle.WheelInfo wheelInfo) {
        this.wheelInfo = wheelInfo;
        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.
* k = 0.0 undamped & bouncy, k = 1.0 critical damping
* 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 vehicle. * @param maxSuspensionForce */ public void setMaxSuspensionForce(float maxSuspensionForce) { this.maxSuspensionForce = maxSuspensionForce; applyInfo(); } private void applyInfo() { if (wheelInfo == null) { return; } wheelInfo.suspensionStiffness = suspensionStiffness; wheelInfo.wheelsDampingRelaxation = wheelsDampingRelaxation; wheelInfo.wheelsDampingCompression = wheelsDampingCompression; wheelInfo.frictionSlip = frictionSlip; wheelInfo.rollInfluence = rollInfluence; wheelInfo.maxSuspensionTravelCm = maxSuspensionTravelCm; wheelInfo.maxSuspensionForce = maxSuspensionForce; wheelInfo.wheelsRadius = radius; wheelInfo.bIsFrontWheel = frontWheel; wheelInfo.suspensionRestLength1 = restLength; } 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) { Converter.convert(wheelInfo.raycastInfo.contactPointWS, vec); return vec; } /** * returns the location where the wheel collides with the ground (world space) */ public Vector3f getCollisionLocation() { return Converter.convert(wheelInfo.raycastInfo.contactPointWS); } /** * returns the normal where the wheel collides with the ground (world space) */ public Vector3f getCollisionNormal(Vector3f vec) { Converter.convert(wheelInfo.raycastInfo.contactNormalWS, vec); return vec; } /** * returns the normal where the wheel collides with the ground (world space) */ public Vector3f getCollisionNormal() { return Converter.convert(wheelInfo.raycastInfo.contactNormalWS); } /** * returns how much the wheel skids on the ground (for skid sounds/smoke etc.)
* 0.0 = wheels are sliding, 1.0 = wheels have traction. */ public float getSkidInfo() { return wheelInfo.skidInfo; } /** * returns how many degrees the wheel has turned since the last physics * step. */ public float getDeltaRotation() { return wheelInfo.deltaRotation; } @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; } /** * write the content of the wheelWorldRotation into the store * * @param store */ public void getWheelWorldRotation(final Quaternion store) { store.set(this.wheelWorldRotation); } /** * write the content of the wheelWorldLocation into the store * * @param store */ public void getWheelWorldLocation(final Vector3f store) { store.set(this.wheelWorldLocation); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy