diff --git a/src/game-lib-api-mesh.js b/src/game-lib-api-mesh.js index 598e70a..92c388f 100644 --- a/src/game-lib-api-mesh.js +++ b/src/game-lib-api-mesh.js @@ -115,4 +115,9 @@ GameLib.D3.API.Mesh = function( up = new GameLib.D3.API.Vector3(0,1,0); } this.up = up; + + this.localRotation = new GameLib.D3.API.Vector3(0,0,0); + this.localScale = new GameLib.D3.API.Vector3(1,1,1); + this.localPosition = new GameLib.D3.API.Vector3(0,0,0); + }; \ No newline at end of file diff --git a/src/game-lib-api-quaternion-a.js b/src/game-lib-api-quaternion-a.js index eec0afe..9647381 100644 --- a/src/game-lib-api-quaternion-a.js +++ b/src/game-lib-api-quaternion-a.js @@ -1,4 +1,4 @@ -GameLib.D3.API.Quaternion = function ApiQuaternion(x, y, z, w, axis, angle) { +GameLib.D3.API.Quaternion = function (x, y, z, w, axis, angle) { if (GameLib.D3.Utils.UndefinedOrNull(x)) { x = 0; @@ -21,7 +21,7 @@ GameLib.D3.API.Quaternion = function ApiQuaternion(x, y, z, w, axis, angle) { this.w = w; if (GameLib.D3.Utils.UndefinedOrNull(axis)) { - axis = new GameLib.D3.API.Vector3(0, 0, 0); + axis = new GameLib.D3.API.Vector3(); } this.axis = axis; @@ -67,23 +67,43 @@ GameLib.D3.API.Quaternion.prototype.normalize = function () { this.z *= invLength; }; -GameLib.D3.API.Quaternion.prototype.multiply = function (s) { - if (s instanceof GameLib.D3.API.Vector3) { - this.x *= s.x; - this.y *= s.y; - this.z *= s.z; - } else if (s instanceof GameLib.D3.API.Matrix4) { - var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w * this.w; - var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w * this.w; - var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z + s.rows[2].w * this.w; - var w = s.rows[3].x * this.x + s.rows[3].y * this.y + s.rows[3].z * this.z + s.rows[3].w * this.w; +GameLib.D3.API.Quaternion.prototype.multiply = function (q) { + + var x, y, z, w; + var a = q; + var b = this; + + if (q instanceof GameLib.D3.API.Matrix4) { + + x = a.rows[0].x * b.x + a.rows[0].y * b.y + a.rows[0].z * b.z + a.rows[0].w * b.w; + y = a.rows[1].x * b.x + a.rows[1].y * b.y + a.rows[1].z * b.z + a.rows[1].w * b.w; + z = a.rows[2].x * b.x + a.rows[2].y * b.y + a.rows[2].z * b.z + a.rows[2].w * b.w; + w = a.rows[3].x * b.x + a.rows[3].y * b.y + a.rows[3].z * b.z + a.rows[3].w * b.w; + this.x = x; this.y = y; this.z = z; this.w = w; + + return this; + + } else if (q instanceof GameLib.D3.API.Quaternion) { + + x = ((a.x * b.x) - (a.y * b.y) - (a.z * b.z) - (a.w * a.w)); + y = ((a.x * b.y) + (a.y * b.x) - (a.z * b.w) + (a.w * a.z)); + z = ((a.x * b.z) + (a.y * b.w) + (a.z * b.x) - (a.w * a.y)); + w = ((a.x * b.w) - (a.y * b.z) + (a.z * b.y) + (a.w * a.x)); + + this.x = x; + this.y = y; + this.z = z; + this.w = w; + + return this; + } else { - console.log("functionality not implemented - please do this"); - throw new Error("not implemented"); + console.log("This functionality not implemented - please do this"); + throw new Error("This functionality not implemented - please do this"); } }; @@ -114,5 +134,64 @@ GameLib.D3.API.Quaternion.prototype.subtract = function (v) { this.w -= v.w; } + return this; +}; + +GameLib.D3.API.Quaternion.prototype.magnitude = function () { + return Math.sqrt( + (this.x * this.x) + + (this.y * this.y) + + (this.z * this.z) + + (this.w * this.w) + ); +}; + +GameLib.D3.API.Quaternion.prototype.normalize = function () { + + var magnitude = this.magnitude(); + + if (magnitude < 0.000001) { + return this; //do nothing for zero vector + } + + this.x *= magnitude; + this.y *= magnitude; + this.z *= magnitude; + this.w *= magnitude; + + return this; +}; + +/** + * + * @param matrix4 GameLib.D3.Matrix4 + */ +GameLib.D3.API.Quaternion.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; +}; + +/** + * + * @param quaternion GameLib.D3.Quaternion + * @param t + * @returns {GameLib.D3.Quaternion} + */ +GameLib.D3.API.Quaternion.prototype.slerp = function (quaternion, t) { + + this.updateInstance(); + + this.instance.slerp(quaternion.instance, t); + + this.x = this.instance.x; + this.y = this.instance.y; + this.z = this.instance.z; + this.w = this.instance.w; + return this; }; \ No newline at end of file diff --git a/src/game-lib-api-vector3.js b/src/game-lib-api-vector3.js index 23d36de..8393355 100644 --- a/src/game-lib-api-vector3.js +++ b/src/game-lib-api-vector3.js @@ -1,4 +1,4 @@ -GameLib.D3.API.Vector3 = function ApiVector3(x, y, z) { +GameLib.D3.API.Vector3 = function (x, y, z) { if (GameLib.D3.Utils.UndefinedOrNull(x)) { x = 0; @@ -74,11 +74,10 @@ GameLib.D3.API.Vector3.prototype.translate = function (v) { }; GameLib.D3.API.Vector3.prototype.add = function (v) { - return new GameLib.D3.API.Vector3( - this.x + v.x, - this.y + v.y, - this.z + v.z - ); + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; }; GameLib.D3.API.Vector3.prototype.squared = function () { @@ -128,54 +127,57 @@ GameLib.D3.API.Vector3.AngleDirection = function(forward, directionToCheck, up) } else { return 0.0; } - }; -GameLib.D3.API.Vector3.prototype.multiply = function (s) { +/** + * Multiplies this vector with a scalar, vector or matrix. If you want a copy, copy() it first + * @param object {Number | GameLib.D3.API.Vector3 | GameLib.D3.API.Vector4 | GameLib.D3.API.Matrix3 | GameLib.D3.API.Matrix4} + * @param cross boolean true if you want the cross product, otherwise returns the scalar (dot or inner) product + * @returns {GameLib.D3.API.Vector3 | Number} + */ +GameLib.D3.API.Vector3.prototype.multiply = function (object, cross) { var x, y, z; - if (s instanceof GameLib.D3.API.Vector3) { + var a = object; + var b = this; - return new GameLib.D3.API.Vector3( - this.x * s.x, - this.y * s.y, - this.z * s.z - ) + if (GameLib.D3.Utils.UndefinedOrNull(cross)) { + cross = false; + } - } else if (s instanceof GameLib.D3.API.Matrix4) { + if (typeof object == 'number') { - x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w; - y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w; - z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z + s.rows[2].w; + if (cross) { + this.x *= object; + this.y *= object; + this.z *= object; + return this; + } else { + return ((this.x * object) + (this.y * object) + (this.z * object)); + } - return new GameLib.D3.API.Vector3( - x, - y, - z - ); + } - } else if (s instanceof GameLib.D3.API.Matrix3) { + if (object instanceof GameLib.D3.API.Vector3) { - x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z; - y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z; - z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z; + if (cross) { - return new GameLib.D3.API.Vector3( - x, - y, - z - ); + x = (a.y * b.z) - (a.z * b.y); + y = (a.z * b.x) - (a.x * b.z); + z = (a.x * b.y) - (a.y * b.x); - } else if(!isNaN(parseFloat(s)) && isFinite(s)) { + this.x = x; + this.y = y; + this.z = z; - return new GameLib.D3.API.Vector3( - this.x * s, - this.y * s, - this.z * s - ); + return this; - } else { + } else { + return ((this.x * object.x) + (this.y * object.y) + (this.z * object.z)); + } + + } else { console.log("functionality not implemented - please do this"); throw new Error("not implemented"); } @@ -226,6 +228,8 @@ GameLib.D3.API.Vector3.prototype.applyQuaternion = function(q) { this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; + + return this; }; GameLib.D3.API.Vector3.prototype.clamp = function(min, max) { diff --git a/src/game-lib-component-a.js b/src/game-lib-component-a.js index 85f23fe..9a4a2bf 100644 --- a/src/game-lib-component-a.js +++ b/src/game-lib-component-a.js @@ -162,7 +162,7 @@ GameLib.D3.Component.FromObjectComponent = function(graphics, objectComponent) { component = new GameLib.D3.ComponentPathFollowing(null, null, graphics); break; case GameLib.D3.Component.COMPONENT_MESH : - component = new GameLib.D3.ComponentMesh(); + component = new GameLib.D3.ComponentMesh(null, null, graphics); break; case GameLib.D3.Component.COMPONENT_MESH_PERMUTATION : component = new GameLib.D3.ComponentMeshPermutation(null, null, graphics); diff --git a/src/game-lib-component-mesh-permutation.js b/src/game-lib-component-mesh-permutation.js index 3b8f195..e818bd1 100644 --- a/src/game-lib-component-mesh-permutation.js +++ b/src/game-lib-component-mesh-permutation.js @@ -61,7 +61,7 @@ GameLib.D3.ComponentMeshPermutation = function ComponentMeshPermutation( quaternionOffset = new GameLib.D3.Quaternion( graphics, this, - new GameLib.D3.API.Quaternion() + new GameLib.D3.API.Quaternion(0, 0, 0, 1) ); } this.quaternionOffset = quaternionOffset; @@ -98,6 +98,8 @@ GameLib.D3.ComponentMeshPermutation = function ComponentMeshPermutation( this, new GameLib.D3.API.Vector3() ); + + this.customCode = ""; }; GameLib.D3.ComponentMeshPermutation.prototype = Object.create(GameLib.D3.Component.prototype); @@ -111,42 +113,56 @@ GameLib.D3.ComponentMeshPermutation.prototype.onUpdate = function(deltaTime) { if (this.parentEntity && this.mesh) { - this.position.x = this.parentEntity.position.x + this.positionOffset.x; - this.position.y = this.parentEntity.position.y + this.positionOffset.y; - this.position.z = this.parentEntity.position.z + this.positionOffset.z; + this.quaternion.x = this.parentEntity.quaternion.x; + this.quaternion.y = this.parentEntity.quaternion.y; + this.quaternion.z = this.parentEntity.quaternion.z; + this.quaternion.w = this.parentEntity.quaternion.w; - this.scale.x = this.parentEntity.scale.x * this.scaleOffset.x; - this.scale.y = this.parentEntity.scale.y * this.scaleOffset.y; - this.scale.z = this.parentEntity.scale.z * this.scaleOffset.z; + this.position.x = this.parentEntity.position.x; + this.position.y = this.parentEntity.position.y; + this.position.z = this.parentEntity.position.z; - this.quaternion.x = this.parentEntity.quaternion.x;// + this.quaternionOffset.x; - this.quaternion.y = this.parentEntity.quaternion.y;// + this.quaternionOffset.y; - this.quaternion.z = this.parentEntity.quaternion.z;// + this.quaternionOffset.z; - this.quaternion.w = this.parentEntity.quaternion.w;// + this.quaternionOffset.w; + this.scale.x = this.parentEntity.scale.x; + this.scale.y = this.parentEntity.scale.y; + this.scale.z = this.parentEntity.scale.z; - this.quaternion.axis.x = this.quaternionOffset.axis.x; - this.quaternion.axis.y = this.quaternionOffset.axis.y; - this.quaternion.axis.z = this.quaternionOffset.axis.z; - this.quaternion.updateInstance(); + + //this.quaternion.multiply(this.quaternionOffset).normalize(); + + //this.position.add(this.positionOffset.applyQuaternion(this.quaternion)); + + //this.quaternion.updateInstance(); + + //TODO: ifdef debug this --- start + + if (this.customCode) { + eval(this.customCode); + } + + + + //TODO: ifdef debug this --- end + + //this.quaternion.updateInstance(); //this.quaternion.setFromAngle(this.quaternionOffset.angle); - this.quaternion.normalize(); + //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.scale.x = this.scale.x; + this.mesh.scale.y = this.scale.y; + this.mesh.scale.z = this.scale.z; + this.mesh.updateInstance(); // this.updateInstance(); diff --git a/src/game-lib-component-mesh.js b/src/game-lib-component-mesh.js index d579879..e90b71c 100644 --- a/src/game-lib-component-mesh.js +++ b/src/game-lib-component-mesh.js @@ -3,16 +3,27 @@ * is. * @param id * @param name String + * @param graphics GameLib.D3.Graphics * @param parentEntity GameLib.D3.Entity * @param mesh GameLib.D3.Camera + * @param positionOffset + * @param scaleOffset + * @param quaternionOffset * @constructor */ GameLib.D3.ComponentMesh = function ComponentMesh( id, name, + graphics, parentEntity, - mesh + mesh, + positionOffset, + scaleOffset, + quaternionOffset ) { + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + GameLib.D3.Component.call( this, id, @@ -31,6 +42,43 @@ GameLib.D3.ComponentMesh = function ComponentMesh( mesh = null; } this.mesh = mesh; + + /** + * Position + */ + if (GameLib.D3.Utils.UndefinedOrNull(positionOffset)) { + positionOffset = new GameLib.D3.Vector3( + graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + } + this.positionOffset = positionOffset; + + /** + * Rotation + */ + if (GameLib.D3.Utils.UndefinedOrNull(quaternionOffset)) { + quaternionOffset = new GameLib.D3.Quaternion( + graphics, + this, + new GameLib.D3.API.Quaternion(1, 0, 0, 0) + ); + } + this.quaternionOffset = quaternionOffset; + + /** + * Scale + */ + if (GameLib.D3.Utils.UndefinedOrNull(scaleOffset)) { + scaleOffset = new GameLib.D3.Vector3( + graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + } + this.scaleOffset = scaleOffset; + }; GameLib.D3.ComponentMesh.prototype = Object.create(GameLib.D3.Component.prototype); @@ -38,29 +86,17 @@ GameLib.D3.ComponentMesh.prototype.constructor = GameLib.D3.ComponentMesh; /** - * onLateUpdate override method + * onUpdate override method * @override * @callback */ -GameLib.D3.ComponentMesh.prototype.onLateUpdate = function() { +GameLib.D3.ComponentMesh.prototype.onUpdate = function() { if (this.mesh) { - this.mesh.position.x = this.parentEntity.position.x; - this.mesh.position.y = this.parentEntity.position.y; - this.mesh.position.z = this.parentEntity.position.z; - - this.mesh.scale.x = this.parentEntity.scale.x; - this.mesh.scale.y = this.parentEntity.scale.y; - this.mesh.scale.z = this.parentEntity.scale.z; - - /** - * Caller is responsible for correct quaternion - i.e. normalize quaternion if needed - */ - this.mesh.quaternion.x = this.parentEntity.quaternion.x; - this.mesh.quaternion.y = this.parentEntity.quaternion.y; - this.mesh.quaternion.z = this.parentEntity.quaternion.z; - this.mesh.quaternion.w = this.parentEntity.quaternion.w; + this.mesh.position = this.parentEntity.position.copy().add(this.positionOffset); + this.mesh.scale = this.parentEntity.scale.copy().add(this.scaleOffset); + this.mesh.quaternion = this.parentEntity.quaternion.copy().multiply(this.quaternionOffset).normalize(); this.mesh.updateInstance(); } diff --git a/src/game-lib-mesh.js b/src/game-lib-mesh.js index c1c281a..3200277 100644 --- a/src/game-lib-mesh.js +++ b/src/game-lib-mesh.js @@ -5,21 +5,35 @@ * @param apiMesh GameLib.D3.API.Mesh * @constructor */ -GameLib.D3.Mesh = function Mesh( +GameLib.D3.Mesh = function RuntimeMesh( graphics, computeNormals, apiMesh ) { - for (var property in apiMesh) { - if (apiMesh.hasOwnProperty(property)) { - this[property] = apiMesh[property]; - } - } - this.graphics = graphics; - this.graphics.isNotThreeThrow(); + + GameLib.D3.API.Mesh.call( + this, + apiMesh.id, + apiMesh.meshType, + apiMesh.name, + apiMesh.vertices, + apiMesh.faces, + apiMesh.faceVertexUvs, + apiMesh.materials, + apiMesh.parentMeshId, + apiMesh.parentSceneId, + apiMesh.skeleton, + apiMesh.skinIndices, + apiMesh.skinWeights, + apiMesh.position, + apiMesh.quaternion, + apiMesh.scale, + apiMesh.up + ); + this.position = new GameLib.D3.Vector3( graphics, this, @@ -41,24 +55,38 @@ GameLib.D3.Mesh = function Mesh( 0.001 ); - - /** - * We don't do a Runtime rotation since it interferes with the quaternion update - */ - this.quaternion = new GameLib.D3.Quaternion( graphics, this, this.quaternion ); + this.localRotation = new GameLib.D3.Vector3( + graphics, + this, + this.localRotation + ); + + this.localPosition = new GameLib.D3.Vector3( + graphics, + this, + this.localPosition + ); + + this.localScale = new GameLib.D3.Vector3( + graphics, + this, + this.localScale + ); + this.computeNormals = computeNormals; this.instance = this.createInstance(false); - - this.needsUpdate = false; }; +GameLib.D3.Mesh.prototype = Object.create(GameLib.D3.API.Mesh.prototype); +GameLib.D3.Mesh.prototype.constructor = GameLib.D3.Mesh; + /** * Mesh Type * @type {number} @@ -330,6 +358,10 @@ GameLib.D3.Mesh.prototype.createInstance = function(update) { instance.quaternion.z = this.quaternion.z; instance.quaternion.w = this.quaternion.w; + instance.rotateX(this.localRotation.x); + instance.rotateY(this.localRotation.y); + instance.rotateZ(this.localRotation.z); + return instance; }; diff --git a/src/game-lib-quaternion.js b/src/game-lib-quaternion.js index 37c1a30..4baee37 100644 --- a/src/game-lib-quaternion.js +++ b/src/game-lib-quaternion.js @@ -12,25 +12,22 @@ GameLib.D3.Quaternion = function RuntimeQuaternion( apiQuaternion, grain ) { - - for (var property in apiQuaternion) { - if (apiQuaternion.hasOwnProperty(property)) { - this[property] = apiQuaternion[property]; - } - } - - GameLib.D3.Utils.Extend(GameLib.D3.Quaternion, GameLib.D3.API.Quaternion); - this.graphics = graphics; - this.graphics.isNotThreeThrow(); - this.parentObject = parentObject; - - if (GameLib.D3.Utils.UndefinedOrNull(grain)) { - grain = 0.001; - } - this.grain = grain; + GameLib.D3.API.Quaternion.call( + this, + apiQuaternion.x, + apiQuaternion.y, + apiQuaternion.z, + apiQuaternion.w, + new GameLib.D3.API.Vector3( + apiQuaternion.axis.x, + apiQuaternion.axis.y, + apiQuaternion.axis.z + ), + apiQuaternion.angle + ); this.axis = new GameLib.D3.Vector3( this.graphics, @@ -39,9 +36,22 @@ GameLib.D3.Quaternion = function RuntimeQuaternion( 0.001 ); + if (GameLib.D3.Utils.UndefinedOrNull(parentObject)) { + parentObject = null; + } + this.parentObject = parentObject; + + if (GameLib.D3.Utils.UndefinedOrNull(grain)) { + grain = 0.001; + } + this.grain = grain; + this.instance = this.createInstance(); }; +GameLib.D3.Quaternion.prototype = Object.create(GameLib.D3.API.Quaternion.prototype); +GameLib.D3.Quaternion.prototype.constructor = GameLib.D3.Quaternion; + /** * Creates an instance quaternion * @param update @@ -90,51 +100,3 @@ GameLib.D3.Quaternion.prototype.toApiQuaternion = function() { this.angle ); }; - -GameLib.D3.Quaternion.prototype.normalize = function () { - - this.updateInstance(); - - this.instance.normalize(); - - this.x = this.instance.x; - this.y = this.instance.y; - this.z = this.instance.z; - this.w = this.instance.w; - - return this; -}; - -/** - * - * @param matrix4 GameLib.D3.Matrix4 - */ -GameLib.D3.Quaternion.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; -}; - -/** - * - * @param quaternion GameLib.D3.Quaternion - * @param t - * @returns {GameLib.D3.Quaternion} - */ -GameLib.D3.Quaternion.prototype.slerp = function (quaternion, t) { - - this.updateInstance(); - - this.instance.slerp(quaternion.instance, t); - - this.x = this.instance.x; - this.y = this.instance.y; - this.z = this.instance.z; - this.w = this.instance.w; - - return this; -};