var Vec3 = require('../math/Vec3'); var Transform = require('../math/Transform'); var RaycastResult = require('../collision/RaycastResult'); var Utils = require('../utils/Utils'); module.exports = WheelInfo; /** * @class WheelInfo * @constructor * @param {Object} [options] * * @param {Vec3} [options.chassisConnectionPointLocal] * @param {Vec3} [options.chassisConnectionPointWorld] * @param {Vec3} [options.directionLocal] * @param {Vec3} [options.directionWorld] * @param {Vec3} [options.axleLocal] * @param {Vec3} [options.axleWorld] * @param {number} [options.suspensionRestLength=1] * @param {number} [options.suspensionMaxLength=2] * @param {number} [options.radius=1] * @param {number} [options.suspensionStiffness=100] * @param {number} [options.dampingCompression=10] * @param {number} [options.dampingRelaxation=10] * @param {number} [options.frictionSlip=10000] * @param {number} [options.steering=0] * @param {number} [options.rotation=0] * @param {number} [options.deltaRotation=0] * @param {number} [options.rollInfluence=0.01] * @param {number} [options.maxSuspensionForce] * @param {boolean} [options.isFrontWheel=true] * @param {number} [options.clippedInvContactDotSuspension=1] * @param {number} [options.suspensionRelativeVelocity=0] * @param {number} [options.suspensionForce=0] * @param {number} [options.skidInfo=0] * @param {number} [options.suspensionLength=0] * @param {number} [options.maxSuspensionTravel=1] * @param {boolean} [options.useCustomSlidingRotationalSpeed=false] * @param {number} [options.customSlidingRotationalSpeed=-0.1] */ function WheelInfo(options){ options = Utils.defaults(options, { chassisConnectionPointLocal: new Vec3(), chassisConnectionPointWorld: new Vec3(), directionLocal: new Vec3(), directionWorld: new Vec3(), axleLocal: new Vec3(), axleWorld: new Vec3(), suspensionRestLength: 1, suspensionMaxLength: 2, radius: 1, suspensionStiffness: 100, dampingCompression: 10, dampingRelaxation: 10, frictionSlip: 10000, steering: 0, rotation: 0, deltaRotation: 0, rollInfluence: 0.01, maxSuspensionForce: Number.MAX_VALUE, isFrontWheel: true, clippedInvContactDotSuspension: 1, suspensionRelativeVelocity: 0, suspensionForce: 0, skidInfo: 0, suspensionLength: 0, maxSuspensionTravel: 1, useCustomSlidingRotationalSpeed: false, customSlidingRotationalSpeed: -0.1 }); /** * Max travel distance of the suspension, in meters. * @property {number} maxSuspensionTravel */ this.maxSuspensionTravel = options.maxSuspensionTravel; /** * Speed to apply to the wheel rotation when the wheel is sliding. * @property {number} customSlidingRotationalSpeed */ this.customSlidingRotationalSpeed = options.customSlidingRotationalSpeed; /** * If the customSlidingRotationalSpeed should be used. * @property {Boolean} useCustomSlidingRotationalSpeed */ this.useCustomSlidingRotationalSpeed = options.useCustomSlidingRotationalSpeed; /** * @property {Boolean} sliding */ this.sliding = false; /** * Connection point, defined locally in the chassis body frame. * @property {Vec3} chassisConnectionPointLocal */ this.chassisConnectionPointLocal = options.chassisConnectionPointLocal.clone(); /** * @property {Vec3} chassisConnectionPointWorld */ this.chassisConnectionPointWorld = options.chassisConnectionPointWorld.clone(); /** * @property {Vec3} directionLocal */ this.directionLocal = options.directionLocal.clone(); /** * @property {Vec3} directionWorld */ this.directionWorld = options.directionWorld.clone(); /** * @property {Vec3} axleLocal */ this.axleLocal = options.axleLocal.clone(); /** * @property {Vec3} axleWorld */ this.axleWorld = options.axleWorld.clone(); /** * @property {number} suspensionRestLength */ this.suspensionRestLength = options.suspensionRestLength; /** * @property {number} suspensionMaxLength */ this.suspensionMaxLength = options.suspensionMaxLength; /** * @property {number} radius */ this.radius = options.radius; /** * @property {number} suspensionStiffness */ this.suspensionStiffness = options.suspensionStiffness; /** * @property {number} dampingCompression */ this.dampingCompression = options.dampingCompression; /** * @property {number} dampingRelaxation */ this.dampingRelaxation = options.dampingRelaxation; /** * @property {number} frictionSlip */ this.frictionSlip = options.frictionSlip; /** * @property {number} steering */ this.steering = 0; /** * Rotation value, in radians. * @property {number} rotation */ this.rotation = 0; /** * @property {number} deltaRotation */ this.deltaRotation = 0; /** * @property {number} rollInfluence */ this.rollInfluence = options.rollInfluence; /** * @property {number} maxSuspensionForce */ this.maxSuspensionForce = options.maxSuspensionForce; /** * @property {number} engineForce */ this.engineForce = 0; /** * @property {number} brake */ this.brake = 0; /** * @property {number} isFrontWheel */ this.isFrontWheel = options.isFrontWheel; /** * @property {number} clippedInvContactDotSuspension */ this.clippedInvContactDotSuspension = 1; /** * @property {number} suspensionRelativeVelocity */ this.suspensionRelativeVelocity = 0; /** * @property {number} suspensionForce */ this.suspensionForce = 0; /** * @property {number} skidInfo */ this.skidInfo = 0; /** * @property {number} suspensionLength */ this.suspensionLength = 0; /** * @property {number} sideImpulse */ this.sideImpulse = 0; /** * @property {number} forwardImpulse */ this.forwardImpulse = 0; /** * The result from raycasting * @property {RaycastResult} raycastResult */ this.raycastResult = new RaycastResult(); /** * Wheel world transform * @property {Transform} worldTransform */ this.worldTransform = new Transform(); /** * @property {boolean} isInContact */ this.isInContact = false; } var chassis_velocity_at_contactPoint = new Vec3(); var relpos = new Vec3(); var chassis_velocity_at_contactPoint = new Vec3(); WheelInfo.prototype.updateWheel = function(chassis){ var raycastResult = this.raycastResult; if (this.isInContact){ var project= raycastResult.hitNormalWorld.dot(raycastResult.directionWorld); raycastResult.hitPointWorld.vsub(chassis.position, relpos); chassis.getVelocityAtWorldPoint(relpos, chassis_velocity_at_contactPoint); var projVel = raycastResult.hitNormalWorld.dot( chassis_velocity_at_contactPoint ); if (project >= -0.1) { this.suspensionRelativeVelocity = 0.0; this.clippedInvContactDotSuspension = 1.0 / 0.1; } else { var inv = -1 / project; this.suspensionRelativeVelocity = projVel * inv; this.clippedInvContactDotSuspension = inv; } } else { // Not in contact : position wheel in a nice (rest length) position raycastResult.suspensionLength = this.suspensionRestLength; this.suspensionRelativeVelocity = 0.0; raycastResult.directionWorld.scale(-1, raycastResult.hitNormalWorld); this.clippedInvContactDotSuspension = 1.0; } };