File: src/objects/RigidVehicle.js
- var Body = require('./Body');
- var Sphere = require('../shapes/Sphere');
- var Box = require('../shapes/Box');
- var Vec3 = require('../math/Vec3');
- var HingeConstraint = require('../constraints/HingeConstraint');
-
- module.exports = RigidVehicle;
-
- /**
- * Simple vehicle helper class with spherical rigid body wheels.
- * @class RigidVehicle
- * @constructor
- * @param {Body} [options.chassisBody]
- */
- function RigidVehicle(options){
- this.wheelBodies = [];
-
- /**
- * @property coordinateSystem
- * @type {Vec3}
- */
- this.coordinateSystem = typeof(options.coordinateSystem)==='undefined' ? new Vec3(1, 2, 3) : options.coordinateSystem.clone();
-
- /**
- * @property {Body} chassisBody
- */
- this.chassisBody = options.chassisBody;
-
- if(!this.chassisBody){
- // No chassis body given. Create it!
- var chassisShape = new Box(new Vec3(5, 2, 0.5));
- this.chassisBody = new Body(1, chassisShape);
- }
-
- /**
- * @property constraints
- * @type {Array}
- */
- this.constraints = [];
-
- this.wheelAxes = [];
- this.wheelForces = [];
- }
-
- /**
- * Add a wheel
- * @method addWheel
- * @param {object} options
- * @param {boolean} [options.isFrontWheel]
- * @param {Vec3} [options.position] Position of the wheel, locally in the chassis body.
- * @param {Vec3} [options.direction] Slide direction of the wheel along the suspension.
- * @param {Vec3} [options.axis] Axis of rotation of the wheel, locally defined in the chassis.
- * @param {Body} [options.body] The wheel body.
- */
- RigidVehicle.prototype.addWheel = function(options){
- options = options || {};
- var wheelBody = options.body;
- if(!wheelBody){
- wheelBody = new Body(1, new Sphere(1.2));
- }
- this.wheelBodies.push(wheelBody);
- this.wheelForces.push(0);
-
- // Position constrain wheels
- var zero = new Vec3();
- var position = typeof(options.position) !== 'undefined' ? options.position.clone() : new Vec3();
-
- // Set position locally to the chassis
- var worldPosition = new Vec3();
- this.chassisBody.pointToWorldFrame(position, worldPosition);
- wheelBody.position.set(worldPosition.x, worldPosition.y, worldPosition.z);
-
- // Constrain wheel
- var axis = typeof(options.axis) !== 'undefined' ? options.axis.clone() : new Vec3(0, 1, 0);
- this.wheelAxes.push(axis);
-
- var hingeConstraint = new HingeConstraint(this.chassisBody, wheelBody, {
- pivotA: position,
- axisA: axis,
- pivotB: Vec3.ZERO,
- axisB: axis,
- collideConnected: false
- });
- this.constraints.push(hingeConstraint);
-
- return this.wheelBodies.length - 1;
- };
-
- /**
- * Set the steering value of a wheel.
- * @method setSteeringValue
- * @param {number} value
- * @param {integer} wheelIndex
- * @todo check coordinateSystem
- */
- RigidVehicle.prototype.setSteeringValue = function(value, wheelIndex){
- // Set angle of the hinge axis
- var axis = this.wheelAxes[wheelIndex];
-
- var c = Math.cos(value),
- s = Math.sin(value),
- x = axis.x,
- y = axis.y;
- this.constraints[wheelIndex].axisA.set(
- c*x -s*y,
- s*x +c*y,
- 0
- );
- };
-
- /**
- * Set the target rotational speed of the hinge constraint.
- * @method setMotorSpeed
- * @param {number} value
- * @param {integer} wheelIndex
- */
- RigidVehicle.prototype.setMotorSpeed = function(value, wheelIndex){
- var hingeConstraint = this.constraints[wheelIndex];
- hingeConstraint.enableMotor();
- hingeConstraint.motorTargetVelocity = value;
- };
-
- /**
- * Set the target rotational speed of the hinge constraint.
- * @method disableMotor
- * @param {number} value
- * @param {integer} wheelIndex
- */
- RigidVehicle.prototype.disableMotor = function(wheelIndex){
- var hingeConstraint = this.constraints[wheelIndex];
- hingeConstraint.disableMotor();
- };
-
- var torque = new Vec3();
-
- /**
- * Set the wheel force to apply on one of the wheels each time step
- * @method setWheelForce
- * @param {number} value
- * @param {integer} wheelIndex
- */
- RigidVehicle.prototype.setWheelForce = function(value, wheelIndex){
- this.wheelForces[wheelIndex] = value;
- };
-
- /**
- * Apply a torque on one of the wheels.
- * @method applyWheelForce
- * @param {number} value
- * @param {integer} wheelIndex
- */
- RigidVehicle.prototype.applyWheelForce = function(value, wheelIndex){
- var axis = this.wheelAxes[wheelIndex];
- var wheelBody = this.wheelBodies[wheelIndex];
- var bodyTorque = wheelBody.torque;
-
- axis.scale(value, torque);
- wheelBody.vectorToWorldFrame(torque, torque);
- bodyTorque.vadd(torque, bodyTorque);
- };
-
- /**
- * Add the vehicle including its constraints to the world.
- * @method addToWorld
- * @param {World} world
- */
- RigidVehicle.prototype.addToWorld = function(world){
- var constraints = this.constraints;
- var bodies = this.wheelBodies.concat([this.chassisBody]);
-
- for (var i = 0; i < bodies.length; i++) {
- world.add(bodies[i]);
- }
-
- for (var i = 0; i < constraints.length; i++) {
- world.addConstraint(constraints[i]);
- }
-
- world.addEventListener('preStep', this._update.bind(this));
- };
-
- RigidVehicle.prototype._update = function(){
- var wheelForces = this.wheelForces;
- for (var i = 0; i < wheelForces.length; i++) {
- this.applyWheelForce(wheelForces[i], i);
- }
- };
-
- /**
- * Remove the vehicle including its constraints from the world.
- * @method removeFromWorld
- * @param {World} world
- */
- RigidVehicle.prototype.removeFromWorld = function(world){
- var constraints = this.constraints;
- var bodies = this.wheelBodies.concat([this.chassisBody]);
-
- for (var i = 0; i < bodies.length; i++) {
- world.remove(bodies[i]);
- }
-
- for (var i = 0; i < constraints.length; i++) {
- world.removeConstraint(constraints[i]);
- }
- };
-
- var worldAxis = new Vec3();
-
- /**
- * Get current rotational velocity of a wheel
- * @method getWheelSpeed
- * @param {integer} wheelIndex
- */
- RigidVehicle.prototype.getWheelSpeed = function(wheelIndex){
- var axis = this.wheelAxes[wheelIndex];
- var wheelBody = this.wheelBodies[wheelIndex];
- var w = wheelBody.angularVelocity;
- this.chassisBody.vectorToWorldFrame(axis, worldAxis);
- return w.dot(worldAxis);
- };
-
-