diff --git a/src/game-lib-api-matrix4.js b/src/game-lib-api-matrix4.js new file mode 100644 index 0000000..ec743f7 --- /dev/null +++ b/src/game-lib-api-matrix4.js @@ -0,0 +1,36 @@ +/** + * Api Matrix 4 + * @param row0 GameLib.D3.API.Vector4 + * @param row1 GameLib.D3.API.Vector4 + * @param row2 GameLib.D3.API.Vector4 + * @param row3 GameLib.D3.API.Vector4 + * @constructor + */ +GameLib.D3.API.Matrix4 = function ApiMatrix4( + row0, + row1, + row2, + row3 +) { + this.rows = []; + + if (GameLib.D3.Utils.UndefinedOrNull(row0)) { + row0 = new GameLib.D3.API.Vector4(1, 0, 0, 0); + } + this.rows[0] = row0; + + if (GameLib.D3.Utils.UndefinedOrNull(row1)) { + row1 = new GameLib.D3.API.Vector4(0, 1, 0, 0); + } + this.rows[1] = row1; + + if (GameLib.D3.Utils.UndefinedOrNull(row2)) { + row2 = new GameLib.D3.API.Vector4(0, 0, 1, 0); + } + this.rows[2] = row2; + + if (GameLib.D3.Utils.UndefinedOrNull(row3)) { + row3 = new GameLib.D3.API.Vector4(0, 0, 0, 1); + } + this.rows[3] = row3; +}; \ No newline at end of file diff --git a/src/game-lib-api-spline.js b/src/game-lib-api-spline.js index cf163d6..44c389e 100644 --- a/src/game-lib-api-spline.js +++ b/src/game-lib-api-spline.js @@ -1,5 +1,8 @@ /** * API Spline + * @param id String + * @param name String + * @param vertices GameLib.D3.API.Vector3[] * @constructor */ GameLib.D3.API.Spline = function( diff --git a/src/game-lib-api-vector2.js b/src/game-lib-api-vector2.js index 7796935..a8b2a84 100644 --- a/src/game-lib-api-vector2.js +++ b/src/game-lib-api-vector2.js @@ -1,6 +1,15 @@ -GameLib.D3.API.Vector2 = function Vector2(x, y) { - this.x = x || 0; - this.y = y || 0; +GameLib.D3.API.Vector2 = function ApiVector2(x, y) { + + if (GameLib.D3.Utils.UndefinedOrNull(x)) { + x = 0; + } + this.x = x; + + if (GameLib.D3.Utils.UndefinedOrNull(y)) { + y = 0; + } + this.y = y; + }; GameLib.D3.API.Vector2.prototype.copy = function () { diff --git a/src/game-lib-api-vector3.js b/src/game-lib-api-vector3.js index 0807e53..438701b 100644 --- a/src/game-lib-api-vector3.js +++ b/src/game-lib-api-vector3.js @@ -1,5 +1,18 @@ -GameLib.D3.API.Vector3 = function Vector3(x, y, z) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; +GameLib.D3.API.Vector3 = function ApiVector3(x, y, z) { + + if (GameLib.D3.Utils.UndefinedOrNull(x)) { + x = 0; + } + this.x = x; + + if (GameLib.D3.Utils.UndefinedOrNull(y)) { + y = 0; + } + this.y = y; + + if (GameLib.D3.Utils.UndefinedOrNull(z)) { + z = 0; + } + this.z = z; + }; \ No newline at end of file diff --git a/src/game-lib-api-vector4.js b/src/game-lib-api-vector4.js index 054f4a6..84d4845 100644 --- a/src/game-lib-api-vector4.js +++ b/src/game-lib-api-vector4.js @@ -1,6 +1,23 @@ -GameLib.D3.API.Vector4 = function Vector4(x, y, z, w) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = w || 1; +GameLib.D3.API.Vector4 = function ApiVector4(x, y, z, w) { + + if (GameLib.D3.Utils.UndefinedOrNull(x)) { + x = 0; + } + this.x = x; + + if (GameLib.D3.Utils.UndefinedOrNull(y)) { + y = 0; + } + this.y = y; + + if (GameLib.D3.Utils.UndefinedOrNull(z)) { + z = 0; + } + this.z = z; + + if (GameLib.D3.Utils.UndefinedOrNull(w)) { + w = 1; + } + this.w = w; + }; \ No newline at end of file diff --git a/src/game-lib-component-path-following.js b/src/game-lib-component-path-following.js index b665ec0..3131dff 100644 --- a/src/game-lib-component-path-following.js +++ b/src/game-lib-component-path-following.js @@ -1,88 +1,212 @@ /** - * - * @param id - * @param name + * This component makes the parentEntity (ex. car) follow the path provided by the spline + * @param id String + * @param name String + * @param graphics GameLib.D3.Graphics + * @param parentEntity GameLib.D3.Entity * @param spline GameLib.D3.Spline - * @param meshes[] GameLib.D3.Mesh - * @param accel - * @param maxSpeed - * @param baseOffset - * @param maxOffset - * @param steeringSpeed + * @param mesh GameLib.D3.Mesh + * @param accelleration Number + * @param maxSpeed Number + * @param baseOffset GameLib.D3.Vector + * @param maxOffset GameLib.D3.Vector + * @param steeringSpeed Number + * @param offset GameLib.D3.Vector3 + * @param currentOffset GameLib.D3.Vector3 + * @param currentPathValue Number + * @param currentSpeed Number + * @param direction Number + * @param mx GameLib.D3.Utils.MovingAverage + * @param my GameLib.D3.Utils.MovingAverage + * @param mz GameLib.D3.Utils.MovingAverage + * @param raycaster GameLib.D3.Raycaster + * @param currentPosition GameLib.D3.Vector3 + * @param futurePosition GameLib.D3.Vector3 + * @param up GameLib.D3.Vector3 + * @param rotationMatrix GameLib.D3.Matrix4 + * @param rotationVector GameLib.D3.Vector4 * @constructor */ GameLib.D3.ComponentPathFollowing = function ComponentPathFollowing( id, name, + graphics, + parentEntity, spline, - meshes, - accel, + mesh, + accelleration, maxSpeed, baseOffset, maxOffset, - steeringSpeed + steeringSpeed, + offset, + currentOffset, + currentPathValue, + currentSpeed, + direction, + mx, + my, + mz, + raycaster, + currentPosition, + futurePosition, + up, + rotationMatrix, + rotationVector ) { - this.id = id || GameLib.D3.Utils.RandomId(); + if (GameLib.D3.Utils.UndefinedOrNull(id)) { + id = GameLib.D3.Utils.RandomId(); + } + this.id = id; - if (typeof name == 'undefined') { + if (GameLib.D3.Utils.UndefinedOrNull(name)) { name = this.constructor.name; } - this.name = name; - this.parentEntity = null; + if (GameLib.D3.Utils.UndefinedOrNull(parentEntity)) { + parentEntity = null; + } + this.parentEntity = parentEntity; + + if (GameLib.D3.Utils.UndefinedOrNull(spline)) { + spline = null; + } this.spline = spline; - this.trackThreeMeshArray = mesh; - this.maxSpeed = maxSpeed || 10.0; - this.accel = accel || 2.0; + if (GameLib.D3.Utils.UndefinedOrNull(mesh)) { + mesh = null; + } + this.mesh = mesh; - this.baseOffset = baseOffset || new GameLib.D3.API.Vector3(); - this.maxOffset = maxOffset || new GameLib.D3.API.Vector3(10, 10, 10); - this.steeringSpeed = steeringSpeed || 1.0; + if (GameLib.D3.Utils.UndefinedOrNull(maxSpeed)) { + maxSpeed = 0.03; + } + this.maxSpeed = maxSpeed; + if (GameLib.D3.Utils.UndefinedOrNull(accelleration)) { + accelleration = 0.1; + } + this.accelleration = accelleration; - // runtime code + if (GameLib.D3.Utils.UndefinedOrNull(baseOffset)) { + baseOffset = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(), 0.1); + } + this.baseOffset = baseOffset; - //#ifdef RUNTIME__ - this.offset = new GameLib.D3.API.Vector3(); // this one is our destination offset - this.currentOffset = new GameLib.D3.API.Vector3(); - this.currentPathValue = 0.0; - this.currentSpeed = 0.0; - this.direction = 0; - this.pastNormal = new THREE.Vector3(0,0,0); - //#endif + if (GameLib.D3.Utils.UndefinedOrNull(maxOffset)) { + maxOffset = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(10, 10, 10), 0.1); + } + this.maxOffset = maxOffset; + + if (GameLib.D3.Utils.UndefinedOrNull(steeringSpeed)) { + steeringSpeed = 1.0; + } + this.steeringSpeed = steeringSpeed; + + if (GameLib.D3.Utils.UndefinedOrNull(offset)) { + offset = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(), 0.1); + } + this.offset = offset; + + if (GameLib.D3.Utils.UndefinedOrNull(currentOffset)) { + currentOffset = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(), 0.1); + } + this.currentOffset = currentOffset; + + if (GameLib.D3.Utils.UndefinedOrNull(currentPathValue)) { + currentPathValue = 0; + } + this.currentPathValue = currentPathValue; + + if (GameLib.D3.Utils.UndefinedOrNull(currentSpeed)) { + currentSpeed = 0; + } + this.currentSpeed = currentSpeed; + + if (GameLib.D3.Utils.UndefinedOrNull(direction)) { + direction = 1; + } + this.direction = direction; + + if (GameLib.D3.Utils.UndefinedOrNull(mx)) { + mx = new GameLib.D3.Utils.MovingAverage(10); + } + this.mx = mx; + + if (GameLib.D3.Utils.UndefinedOrNull(my)) { + my = new GameLib.D3.Utils.MovingAverage(10); + } + this.my = my; + + if (GameLib.D3.Utils.UndefinedOrNull(mz)) { + mz = new GameLib.D3.Utils.MovingAverage(10); + } + this.mz = mz; + + if (GameLib.D3.Utils.UndefinedOrNull(raycaster)) { + raycaster = new GameLib.D3.Raycaster( + graphics, + new GameLib.D3.Vector3( + graphics, + this, + new GameLib.D3.API.Vector3() + ), + new GameLib.D3.Vector3( + graphics, + this, + new GameLib.D3.API.Vector3(0, -1, 0) + ) + ); + } + this.raycaster = raycaster; + + if (GameLib.D3.Utils.UndefinedOrNull(currentPosition)) { + currentPosition = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(), 0.1); + } + this.currentPosition = currentPosition; + + if (GameLib.D3.Utils.UndefinedOrNull(futurePosition)) { + futurePosition = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(), 0.1); + } + this.futurePosition = futurePosition; + + if (GameLib.D3.Utils.UndefinedOrNull(up)) { + up = new GameLib.D3.Vector3(graphics, this, new GameLib.D3.API.Vector3(0, 1, 0), 0.1); + } + this.up = up; + + if (GameLib.D3.Utils.UndefinedOrNull(rotationMatrix)) { + rotationMatrix = new GameLib.D3.Matrix4( + graphics, + this, + new GameLib.D3.API.Matrix4() + ); + } + this.rotationMatrix = rotationMatrix; + + if (GameLib.D3.Utils.UndefinedOrNull(rotationVector)) { + rotationVector = new GameLib.D3.Vector4(graphics, this, new GameLib.D3.API.Vector4(), 0.1); + } + this.rotationVector = rotationVector; - // extend GameLib.D3.Utils.Extend(GameLib.D3.ComponentPathFollowing, GameLib.D3.ComponentInterface); }; -//#ifdef RUNTIME__ - -ComponentPathFollowing_Three_Raycaster = new THREE.Raycaster(); - ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentPathFollowing.prototype.onUpdate = function( - deltaTime, - parentEntity + deltaTime ) { - if(this.spline && this.trackThreeMeshArray) { + if (this.spline && this.mesh) { - // current speed - - this.maxSpeed = 0.03; - this.accel = 0.1; - - this.currentSpeed += this.accel * deltaTime * this.direction; + this.currentSpeed += this.accelleration * deltaTime * this.direction; if(this.currentSpeed > this.maxSpeed) { this.currentSpeed = this.maxSpeed; } this.grain = (this.currentSpeed / 100.0); - //this.grain = (deltaTime / 100.0); - - var currentPosition = this.splineCurve3.getPointAt(this.currentPathValue); + this.currentPosition = this.spline.getPointAt(this.currentPathValue); this.currentPathValue += this.grain; @@ -94,126 +218,148 @@ GameLib.D3.ComponentPathFollowing.prototype.onUpdate = function( this.currentPathValue = 0.0; } - var futurePosition = this.splineCurve3.getPointAt(this.currentPathValue); + this.futurePosition = this.spline.getPointAt(this.currentPathValue); // - - - - - - - - - - - - - // Ray trace from the future position. // - - - - - - - - -- - - - - - ComponentPathFollowing_Three_Raycaster.set( - futurePosition, - new THREE.Vector3( - 0, - -1, - 0 - ) + this.raycaster.setPosition( + this.futurePosition ); - var futureNormal = new THREE.Vector3(0, 1, 0); - var futurePositionRayCasted = new THREE.Vector3( - futurePosition.x, - futurePosition.y, - futurePosition.z - ); - for(var m = 0, ml = this.trackThreeMeshArray.length; m < ml; ++m) { - var intersect = ComponentPathFollowing_Three_Raycaster.intersectObject( - this.trackThreeMeshArray[m] - ); + // var futureNormal = new THREE.Vector3(0, 1, 0); + // var futurePositionRayCasted = new THREE.Vector3( + // futurePosition.x, + // futurePosition.y, + // futurePosition.z + // ); - if(intersect && intersect.length > 0) { - futureNormal = intersect[0].face.normal; - futurePositionRayCasted = intersect[0].point; - break; - } - } + var normal = this.raycaster.getFaceNormal(this.mesh); + + this.up.x = this.mx(normal.x); + this.up.y = this.my(normal.y); + this.up.z = this.mz(normal.z); + + this.up.updateInstance(); // - - - - - - - - - - - - - // Ray trace from the current position. // - - - - - - - - -- - - - - + // + // ComponentPathFollowing_Three_Raycaster.set( + // currentPosition, + // new THREE.Vector3( + // 0, + // -1, + // 0 + // ) + // ); - ComponentPathFollowing_Three_Raycaster.set( - currentPosition, - new THREE.Vector3( - 0, - -1, - 0 - ) - ); - - var currentNormal = new THREE.Vector3(0, 1, 0); - for(var m = 0, ml = this.trackThreeMeshArray.length; m < ml; ++m) { - var intersect = ComponentPathFollowing_Three_Raycaster.intersectObject( - this.trackThreeMeshArray[m] - ); - - if(intersect && intersect.length > 0) { - currentNormal = intersect[0].face.normal; - break; - } - } + // var currentNormal = new THREE.Vector3(0, 1, 0); + // for(var m = 0, ml = this.trackThreeMeshArray.length; m < ml; ++m) { + // var intersect = ComponentPathFollowing_Three_Raycaster.intersectObject( + // this.meshes[m].instance + // ); + // + // if(intersect && intersect.length > 0) { + // currentNormal = intersect[0].face.normal; + // break; + // } + // } //var avgNormal = currentNormal.add(this.pastNormal).add(futureNormal).normalize(); - var avgNormal = (this.pastNormal).add(futureNormal).normalize(); - this.pastNormal = futureNormal; + // var avgNormal = (this.pastNormal).add(futureNormal).normalize(); + // this.pastNormal = futureNormal; - var matrix = new THREE.Matrix4().lookAt( - currentPosition, - futurePosition, - avgNormal + + this.rotationMatrix.lookAt( + this.currentPosition, + this.futurePosition, + this.up ); - var quaternion = new THREE.Quaternion().setFromRotationMatrix(matrix); + this.rotationVector.setFromRotationMatrix(this.rotationMatrix); - var targetVector = new THREE.Vector3( - this.maxOffset.x * this.offset.x, - this.maxOffset.y * this.offset.y, - this.maxOffset.z * this.offset.z - ); - - var lerpedOffset = new THREE.Vector3( - this.currentOffset.x, - this.currentOffset.y, - this.currentOffset.z - ).lerp( - targetVector, - (this.grain * this.steeringSpeed) - ); - - this.currentOffset.x = lerpedOffset.x; - this.currentOffset.y = lerpedOffset.y; - this.currentOffset.z = lerpedOffset.z; - - var transformedOffset = new THREE.Vector3( - this.baseOffset.x + lerpedOffset.x, - this.baseOffset.y + lerpedOffset.y, - this.baseOffset.z + lerpedOffset.z - ).applyQuaternion(quaternion); + // var targetVector = new THREE.Vector3( + // this.maxOffset.x * this.offset.x, + // this.maxOffset.y * this.offset.y, + // this.maxOffset.z * this.offset.z + // ); + // + // var lerpedOffset = new THREE.Vector3( + // this.currentOffset.x, + // this.currentOffset.y, + // this.currentOffset.z + // ).lerp( + // targetVector, + // (this.grain * this.steeringSpeed) + // ); + // + // this.currentOffset.x = lerpedOffset.x; + // this.currentOffset.y = lerpedOffset.y; + // this.currentOffset.z = lerpedOffset.z; + // + // var transformedOffset = new THREE.Vector3( + // this.baseOffset.x + lerpedOffset.x, + // this.baseOffset.y + lerpedOffset.y, + // this.baseOffset.z + lerpedOffset.z + // ).applyQuaternion(quaternion); // apply to parent rigidbody instead of direclty to the mesh. - /* parentEntity.position.x = futurePositionRayCasted.x + transformedOffset.x; - parentEntity.position.y = futurePositionRayCasted.y + transformedOffset.y + this.parentEntity.mesh.geometry.boundingBox.y; - parentEntity.position.z = futurePositionRayCasted.z + transformedOffset.z; -*/ + /* parentEntity.position.x = futurePositionRayCasted.x + transformedOffset.x; + parentEntity.position.y = futurePositionRayCasted.y + transformedOffset.y + this.parentEntity.mesh.geometry.boundingBox.y; + parentEntity.position.z = futurePositionRayCasted.z + transformedOffset.z; + */ - parentEntity.position.x = futurePosition.x + transformedOffset.x; - parentEntity.position.y = futurePosition.y + transformedOffset.y; - parentEntity.position.z = futurePosition.z + transformedOffset.z; + /** + * Update Position + */ + this.parentEntity.position.x = this.futurePosition.x;// + transformedOffset.x; + this.parentEntity.position.y = this.futurePosition.y;// + transformedOffset.y; + this.parentEntity.position.z = this.futurePosition.z;// + transformedOffset.z; - // update rotation - parentEntity.quaternion.x = quaternion.x; - parentEntity.quaternion.y = quaternion.y; - parentEntity.quaternion.z = quaternion.z; - parentEntity.quaternion.w = quaternion.w; + /** + * Update Rotation + */ + this.parentEntity.quaternion.x = this.rotationVector.x; + this.parentEntity.quaternion.y = this.rotationVector.y; + this.parentEntity.quaternion.z = this.rotationVector.z; + this.parentEntity.quaternion.w = this.rotationVector.w; + + // // original code + // + // this.step += this.grain; + // + // if (this.step > 1) { + // this.step = 0; + // } + // + // var lookAtStep = this.step + this.grain * 2; + // + // if (lookAtStep > 1) { + // lookAtStep = 0; + // } + // + // var position = this.scene.splines[0].instance.getPoint(this.step); + // var futurePosition = this.scene.splines[0].instance.getPoint(lookAtStep); + // + // this.raycaster.set(position, new THREE.Vector3(0, -1, 0)); + // + // var intersect = this.raycaster.intersectObject(this.scene.meshes[6].instance); + // + // this.scene.entities[1].position.x = position.x; + // this.scene.entities[1].position.y = position.y; + // this.scene.entities[1].position.z = position.z; + // + // var matrix = new THREE.Matrix4().lookAt(position, futurePosition, intersect[0].face.normal); + // + // var quaternion = new THREE.Quaternion().setFromRotationMatrix(matrix); + // + // this.scene.entities[1].quaternion.x = quaternion.x; + // this.scene.entities[1].quaternion.y = quaternion.y; + // this.scene.entities[1].quaternion.z = quaternion.z; + // this.scene.entities[1].quaternion.w = quaternion.w; } -}; -//#endif - -GameLib.D3.ComponentPathFollowing.prototype.onSetParentEntity = function( - parentScene, - parentEntity -) { - if(!this.splineCurve3) { - console.error("NO PATH GIVEN"); - } }; \ No newline at end of file diff --git a/src/game-lib-entity.js b/src/game-lib-entity.js index f10dd51..f3c5ac9 100644 --- a/src/game-lib-entity.js +++ b/src/game-lib-entity.js @@ -5,7 +5,7 @@ * @param mesh * @constructor */ -GameLib.D3.Entity = function( +GameLib.D3.Entity = function Entity( apiEntity, parentScene, mesh @@ -41,17 +41,28 @@ GameLib.D3.Entity.prototype.update = function( }; GameLib.D3.Entity.prototype.updateMesh = function() { - if(this.mesh) { - this.mesh.position.set(this.position.x, this.position.y, this.position.z); - this.mesh.scale.set(this.scale.x, this.scale.y, this.scale.z); - this.mesh.quaternion.set(this.quaternion.x, this.quaternion.y, this.quaternion.z, this.quaternion.w).normalize(); - // normalize the quaternion, if we have a mesh. - // if we don't do this, then the mesh will get stretched - this.quaternion.x = this.mesh.quaternion.x; - this.quaternion.y = this.mesh.quaternion.y; - this.quaternion.z = this.mesh.quaternion.z; - this.quaternion.w = this.mesh.quaternion.w; + if (this.mesh) { + + /** + * Normalize to prevent stretching + */ + this.quaternion.normalize(); + + this.mesh.position.x = this.position.x; + this.mesh.position.y = this.position.y; + this.mesh.position.z = this.position.z; + + this.mesh.scale.x = this.scale.x; + this.mesh.scale.y = this.scale.y; + this.mesh.scale.z = this.scale.z; + + this.mesh.quaternion.x = this.quaternion.x; + this.mesh.quaternion.y = this.quaternion.y; + this.mesh.quaternion.z = this.quaternion.z; + this.mesh.quaternion.w = this.quaternion.w; + + this.mesh.updateInstance(); } }; diff --git a/src/game-lib-matrix-4.js b/src/game-lib-matrix-4.js index d8c9d0a..3936b2a 100644 --- a/src/game-lib-matrix-4.js +++ b/src/game-lib-matrix-4.js @@ -1,27 +1,111 @@ +/** + * Runtime Matrix4 + * @param graphics + * @param parentObject + * @param matrix4 + * @param grain + * @constructor + */ GameLib.D3.Matrix4 = function( - row0, - row1, - row2, - row3 + graphics, + parentObject, + matrix4, + grain ) { - this.identity(); - - if (row0) { - this.rows[0] = row0; + for (var property in matrix4) { + if (matrix4.hasOwnProperty(property)) { + this[property] = matrix4[property]; + } } - if (row1) { - this.rows[1] = row1; + GameLib.D3.Utils.Extend(GameLib.D3.Matrix4, GameLib.D3.API.Matrix4); + + this.graphics = graphics; + + this.graphics.isNotThreeThrow(); + + this.parentObject = parentObject; + + if (GameLib.D3.Utils.UndefinedOrNull(grain)) { + grain = 0.001; + } + this.grain = grain; + + this.rows[0] = new GameLib.D3.Vector4( + this.graphics, + this, + this.rows[0], + grain + ); + + this.rows[1] = new GameLib.D3.Vector4( + this.graphics, + this, + this.rows[1], + grain + ); + + this.rows[2] = new GameLib.D3.Vector4( + this.graphics, + this, + this.rows[2], + grain + ); + + this.rows[3] = new GameLib.D3.Vector4( + this.graphics, + this, + this.rows[3], + grain + ); + + this.instance = this.createInstance(); +}; + +/** + * Creates a matrix 4 instance (currently from graphics lib) + * @param update + */ +GameLib.D3.Matrix4.prototype.createInstance = function(update) { + + var instance = null; + + if (update) { + instance = this.instance; } - if (row2) { - this.rows[2] = row2; + if (!instance) { + instance = new THREE.Matrix4(); } - if (row3) { - this.rows[3] = row3; - } + instance.set( + this.rows[0].x, + this.rows[0].y, + this.rows[0].z, + this.rows[0].w, + this.rows[1].x, + this.rows[1].y, + this.rows[1].z, + this.rows[1].w, + this.rows[2].x, + this.rows[2].y, + this.rows[2].z, + this.rows[2].w, + this.rows[3].x, + this.rows[3].y, + this.rows[3].z, + this.rows[3].w + ); + + return instance; +}; + +/** + * Updates this instance + */ +GameLib.D3.Matrix4.prototype.updateInstance = function() { + this.createInstance(true); }; GameLib.D3.Matrix4.prototype.rotationMatrixX = function (radians) { @@ -101,34 +185,55 @@ GameLib.D3.Matrix4.prototype.identity = function () { GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) { - var pv = new GameLib.D3.API.Vector3(position.x, position.y, position.z); + this.instance.lookAt(position.instance, target.instance, up.instance); - var z = pv.subtract(target).normalize(); + this.rows[0].x = this.instance.elements[0]; + this.rows[0].y = this.instance.elements[1]; + this.rows[0].z = this.instance.elements[2]; + this.rows[0].w = this.instance.elements[3]; - if (z.squared() === 0) { - z.z = 1; - } + this.rows[1].x = this.instance.elements[4]; + this.rows[1].y = this.instance.elements[5]; + this.rows[1].z = this.instance.elements[6]; + this.rows[1].w = this.instance.elements[7]; - var x = up.cross(z).normalize(); + this.rows[2].x = this.instance.elements[8]; + this.rows[2].y = this.instance.elements[9]; + this.rows[2].z = this.instance.elements[10]; + this.rows[2].w = this.instance.elements[11]; - if (x.squared() === 0) { - z.x += 0.0001; - x = up.cross(z).normalize(); - } - - var y = z.cross(x); - - this.rows[0].x = x.x; - this.rows[0].y = x.y; - this.rows[0].z = x.z; - - this.rows[1].x = y.x; - this.rows[1].y = y.y; - this.rows[1].z = y.z; - - this.rows[2].x = z.x; - this.rows[2].y = z.y; - this.rows[2].z = z.z; - - return this; + this.rows[3].x = this.instance.elements[12]; + this.rows[3].y = this.instance.elements[13]; + this.rows[3].z = this.instance.elements[14]; + this.rows[3].w = this.instance.elements[15]; + // var pv = new GameLib.D3.API.Vector3(position.x, position.y, position.z); + // + // var z = pv.subtract(target).normalize(); + // + // if (z.squared() === 0) { + // z.z = 1; + // } + // + // var x = up.cross(z).normalize(); + // + // if (x.squared() === 0) { + // z.x += 0.0001; + // x = up.cross(z).normalize(); + // } + // + // var y = z.cross(x); + // + // this.rows[0].x = x.x; + // this.rows[0].y = x.y; + // this.rows[0].z = x.z; + // + // this.rows[1].x = y.x; + // this.rows[1].y = y.y; + // this.rows[1].z = y.z; + // + // this.rows[2].x = z.x; + // this.rows[2].y = z.y; + // this.rows[2].z = z.z; + // + // return this; }; diff --git a/src/game-lib-mesh.js b/src/game-lib-mesh.js index 04f928a..6a09757 100644 --- a/src/game-lib-mesh.js +++ b/src/game-lib-mesh.js @@ -309,16 +309,25 @@ GameLib.D3.Mesh.prototype.createInstance = function(update) { instance.gameLibObject = this; - instance.position.copy(this.position.instance); + instance.position.x = this.position.x; + instance.position.y = this.position.y; + instance.position.z = this.position.z; - instance.scale.copy(this.scale.instance); + instance.scale.x = this.scale.x; + instance.scale.y = this.scale.y; + instance.scale.z = this.scale.z; - instance.up.copy(this.up.instance); + instance.up.x = this.up.x; + instance.up.y = this.up.y; + instance.up.z = this.up.z; /** * We don't do rotation - its dealt with by quaternion */ - instance.quaternion.copy(this.quaternion.instance); + instance.quaternion.x = this.quaternion.x; + instance.quaternion.y = this.quaternion.y; + instance.quaternion.z = this.quaternion.z; + instance.quaternion.w = this.quaternion.w; return instance; }; diff --git a/src/game-lib-raycaster.js b/src/game-lib-raycaster.js new file mode 100644 index 0000000..71cc288 --- /dev/null +++ b/src/game-lib-raycaster.js @@ -0,0 +1,132 @@ +/** + * Raycaster for GameLib.D3 + * @param graphics GameLib.D3.Graphics + * @param position GameLib.D3.Vector3 + * @param direction GameLib.D3.Vector3 + * @constructor + */ +GameLib.D3.Raycaster = function( + graphics, + position, + direction +) { + + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (GameLib.D3.Utils.UndefinedOrNull(position)) { + position = new GameLib.D3.Vector3( + graphics, + this, + new GameLib.D3.API.Vector3() + ); + } + this.position = position; + + if (GameLib.D3.Utils.UndefinedOrNull(direction)) { + direction = new GameLib.D3.Vector3( + graphics, + this, + new GameLib.D3.API.Vector3(0, -1, 0) + ); + } + this.direction = direction; + + this.instance = this.createInstance(); +}; + +/** + * Creates or updates a raycaster instance + * @param update + */ +GameLib.D3.Raycaster.prototype.createInstance = function(update) { + + var instance = null; + + if (update) { + instance = this.instance; + } else { + instance = new THREE.Raycaster(); + } + + instance.set( + this.position.instance, + this.direction.instance + ); + + return instance; +}; + +/** + * Sets the direction and position of this raycaster + * @param position GameLib.D3.Vector3 + * @param direction GameLib.D3.Vector3 + */ +GameLib.D3.Raycaster.prototype.set = function( + position, + direction +) { + this.position = position; + this.direction = direction; + + this.position.updateInstance(); + this.direction.updateInstance(); + + this.createInstance(true); +}; + +/** + * Sets the direction of this raycaster + * @param direction GameLib.D3.Vector3 + */ +GameLib.D3.Raycaster.prototype.setDirection = function( + direction +) { + this.direction = direction; + + this.direction.updateInstance(); + + this.createInstance(true); +}; + +/** + * Sets the position of this raycaster + * @param position GameLib.D3.Vector3 + */ +GameLib.D3.Raycaster.prototype.setPosition = function( + position +) { + this.position = position; + + this.position.updateInstance(); + + this.createInstance(true); +}; + +/** + * Returns the face normal (if any) of an intersection between current ray position, direction and a provided mesh + * @param mesh GameLib.D3.Mesh + * @returns {null | GameLib.D3.Vector3} + */ +GameLib.D3.Raycaster.prototype.getFaceNormal = function(mesh) { + + var normal = null; + + var intersect = this.instance.intersectObject( + mesh.instance + ); + + if (intersect && intersect.length > 0) { + normal = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3( + intersect[0].face.normal.x, + intersect[0].face.normal.y, + intersect[0].face.normal.z + ) + ); + } + + return normal; +}; \ No newline at end of file diff --git a/src/game-lib-spline.js b/src/game-lib-spline.js index 0c40fa9..afc0081 100644 --- a/src/game-lib-spline.js +++ b/src/game-lib-spline.js @@ -4,7 +4,7 @@ * @param apiSpline GameLib.D3.API.Spline * @constructor */ -GameLib.D3.Spline = function( +GameLib.D3.Spline = function Spline( graphics, apiSpline ) { @@ -30,7 +30,7 @@ GameLib.D3.Spline.prototype.createInstance = function(update) { var vertices = []; for (var v = 0; v < this.vertices.length; v++) { - vertices.push(new this.graphics.instance.Vector3( + vertices.push(new THREE.Vector3( this.vertices[v].x, this.vertices[v].y, this.vertices[v].z @@ -47,4 +47,19 @@ GameLib.D3.Spline.prototype.updateInstance = function() { this.instance = this.createInstance(true); }; +/** + * Gets the current point from the spline at the proper value + * @param proper Number (fraction between 0 and 1 indicating position on spline) + * @returns {*} + */ +GameLib.D3.Spline.prototype.getPointAt = function(proper) { + var point = this.instance.getPointAt(proper); + return new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(point.x, point.y, point.z), + 0.1 + ); +}; + diff --git a/src/game-lib-vector4.js b/src/game-lib-vector4.js index 74df1db..eda8c5e 100644 --- a/src/game-lib-vector4.js +++ b/src/game-lib-vector4.js @@ -6,7 +6,12 @@ * @param grain Number * @constructor */ -GameLib.D3.Vector4 = function RuntimeVector4(graphics, parentObject, vector4, grain) { +GameLib.D3.Vector4 = function RuntimeVector4( + graphics, + parentObject, + vector4, + grain +) { for (var property in vector4) { if (vector4.hasOwnProperty(property)) { @@ -46,7 +51,7 @@ GameLib.D3.Vector4.prototype.createInstance = function(update) { instance.z = this.z; instance.w = this.w; } else { - instance = new this.graphics.instance.Vector4(this.x, this.y, this.z, this.w); + instance = new THREE.Quaternion(this.x, this.y, this.z, this.w); } return instance; @@ -116,20 +121,31 @@ GameLib.D3.Vector4.prototype.multiply = function (s) { GameLib.D3.Vector4.prototype.normalize = function () { - // note - leave w untouched - var EPSILON = 0.000001; + this.updateInstance(); - var v2 = this.x * this.x + this.y * this.y + this.z * this.z; + this.instance.normalize(); - if (v2 < EPSILON) { - return this; //do nothing for zero vector - } - - var invLength = 1 / Math.sqrt(v2); - - this.x *= invLength; - this.y *= invLength; - this.z *= invLength; + this.x = this.instance.x; + this.y = this.instance.y; + this.z = this.instance.z; + this.w = this.instance.w; + // + // + // + // // note - leave w untouched + // var EPSILON = 0.000001; + // + // var v2 = this.x * this.x + this.y * this.y + this.z * this.z; + // + // if (v2 < EPSILON) { + // return this; //do nothing for zero vector + // } + // + // var invLength = 1 / Math.sqrt(v2); + // + // this.x *= invLength; + // this.y *= invLength; + // this.z *= invLength; return this; }; @@ -376,3 +392,17 @@ GameLib.D3.Vector4.Points.prototype.toOrigin = function () { this.vectors[i].translate(distanceFromOrigin); } }; + +/** + * + * @param matrix4 GameLib.D3.Matrix4 + */ +GameLib.D3.Vector4.prototype.setFromRotationMatrix = function(matrix4) { + + this.instance.setFromRotationMatrix(matrix4.instance); + + this.x = this.instance.x; + this.y = this.instance.y; + this.z = this.instance.z; + this.w = this.instance.w; +};