/** * This component makes the parentEntity (ex. car) follow the path provided by the spline * @param graphics GameLib.D3.Graphics * @param parentObject * @param apiPathFollowing GameLib.D3.API.PathFollowing * @constructor */ GameLib.D3.PathFollowing = function RuntimePathFollowing( graphics, parentObject, apiPathFollowing ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (GameLib.Utils.UndefinedOrNull(parentObject)) { parentObject = null; } this.parentObject = parentObject; 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, this.baseOffset ); this.maxOffset = new GameLib.Vector3( this.graphics, this, this.maxOffset ); this.targetOffset = new GameLib.Vector3( this.graphics, this, this.targetOffset ); this.currentOffset = new GameLib.Vector3( this.graphics, this, this.currentOffset ); this.raycaster = new GameLib.D3.Raycaster( this.graphics, this, this.raycaster ); this.currentPosition = new GameLib.Vector3( this.graphics, this, this.currentPosition ); this.futurePosition = new GameLib.Vector3( this.graphics, this, this.futurePosition ); this.up = new GameLib.Vector3( this.graphics, this, this.up ); this.rotationMatrix = new GameLib.Matrix4( this.graphics, this, this.rotationMatrix ); this.rotationVector = new GameLib.Quaternion( this.graphics, this, this.rotationVector ); this.mx = new GameLib.Utils.MovingAverage(10); this.my = new GameLib.Utils.MovingAverage(10); this.mz = new GameLib.Utils.MovingAverage(10); }; GameLib.D3.PathFollowing.prototype = Object.create(GameLib.D3.API.PathFollowing.prototype); GameLib.D3.PathFollowing.prototype.constructor = GameLib.D3.PathFollowing; GameLib.D3.PathFollowing.prototype.toApiComponent = 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.toApiVector(), this.maxOffset.toApiVector(), this.steeringSpeed, this.targetOffset.toApiVector(), this.currentOffset.toApiVector(), this.currentPathValue, this.currentSpeed, this.direction, this.raycaster.toApiRaycaster(), this.currentPosition.toApiVector(), this.futurePosition.toApiVector(), this.up.toApiVector(), this.rotationMatrix.toApiMatrix(), this.rotationVector.toApiQuaternion(), GameLib.Utils.IdOrNull(this.parentEntity) ); return apiPathFollowing; }; GameLib.D3.PathFollowing.FromObjectComponent = function(graphics, objectComponent) { var apiPathFollowing = new GameLib.D3.API.PathFollowing( objectComponent.id, objectComponent.name, objectComponent.spline, objectComponent.mesh, objectComponent.raytraceMesh, objectComponent.accelleration, objectComponent.maxSpeed, new GameLib.API.Vector3( objectComponent.baseOffset.x, objectComponent.baseOffset.y, objectComponent.baseOffset.z ), new GameLib.API.Vector3( objectComponent.maxOffset.x, objectComponent.maxOffset.y, objectComponent.maxOffset.z ), objectComponent.steeringSpeed, new GameLib.API.Vector3( objectComponent.targetOffset.x, objectComponent.targetOffset.y, objectComponent.targetOffset.z ), new GameLib.API.Vector3( objectComponent.currentOffset.x, objectComponent.currentOffset.y, objectComponent.currentOffset.z ), this.currentPathValue, this.currentSpeed, this.direction, new GameLib.D3.API.Raycaster( new GameLib.API.Vector3( objectComponent.raycaster.position.x, objectComponent.raycaster.position.y, objectComponent.raycaster.position.z ), new GameLib.API.Vector3( objectComponent.raycaster.direction.x, objectComponent.raycaster.direction.y, objectComponent.raycaster.direction.z ) ), new GameLib.API.Vector3( objectComponent.currentPosition.x, objectComponent.currentPosition.y, objectComponent.currentPosition.z ), new GameLib.API.Vector3( objectComponent.futurePosition.x, objectComponent.futurePosition.y, objectComponent.futurePosition.z ), new GameLib.API.Vector3( objectComponent.up.x, objectComponent.up.y, objectComponent.up.z ), //TODO : objectComponent rotationVector matrix4 new GameLib.API.Matrix4( new GameLib.API.Quaternion(), new GameLib.API.Quaternion(), new GameLib.API.Quaternion(), new GameLib.API.Quaternion() ), new GameLib.API.Quaternion( objectComponent.rotationVector.x, objectComponent.rotationVector.y, objectComponent.rotationVector.z, objectComponent.rotationVector.w ), objectComponent.parentEntity ); return new GameLib.D3.PathFollowing( graphics, this, 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.futurePosition ); var direction = new GameLib.Vector3( this.graphics, this, new GameLib.API.Vector3( this.up.x * -1, this.up.y * -1, this.up.z * -1 ) ); this.raycaster.setDirection( direction ); 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.up.updateInstance(); } this.rotationMatrix.lookAt( this.currentPosition, this.futurePosition, this.up ); this.rotationVector.setFromRotationMatrix(this.rotationMatrix); /** * Update Position */ // this.mesh.position.x = this.futurePosition.x + (this.rotationMatrix.up.x * (this.mesh.height - (2 * this.rotationMatrix.up.x)) / 2);// + transformedOffset.x; // this.mesh.position.y = this.futurePosition.y + (this.rotationMatrix.up.y * (this.mesh.height - (2 * this.rotationMatrix.up.y)) / 2); // this.mesh.position.z = this.futurePosition.z + (this.rotationMatrix.up.z * (this.mesh.height - (2 * this.rotationMatrix.up.z)) / 2);// + transformedOffset.z; this.mesh.position.x = this.futurePosition.x;// + transformedOffset.x; this.mesh.position.y = this.futurePosition.y; this.mesh.position.z = this.futurePosition.z;// + transformedOffset.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; } };