/** * This component makes the parentEntity (ex. car) follow the path provided by the spline * @param graphics GameLib.GraphicsRuntime * @param apiPathFollowing GameLib.D3.API.PathFollowing * @constructor */ GameLib.D3.PathFollowing = function ( graphics, apiPathFollowing ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (GameLib.Utils.UndefinedOrNull(apiPathFollowing)) { apiPathFollowing = {}; } if (apiPathFollowing instanceof GameLib.D3.PathFollowing) { return apiPathFollowing; } GameLib.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 GameLib.Vector3( this.graphics, this.baseOffset, this ); this.maxOffset = new GameLib.Vector3( this.graphics, this.maxOffset, this ); this.targetOffset = new GameLib.Vector3( this.graphics, this.targetOffset, this ); this.currentOffset = new GameLib.Vector3( this.graphics, this.currentOffset, this ); this.raycaster = new GameLib.D3.Raycaster( this.graphics, this.raycaster ); this.currentPosition = new GameLib.Vector3( this.graphics, this.currentPosition, this ); this.futurePosition = new GameLib.Vector3( this.graphics, this.futurePosition, this ); this.up = new GameLib.Vector3( this.graphics, this.up, this ); this.rotationMatrix = new GameLib.Matrix4( this.graphics, this.rotationMatrix, this ); this.rotationVector = new GameLib.Quaternion( this.graphics, this.rotationVector, this ); this.mx = new GameLib.Utils.MovingAverage(10); this.my = new GameLib.Utils.MovingAverage(10); this.mz = new GameLib.Utils.MovingAverage(10); GameLib.Component.call( this, GameLib.Component.COMPONENT_PATH_FOLLOWING, { 'spline': GameLib.D3.Spline, 'mesh' : GameLib.D3.Mesh, 'raytraceMesh' : GameLib.D3.Mesh } ); }; GameLib.D3.PathFollowing.prototype = Object.create(GameLib.D3.API.PathFollowing.prototype); GameLib.D3.PathFollowing.prototype.constructor = GameLib.D3.PathFollowing; GameLib.D3.PathFollowing.prototype.createInstance = function() { console.log('GameLib.D3.PathFollowing.prototype.createInstance()'); GameLib.Component.prototype.createInstance.call(this); }; GameLib.D3.PathFollowing.prototype.toApiObject = function() { var apiPathFollowing = new GameLib.D3.API.PathFollowing( this.id, this.name, GameLib.Utils.IdOrNull(this.spline), GameLib.Utils.IdOrNull(this.mesh), GameLib.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(), GameLib.Utils.IdOrNull(this.parentEntity) ); return apiPathFollowing; }; /** * Object path following to GameLib.D3.PathFollowing * @param graphics * @param objectComponent * @returns {GameLib.D3.PathFollowing} * @constructor */ GameLib.D3.PathFollowing.FromObject = function(graphics, objectComponent) { var apiPathFollowing = GameLib.D3.API.PathFollowing.FromObject(objectComponent); return new GameLib.D3.PathFollowing( graphics, apiPathFollowing ); }; /** * Updates the component * @param deltaTime */ GameLib.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; } };