/*
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* Bullet Continuous Collision Detection and Physics Library
* Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package com.bulletphysics.dynamics.vehicle;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.Stack;
import javax.vecmath.Vector3f;
/**
* WheelInfo contains information per wheel about friction and suspension.
*
* @author jezek2
*/
public class WheelInfo {
//protected final BulletStack stack = BulletStack.get();
public final RaycastInfo raycastInfo = new RaycastInfo();
public final Transform worldTransform = new Transform();
public final Vector3f chassisConnectionPointCS = new Vector3f(); // const
public final Vector3f wheelDirectionCS = new Vector3f(); // const
public final Vector3f wheelAxleCS = new Vector3f(); // const or modified by steering
public float suspensionRestLength1; // const
public float maxSuspensionTravelCm;
public float wheelsRadius; // const
public float suspensionStiffness; // const
public float wheelsDampingCompression; // const
public float wheelsDampingRelaxation; // const
public float frictionSlip;
public float steering;
public float rotation;
public float deltaRotation;
public float rollInfluence;
public float engineForce;
public float brake;
public boolean bIsFrontWheel;
public Object clientInfo; // can be used to store pointer to sync transforms...
public float clippedInvContactDotSuspension;
public float suspensionRelativeVelocity;
// calculated by suspension
public float wheelsSuspensionForce;
public float skidInfo;
public WheelInfo(WheelInfoConstructionInfo ci) {
suspensionRestLength1 = ci.suspensionRestLength;
maxSuspensionTravelCm = ci.maxSuspensionTravelCm;
wheelsRadius = ci.wheelRadius;
suspensionStiffness = ci.suspensionStiffness;
wheelsDampingCompression = ci.wheelsDampingCompression;
wheelsDampingRelaxation = ci.wheelsDampingRelaxation;
chassisConnectionPointCS.set(ci.chassisConnectionCS);
wheelDirectionCS.set(ci.wheelDirectionCS);
wheelAxleCS.set(ci.wheelAxleCS);
frictionSlip = ci.frictionSlip;
steering = 0f;
engineForce = 0f;
rotation = 0f;
deltaRotation = 0f;
brake = 0f;
rollInfluence = 0.1f;
bIsFrontWheel = ci.bIsFrontWheel;
}
public float getSuspensionRestLength() {
return suspensionRestLength1;
}
public void updateWheel(RigidBody chassis, RaycastInfo raycastInfo) {
if (raycastInfo.isInContact) {
Stack stack = Stack.enter();
float project = raycastInfo.contactNormalWS.dot(raycastInfo.wheelDirectionWS);
Vector3f chassis_velocity_at_contactPoint = stack.allocVector3f();
Vector3f relpos = stack.allocVector3f();
relpos.sub(raycastInfo.contactPointWS, chassis.getCenterOfMassPosition(stack.allocVector3f()));
chassis.getVelocityInLocalPoint(relpos, chassis_velocity_at_contactPoint);
float projVel = raycastInfo.contactNormalWS.dot(chassis_velocity_at_contactPoint);
if (project >= -0.1f) {
suspensionRelativeVelocity = 0f;
clippedInvContactDotSuspension = 1f / 0.1f;
}
else {
float inv = -1f / project;
suspensionRelativeVelocity = projVel * inv;
clippedInvContactDotSuspension = inv;
}
stack.leave();
}
else {
// Not in contact : position wheel in a nice (rest length) position
raycastInfo.suspensionLength = getSuspensionRestLength();
suspensionRelativeVelocity = 0f;
raycastInfo.contactNormalWS.negate(raycastInfo.wheelDirectionWS);
clippedInvContactDotSuspension = 1f;
}
}
////////////////////////////////////////////////////////////////////////////
public static class RaycastInfo {
// set by raycaster
public final Vector3f contactNormalWS = new Vector3f(); // contactnormal
public final Vector3f contactPointWS = new Vector3f(); // raycast hitpoint
public float suspensionLength;
public final Vector3f hardPointWS = new Vector3f(); // raycast starting point
public final Vector3f wheelDirectionWS = new Vector3f(); // direction in worldspace
public final Vector3f wheelAxleWS = new Vector3f(); // axle in worldspace
public boolean isInContact;
public Object groundObject; // could be general void* ptr
}
}