/** * This component makes the parentEntity (ex. car) follow the path provided by the spline * @param graphics R3.GraphicsRuntime * @param apiPathFollowing R3.D3.API.PathFollowing * @constructor */ R3.D3.PathFollowing = function ( graphics, apiPathFollowing ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (R3.Utils.UndefinedOrNull(apiPathFollowing)) { apiPathFollowing = {}; } if (apiPathFollowing instanceof R3.D3.PathFollowing) { return apiPathFollowing; } R3.D3.API.PathFollowing.call( this, apiPathFollowing.id, apiPathFollowing.name, apiPathFollowing.spline, apiPathFollowing.mesh, apiPathFollowing.raytraceMesh, apiPathFollowing.accelleration, apiPathFollowing.maxSpeed, apiPathFollowing.baseOffset, apiPathFollowing.maxOffset, apiPathFollowing.steeringSpeed, apiPathFollowing.targetOffset, apiPathFollowing.currentOffset, apiPathFollowing.currentPathValue, apiPathFollowing.currentSpeed, apiPathFollowing.direction, apiPathFollowing.raycaster, apiPathFollowing.currentPosition, apiPathFollowing.futurePosition, apiPathFollowing.up, apiPathFollowing.rotationMatrix, apiPathFollowing.rotationVector, apiPathFollowing.parentEntity ); this.baseOffset = new R3.Vector3( this.graphics, this.baseOffset, this ); this.maxOffset = new R3.Vector3( this.graphics, this.maxOffset, this ); this.targetOffset = new R3.Vector3( this.graphics, this.targetOffset, this ); this.currentOffset = new R3.Vector3( this.graphics, this.currentOffset, this ); this.raycaster = new R3.D3.Raycaster( this.graphics, this.raycaster ); this.currentPosition = new R3.Vector3( this.graphics, this.currentPosition, this ); this.futurePosition = new R3.Vector3( this.graphics, this.futurePosition, this ); this.up = new R3.Vector3( this.graphics, this.up, this ); this.rotationMatrix = new R3.Matrix4( this.graphics, this.rotationMatrix, this ); this.rotationVector = new R3.Quaternion( this.graphics, this.rotationVector, this ); this.mx = new R3.Utils.MovingAverage(10); this.my = new R3.Utils.MovingAverage(10); this.mz = new R3.Utils.MovingAverage(10); R3.Component.call( this, R3.Component.COMPONENT_PATH_FOLLOWING, { 'spline': R3.D3.Spline, 'mesh' : R3.D3.Mesh, 'raytraceMesh' : R3.D3.Mesh } ); }; R3.D3.PathFollowing.prototype = Object.create(R3.D3.API.PathFollowing.prototype); R3.D3.PathFollowing.prototype.constructor = R3.D3.PathFollowing; R3.D3.PathFollowing.prototype.createInstance = function() { console.log('R3.D3.PathFollowing.prototype.createInstance()'); R3.Component.prototype.createInstance.call(this); }; R3.D3.PathFollowing.prototype.toApiObject = function() { var apiPathFollowing = new R3.D3.API.PathFollowing( this.id, this.name, R3.Utils.IdOrNull(this.spline), R3.Utils.IdOrNull(this.mesh), R3.Utils.IdOrNull(this.raytraceMesh), this.accelleration, this.maxSpeed, this.baseOffset.toApiObject(), this.maxOffset.toApiObject(), this.steeringSpeed, this.targetOffset.toApiObject(), this.currentOffset.toApiObject(), this.currentPathValue, this.currentSpeed, this.direction, this.raycaster.toApiObject(), this.currentPosition.toApiObject(), this.futurePosition.toApiObject(), this.up.toApiObject(), this.rotationMatrix.toApiObject(), this.rotationVector.toApiObject(), R3.Utils.IdOrNull(this.parentEntity) ); return apiPathFollowing; }; /** * Object path following to R3.D3.PathFollowing * @param graphics * @param objectComponent * @returns {R3.D3.PathFollowing} * @constructor */ R3.D3.PathFollowing.FromObject = function(graphics, objectComponent) { var apiPathFollowing = R3.D3.API.PathFollowing.FromObject(objectComponent); return new R3.D3.PathFollowing( graphics, apiPathFollowing ); }; /** * Updates the component * @param deltaTime */ R3.D3.PathFollowing.prototype.update = function(deltaTime) { if (this.spline && this.mesh && this.raytraceMesh) { this.currentSpeed += this.accelleration * deltaTime * this.direction; if(this.currentSpeed > this.maxSpeed) { this.currentSpeed = this.maxSpeed; } this.grain = (this.currentSpeed / 100.0); var currentPosition = this.spline.getPointAt(this.currentPathValue); this.currentPosition.x = currentPosition.x; this.currentPosition.y = currentPosition.y; this.currentPosition.z = currentPosition.z; this.currentPathValue += this.grain; if (this.currentPathValue >= 1) { this.currentPathValue = this.currentPathValue - 1; } if (this.currentPathValue < 0) { this.currentPathValue = 0.0; } var futurePosition = this.spline.getPointAt(this.currentPathValue); this.futurePosition.x = futurePosition.x; this.futurePosition.y = futurePosition.y; this.futurePosition.z = futurePosition.z; this.raycaster.setPosition( this.currentPosition ); this.raycaster.setDirection( { x : -this.up.x, y : -this.up.y, z : -this.up.z } ); var normal = this.raycaster.getFaceNormal(this.raytraceMesh); if (normal) { this.up.x = this.mx(normal.x); this.up.y = this.my(normal.y); this.up.z = this.mz(normal.z); } this.rotationMatrix.lookAt( this.currentPosition, this.futurePosition, this.up ); this.rotationVector.setFromRotationMatrix(this.rotationMatrix); this.mesh.position.x = this.futurePosition.x; this.mesh.position.y = this.futurePosition.y; this.mesh.position.z = this.futurePosition.z; /** * Update Rotation */ this.mesh.quaternion.x = this.rotationVector.x; this.mesh.quaternion.y = this.rotationVector.y; this.mesh.quaternion.z = this.rotationVector.z; this.mesh.quaternion.w = this.rotationVector.w; } };