diff --git a/src/game-lib-api-camera.js b/src/game-lib-api-camera.js index ad10a53..6777019 100644 --- a/src/game-lib-api-camera.js +++ b/src/game-lib-api-camera.js @@ -15,6 +15,7 @@ * @param maxY * @param minZ * @param maxZ + * @param quaternion GameLib.D3.Vector4 * @constructor */ GameLib.D3.API.Camera = function( @@ -32,7 +33,8 @@ GameLib.D3.API.Camera = function( minY, maxY, minZ, - maxZ + maxZ, + quaternion ) { if (GameLib.D3.Utils.UndefinedOrNull(id)) { id = GameLib.D3.Utils.RandomId(); @@ -60,7 +62,7 @@ GameLib.D3.API.Camera = function( this.aspect = aspect; if (GameLib.D3.Utils.UndefinedOrNull(near)) { - near = 0.1; + near = 0.001; } this.near = near; @@ -78,6 +80,11 @@ GameLib.D3.API.Camera = function( } this.position = position; + if (GameLib.D3.Utils.UndefinedOrNull(quaternion)) { + quaternion = new GameLib.D3.API.Vector4(); + } + this.quaternion = quaternion; + if (GameLib.D3.Utils.UndefinedOrNull(lookAt)) { lookAt = new GameLib.D3.API.Vector3( 0, diff --git a/src/game-lib-api-matrix4.js b/src/game-lib-api-matrix4.js index ec743f7..6493ddf 100644 --- a/src/game-lib-api-matrix4.js +++ b/src/game-lib-api-matrix4.js @@ -33,4 +33,114 @@ GameLib.D3.API.Matrix4 = function ApiMatrix4( row3 = new GameLib.D3.API.Vector4(0, 0, 0, 1); } this.rows[3] = row3; -}; \ No newline at end of file +}; + +GameLib.D3.API.Matrix4.prototype.rotationMatrixX = function (radians) { + this.identity(); + this.rows[1] = new GameLib.D3.API.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0); + this.rows[2] = new GameLib.D3.API.Vector4(0, Math.sin(radians), Math.cos(radians), 0); + return this; +}; + +GameLib.D3.API.Matrix4.prototype.rotationMatrixY = function (radians) { + this.identity(); + this.rows[0] = new GameLib.D3.API.Vector4( + Math.cos(radians), + 0, + Math.sin(radians), + 0 + ); + this.rows[2] = new GameLib.D3.API.Vector4( + -1 * Math.sin(radians), + 0, + Math.cos(radians), + 0 + ); + return this; +}; + +GameLib.D3.API.Matrix4.prototype.rotationMatrixZ = function (radians) { + this.identity(); + this.rows[0] = new GameLib.D3.API.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0); + this.rows[1] = new GameLib.D3.API.Vector4(Math.sin(radians), Math.cos(radians), 0, 0); + return this; +}; + +GameLib.D3.API.Matrix4.prototype.rotateX = function (radians, point) { + this.identity(); + this.rotationMatrixX(radians); + return this.multiply(point); +}; + +GameLib.D3.API.Matrix4.prototype.rotateY = function (radians, point) { + this.identity(); + this.rotationMatrixY(radians); + return this.multiply(point); +}; + +GameLib.D3.API.Matrix4.prototype.rotateZ = function (radians, point) { + this.identity(); + this.rotationMatrixZ(radians); + return this.multiply(point); +}; + +GameLib.D3.API.Matrix4.prototype.multiply = function (mvp) { + if (mvp instanceof GameLib.D3.API.Vector4) { + return new GameLib.D3.API.Vector4( + this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w, + this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w, + this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w, + this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w + ); + } else if (mvp instanceof GameLib.D3.API.Vector3) { + return new GameLib.D3.API.Vector3( + this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z, + this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z, + this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + ); + } +}; + +GameLib.D3.API.Matrix4.prototype.identity = function () { + this.rows = [ + new GameLib.D3.API.Vector4(1, 0, 0, 0), + new GameLib.D3.API.Vector4(0, 1, 0, 0), + new GameLib.D3.API.Vector4(0, 0, 1, 0), + new GameLib.D3.API.Vector4(0, 0, 0, 1) + ]; +}; + +GameLib.D3.API.Matrix4.prototype.lookAt = function (position, target, up) { + + 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-api-vector3.js b/src/game-lib-api-vector3.js index 438701b..23d36de 100644 --- a/src/game-lib-api-vector3.js +++ b/src/game-lib-api-vector3.js @@ -15,4 +15,236 @@ GameLib.D3.API.Vector3 = function ApiVector3(x, y, z) { } this.z = z; +}; + +GameLib.D3.API.Vector3.prototype.negate = function() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + return this; +}; + +GameLib.D3.API.Vector3.prototype.subtract = function (v) { + return new GameLib.D3.API.Vector3( + this.x - v.x, + this.y - v.y, + this.z - v.z + ); +}; + +GameLib.D3.API.Vector3.prototype.sub = function (v) { + return new GameLib.D3.API.Vector3( + this.x - v.x, + this.y - v.y, + this.z - v.z + ); +}; + +GameLib.D3.API.Vector3.prototype.cross = function (v) { + return new GameLib.D3.API.Vector3( + this.y * v.z - this.z * v.y, + this.z * v.x - this.x * v.z, + this.x * v.y - this.y * v.x + ); +}; + +GameLib.D3.API.Vector3.clockwise = function (u, v, w, viewPoint) { + var normal = GameLib.D3.API.Vector3.normal(u, v, w); + var uv = u.copy(); + var winding = normal.dot(uv.subtract(viewPoint)); + return (winding > 0); +}; + +GameLib.D3.API.Vector3.normal = function (u, v, w) { + var vv = v.copy(); + var wv = w.copy(); + return vv.subtract(u).cross(wv.subtract(u)); +}; + +GameLib.D3.API.Vector3.prototype.lookAt = function (at, up) { + var lookAtMatrix = GameLib.D3.API.Matrix4.lookAt(this, at, up); + return this.multiply(lookAtMatrix); +}; + +GameLib.D3.API.Vector3.prototype.translate = function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; +}; + +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 + ); +}; + +GameLib.D3.API.Vector3.prototype.squared = function () { + return this.x * this.x + this.y * this.y + this.z * this.z; +}; + +GameLib.D3.API.Vector3.prototype.copy = function () { + return new GameLib.D3.API.Vector3( + this.x, + this.y, + this.z + ); +}; + +GameLib.D3.API.Vector3.prototype.set = function (x, y, z) { + this.x = x; + this.y = y; + this.z = z; +}; + +GameLib.D3.API.Vector3.prototype.lerp = function ( v, alpha ) { + return new GameLib.D3.API.Vector3( + this.x + ( v.x - this.x ) * alpha, + this.y + ( v.y - this.y ) * alpha, + this.z + ( v.z - this.z ) * alpha + ); +}; + +GameLib.D3.API.Vector3.prototype.distanceTo = function(v) { + var dx = this.x - v.x, + dy = this.y - v.y, + dz = this.z - v.z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); +}; + +/** + * @return {number} + */ +GameLib.D3.API.Vector3.AngleDirection = function(forward, directionToCheck, up) { + var perp = forward.cross(directionToCheck); + var dir = perp.dot(up); + + if (dir > 0.0) { + return 1.0; + } else if (dir < 0.0) { + return -1.0; + } else { + return 0.0; + } + +}; + +GameLib.D3.API.Vector3.prototype.multiply = function (s) { + + var x, y, z; + + if (s instanceof GameLib.D3.API.Vector3) { + + return new GameLib.D3.API.Vector3( + this.x * s.x, + this.y * s.y, + this.z * s.z + ) + + } else if (s instanceof GameLib.D3.API.Matrix4) { + + 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; + + return new GameLib.D3.API.Vector3( + x, + y, + z + ); + + } else if (s instanceof GameLib.D3.API.Matrix3) { + + 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; + + return new GameLib.D3.API.Vector3( + x, + y, + z + ); + + } else if(!isNaN(parseFloat(s)) && isFinite(s)) { + + return new GameLib.D3.API.Vector3( + this.x * s, + this.y * s, + this.z * s + ); + + } else { + console.log("functionality not implemented - please do this"); + throw new Error("not implemented"); + } +}; + + +GameLib.D3.API.Vector3.prototype.dot = function (v) { + return (this.x * v.x) + (this.y * v.y) + (this.z * v.z); +}; + +GameLib.D3.API.Vector3.prototype.normalize = function () { + var EPSILON = 0.000001; + var v2 = this.squared(); + + if (v2 < EPSILON) { + return this; //do nothing for zero vector + } + + var invLength = 1.0 / Math.sqrt(v2); + return new GameLib.D3.API.Vector3( + this.x * invLength, + this.y * invLength, + this.z * invLength + ); +}; + +GameLib.D3.API.Vector3.prototype.clone = function () { + return new GameLib.D3.API.Vector3( + this.x, + this.y, + this.z + ); +}; + +GameLib.D3.API.Vector3.prototype.applyQuaternion = function(q) { + var x = this.x, y = this.y, z = this.z; + var qx = q.x, qy = q.y, qz = q.z, qw = q.w; + + // calculate quat * vector + + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var iw = - qx * x - qy * y - qz * z; + + // calculate result * inverse quat + + 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; +}; + +GameLib.D3.API.Vector3.prototype.clamp = function(min, max) { + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + + return this; +}; + +GameLib.D3.API.Vector3.prototype.length = function() { + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); +}; + +GameLib.D3.API.Vector3.prototype.reflect = function(normal) { + return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) ); +}; + +GameLib.D3.API.Vector3.prototype.angleTo = function (v) { + var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); + return Math.acos( exports.Math.clamp( theta, - 1, 1 ) ); }; \ No newline at end of file diff --git a/src/game-lib-api-vector4-a.js b/src/game-lib-api-vector4-a.js new file mode 100644 index 0000000..2e9cd9e --- /dev/null +++ b/src/game-lib-api-vector4-a.js @@ -0,0 +1,97 @@ +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; + +}; + +GameLib.D3.API.Vector4.prototype.translate = function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; +}; + +GameLib.D3.API.Vector4.prototype.copy = function () { + return new GameLib.D3.API.Vector4( + this.x, + this.y, + this.z, + this.w + ); +}; + +/** + * Note, this normalize function leaves 'w' component untouched + */ +GameLib.D3.API.Vector4.prototype.normalize = function () { + + 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; +}; + +GameLib.D3.API.Vector4.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; + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } else { + console.log("functionality not implemented - please do this"); + throw new Error("not implemented"); + } +}; + +GameLib.D3.API.Vector4.prototype.subtract = function (v) { + + if (v instanceof GameLib.D3.API.Vector3) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + } + + if (v instanceof GameLib.D3.API.Vector4) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + } + + return this; +}; \ No newline at end of file diff --git a/src/game-lib-api-vector4-points.js b/src/game-lib-api-vector4-points.js new file mode 100644 index 0000000..98c1abe --- /dev/null +++ b/src/game-lib-api-vector4-points.js @@ -0,0 +1,224 @@ +GameLib.D3.API.Vector4.Points = function () { + this.vectors = []; +}; + +GameLib.D3.API.Vector4.Points.prototype.add = function (vector) { + + if (vector instanceof GameLib.D3.API.Vector3) { + vector = new GameLib.D3.API.Vector4( + vector.x, + vector.y, + vector.z, + 1 + ) + } + + if (!vector instanceof GameLib.D3.API.Vector4) { + console.warn("Vector needs to be of type Vector4"); + throw new Error("Vector needs to be of type Vector4"); + } + + this.vectors.push(vector); + + return this; +}; + +GameLib.D3.API.Vector4.Points.prototype.copy = function () { + + var vectors = []; + + for (var i = 0; i < this.vectors.length; i++) { + vectors.push(this.vectors[i].copy()); + } + + return vectors; +}; + +GameLib.D3.API.Vector4.Points.prototype.maximizeXDistance = function (grain) { + +// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); + + var multiplier = 0; + + var rotationMatrixY = new GameLib.D3.API.Matrix4().rotationMatrixY(grain); + + var totalRadians = 0; + + var backupVectors = this.copy(); + + var maxXDistance = 0; + + for (var i = 0; i < Math.PI * 2; i += grain) { + + multiplier++; + + for (var j = 0; j < this.vectors.length; j++) { + this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]); + } + + var distances = this.distances(); + + if (distances.x > maxXDistance) { + + maxXDistance = distances.x; + totalRadians = multiplier * grain; + } + } + + this.vectors = backupVectors; + +// console.log("distance: " + maxXDistance + " radians : " + totalRadians); + + var maxRotationMatrix = new GameLib.D3.API.Matrix4().rotationMatrixY(totalRadians); + + for (var k = 0; k < this.vectors.length; k++) { + this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]); + } + +// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2)); + +}; + +GameLib.D3.API.Vector4.Points.prototype.maximizeYDistance = function (grain) { + +// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); + + var multiplier = 0; + + var rotationMatrixX = new GameLib.D3.API.Matrix4().rotationMatrixX(grain); + + var totalRadians = 0; + + var backupVectors = this.copy(); + + var maxYDistance = 0; + + for (var i = 0; i < Math.PI * 2; i += grain) { + + multiplier++; + + for (var j = 0; j < this.vectors.length; j++) { + this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]); + } + + var distances = this.distances(); + + if (distances.y > maxYDistance) { + maxYDistance = distances.y; + totalRadians = multiplier * grain; + } + } + + this.vectors = backupVectors; + +// console.log("distance: " + maxYDistance + " radians : " + totalRadians); + + var maxRotationMatrix = new GameLib.D3.API.Matrix4().rotationMatrixX(totalRadians); + + for (var k = 0; k < this.vectors.length; k++) { + this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]); + } + +// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2)); + +}; + + +GameLib.D3.API.Vector4.Points.prototype.lookAt = function (at, up) { + + var polyCenter = this.average(); + + console.log("poly center : " + JSON.stringify(polyCenter)); + + var lookAtMatrix = new GameLib.D3.API.Matrix4().lookAt(polyCenter, at, up); + + lookAtMatrix.rows[0] = new GameLib.D3.API.Vector4(1, 0, 0, 0); + lookAtMatrix.rows[1] = new GameLib.D3.API.Vector4(0, 0, 1, 0); + lookAtMatrix.rows[2] = new GameLib.D3.API.Vector4(0, 1, 0, 0); + + console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2)); + + for (var i = 0; i < this.vectors.length; i++) { + console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i])); + this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]); + console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i])); + } +}; + +GameLib.D3.API.Vector4.Points.prototype.distances = function () { + + var minX = this.vectors[0].x; + var minY = this.vectors[0].y; + var minZ = this.vectors[0].z; + + var maxX = this.vectors[0].x; + var maxY = this.vectors[0].y; + var maxZ = this.vectors[0].z; + + for (var i = 0; i < this.vectors.length; i++) { + if (this.vectors[i].x < minX) { + minX = this.vectors[i].x; + } + if (this.vectors[i].y < minY) { + minY = this.vectors[i].y; + } + if (this.vectors[i].z < minZ) { + minZ = this.vectors[i].z; + } + + if (this.vectors[i].x > maxX) { + maxX = this.vectors[i].x; + } + if (this.vectors[i].y > maxY) { + maxY = this.vectors[i].y; + } + if (this.vectors[i].z > maxZ) { + maxZ = this.vectors[i].z; + } + } + + return new GameLib.D3.API.Vector3( + Math.abs(maxX - minX), + Math.abs(maxY - minY), + Math.abs(maxY - minZ) + ) +}; + +GameLib.D3.API.Vector4.Points.prototype.average = function () { + var averageX = 0; + var averageY = 0; + var averageZ = 0; + + for (var i = 0; i < this.vectors.length; i++) { + averageX += this.vectors[i].x; + averageY += this.vectors[i].y; + averageZ += this.vectors[i].z; + } + + return new GameLib.D3.API.Vector3( + averageX / this.vectors.length, + averageY / this.vectors.length, + averageZ / this.vectors.length + ); +}; + +GameLib.D3.API.Vector4.Points.prototype.negate = function () { + + for (var i = 0; i < this.vectors.length; i++) { + this.vectors[i].x *= -1; + this.vectors[i].y *= -1; + this.vectors[i].z *= -1; + } + + return this; +}; + + +GameLib.D3.API.Vector4.Points.prototype.toOrigin = function () { + + var distanceFromOrigin = this.average().negate(); + + for (var i = 0; i < this.vectors.length; i++) { + this.vectors[i].translate(distanceFromOrigin); + } +}; \ No newline at end of file diff --git a/src/game-lib-api-vector4.js b/src/game-lib-api-vector4.js deleted file mode 100644 index 84d4845..0000000 --- a/src/game-lib-api-vector4.js +++ /dev/null @@ -1,23 +0,0 @@ -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-camera.js b/src/game-lib-camera.js index 588fe95..69d806c 100644 --- a/src/game-lib-camera.js +++ b/src/game-lib-camera.js @@ -24,6 +24,12 @@ GameLib.D3.Camera = function Camera( this.position ); + this.quaternion = new GameLib.D3.Vector4( + graphics, + this, + this.quaternion + ); + this.lookAt = new GameLib.D3.Vector3( graphics, this, @@ -88,9 +94,16 @@ GameLib.D3.Camera.prototype.createInstance = function(update) { instance.far = this.far; } - 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.lookAt(this.lookAt.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; + +// instance.lookAt(this.lookAt.instance); instance.updateProjectionMatrix(); diff --git a/src/game-lib-component-camera.js b/src/game-lib-component-camera.js index d105a6c..1dc2b61 100644 --- a/src/game-lib-component-camera.js +++ b/src/game-lib-component-camera.js @@ -4,31 +4,36 @@ * @param id * @param name String * @param camera GameLib.D3.Camera + * @param parentEntity GameLib.D3.Entity * @constructor */ GameLib.D3.ComponentCamera = function ComponentCamera( id, name, - camera + camera, + parentEntity ) { - 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; - // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. - GameLib.D3.Utils.Extend(GameLib.D3.ComponentCamera, GameLib.D3.ComponentInterface); - - if (typeof camera == 'undefined') { + if (GameLib.D3.Utils.UndefinedOrNull(camera)) { camera = null; } + this.camera = camera; - // Component fields - this.camera = camera.instance; + GameLib.D3.Utils.Extend(GameLib.D3.ComponentCamera, GameLib.D3.ComponentInterface); }; ///////////////////////// Methods to override ////////////////////////// @@ -36,11 +41,25 @@ GameLib.D3.ComponentCamera.prototype.onLateUpdate = function( deltaTime, parentEntity ) { - this.camera.quaternion.copy(parentEntity.quaternion).normalize(); - this.camera.position.copy(parentEntity.position); - parentEntity.quaternion.x = this.camera.quaternion.x; - parentEntity.quaternion.y = this.camera.quaternion.y; - parentEntity.quaternion.z = this.camera.quaternion.z; - parentEntity.quaternion.w = this.camera.quaternion.w; + if (this.camera) { + + this.camera.quaternion.copy(this.parentEntity.quaternion); + this.camera.quaternion.normalize(); + + this.camera.position.copy(this.parentEntity.position); + + this.camera.quaternion.updateInstance(); + this.camera.position.updateInstance(); + + this.parentEntity.quaternion.x = this.camera.quaternion.x; + this.parentEntity.quaternion.y = this.camera.quaternion.y; + this.parentEntity.quaternion.z = this.camera.quaternion.z; + this.parentEntity.quaternion.w = this.camera.quaternion.w; + + this.parentEntity.quaternion.updateInstance(); + } else { + console.warn('no camera object'); + } + }; \ No newline at end of file diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js index 9958864..0fb230d 100644 --- a/src/game-lib-component-follow.js +++ b/src/game-lib-component-follow.js @@ -2,31 +2,49 @@ * * @param id * @param name + * @param graphics GameLib.D3.Graphics * @param targetEntity GameLib.D3.Entity * @param targetOffset GameLib.D3.API.Vector3 * @param minDistance * @param moveSpeed + * @param parentEntity + * @param target GameLib.D3.Vector3 + * @param targetToParent GameLib.D3.Vector3 + * @param rotatedTargetOffset GameLib.D3.Vector3 + * @param rotated GameLib.D3.Vector4 * @constructor */ GameLib.D3.ComponentFollow = function ComponentFollow( id, name, + graphics, targetEntity, targetOffset, minDistance, - moveSpeed + moveSpeed, + parentEntity, + target, + targetToParent, + rotatedTargetOffset, + rotated ) { - 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; - // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. - GameLib.D3.Utils.Extend(GameLib.D3.ComponentFollow, GameLib.D3.ComponentInterface); + this.graphics = graphics; + this.graphics.isNotThreeThrow(); - this.parentEntity = null; + if (GameLib.D3.Utils.UndefinedOrNull(parentEntity)) { + parentEntity = null; + } + this.parentEntity = parentEntity; if (GameLib.D3.Utils.UndefinedOrNull(targetEntity)) { targetEntity = null; @@ -34,20 +52,62 @@ GameLib.D3.ComponentFollow = function ComponentFollow( this.targetEntity = targetEntity; if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) { - targetOffset = new GameLib.D3.API.Vector3(0, 0, 0); + targetOffset = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); } this.targetOffset = targetOffset; - this.moveSpeed = moveSpeed || 12.5; - this.minDistance = minDistance || 0; -}; + if (GameLib.D3.Utils.UndefinedOrNull(moveSpeed)) { + moveSpeed = 12.5; + } + this.moveSpeed = moveSpeed; -if(typeof THREE != "undefined") { - ComponentFollow_Target_Vec3 = new THREE.Vector3(); - ComponentFollow_TargetToParent_Vec3 = new THREE.Vector3(); - ComponentFollow_rotatedTargetOffset_Vec3 = new THREE.Vector3(); - ComponentFollow_tempQuaternion = new THREE.Quaternion(); -} + if (GameLib.D3.Utils.UndefinedOrNull(minDistance)) { + minDistance = 0; + } + this.minDistance = minDistance; + + if (GameLib.D3.Utils.UndefinedOrNull(target)) { + target = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + } + this.target = target; + + if (GameLib.D3.Utils.UndefinedOrNull(targetToParent)) { + targetToParent = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + } + this.targetToParent = targetToParent; + + if (GameLib.D3.Utils.UndefinedOrNull(rotatedTargetOffset)) { + rotatedTargetOffset = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + } + this.rotatedTargetOffset = rotatedTargetOffset; + + if (GameLib.D3.Utils.UndefinedOrNull(rotated)) { + rotated = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + } + this.rotated = rotated; + + GameLib.D3.Utils.Extend(GameLib.D3.ComponentFollow, GameLib.D3.ComponentInterface); +}; ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentFollow.prototype.onUpdate = function( @@ -55,54 +115,57 @@ GameLib.D3.ComponentFollow.prototype.onUpdate = function( parentEntity ) { - if(this.targetEntity) { + if (this.targetEntity) { - ComponentFollow_tempQuaternion.set( - this.targetEntity.quaternion.x, - this.targetEntity.quaternion.y, - this.targetEntity.quaternion.z, - this.targetEntity.quaternion.w - ); + this.rotated.x = this.targetEntity.quaternion.x; + this.rotated.y = this.targetEntity.quaternion.y; + this.rotated.z = this.targetEntity.quaternion.z; + this.rotated.w = this.targetEntity.quaternion.w; - ComponentFollow_rotatedTargetOffset_Vec3.set( - this.targetOffset.x, - this.targetOffset.y, - this.targetOffset.z - ); + this.rotated.updateInstance(); - ComponentFollow_rotatedTargetOffset_Vec3 = - ComponentFollow_rotatedTargetOffset_Vec3.applyQuaternion( - ComponentFollow_tempQuaternion - ); + this.rotatedTargetOffset.x = this.targetOffset.x; + this.rotatedTargetOffset.y = this.targetOffset.y; + this.rotatedTargetOffset.z = this.targetOffset.z; - ComponentFollow_Target_Vec3.set( - this.targetEntity.position.x + ComponentFollow_rotatedTargetOffset_Vec3.x, - this.targetEntity.position.y + ComponentFollow_rotatedTargetOffset_Vec3.y, - this.targetEntity.position.z + ComponentFollow_rotatedTargetOffset_Vec3.z - ); + this.rotatedTargetOffset.applyQuaternion(this.rotated); - ComponentFollow_TargetToParent_Vec3.set( - parentEntity.position.x - this.targetEntity.position.x, - parentEntity.position.y - this.targetEntity.position.y, - parentEntity.position.z - this.targetEntity.position.z - ); + this.rotatedTargetOffset.updateInstance(); - ComponentFollow_TargetToParent_Vec3.normalize(); + this.target.x = this.targetEntity.position.x + this.rotatedTargetOffset.x; + this.target.y = this.targetEntity.position.y + this.rotatedTargetOffset.y; + this.target.z = this.targetEntity.position.z + this.rotatedTargetOffset.z; - ComponentFollow_TargetToParent_Vec3.set( - ComponentFollow_TargetToParent_Vec3.x * this.minDistance, - ComponentFollow_TargetToParent_Vec3.y * this.minDistance, - ComponentFollow_TargetToParent_Vec3.z * this.minDistance - ); + this.target.updateInstance(); - ComponentFollow_Target_Vec3.set( - ComponentFollow_Target_Vec3.x + ComponentFollow_TargetToParent_Vec3.x, - ComponentFollow_Target_Vec3.y + ComponentFollow_TargetToParent_Vec3.y, - ComponentFollow_Target_Vec3.z + ComponentFollow_TargetToParent_Vec3.z - ); + this.targetToParent.x = this.parentEntity.position.x - this.targetEntity.position.x; + this.targetToParent.y = this.parentEntity.position.y - this.targetEntity.position.y; + this.targetToParent.z = this.parentEntity.position.z - this.targetEntity.position.z; + + this.targetToParent.normalize(); + + this.targetToParent.x *= this.minDistance; + this.targetToParent.y *= this.minDistance; + this.targetToParent.z *= this.minDistance; + + this.targetToParent.updateInstance(); + + this.target.x = this.target.x + this.targetToParent.x; + this.target.y = this.target.y + this.targetToParent.y; + this.target.z = this.target.z + this.targetToParent.z; + + this.target.updateInstance(); var t = deltaTime * this.moveSpeed; + //t = t * t * t * (t * (6.0 * t - 15.0) + 10.0); - parentEntity.position = parentEntity.position.lerp(ComponentFollow_Target_Vec3, t); + + var lerp = this.parentEntity.position.lerp(this.target, t); + + this.parentEntity.position.x = lerp.x; + this.parentEntity.position.y = lerp.y; + this.parentEntity.position.z = lerp.z; + + this.parentEntity.position.updateInstance(); } }; \ No newline at end of file diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js index 1e74357..b4962cc 100644 --- a/src/game-lib-component-look-at.js +++ b/src/game-lib-component-look-at.js @@ -1,116 +1,128 @@ /** - * + * Looks from parentEntity to targetEntity (default up is 0,1,0) * @param id * @param name - * @param targetEntity - * @param targetOffset + * @param graphics GameLib.D3.Graphics + * @param parentEntity GameLib.D3.Entity + * @param targetEntity GameLib.D3.Entity + * @param targetOffset GameLib.D3.Vector3 * @param rotationSpeed + * @param lookAtMatrix GameLib.D3.Matrix4 + * @param up GameLib.D3.Vector3 * @constructor */ GameLib.D3.ComponentLookAt = function ComponentLookAt( id, name, + graphics, + parentEntity, targetEntity, targetOffset, - rotationSpeed + rotationSpeed, + lookAtMatrix, + up ) { - this.id = id || GameLib.D3.Utils.RandomId(); + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + 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; - - // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. - GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface); - - // todo: USE TARGET OFFSET. + if (GameLib.D3.Utils.UndefinedOrNull(parentEntity)) { + parentEntity = null; + } + this.parentEntity = parentEntity; + + if (GameLib.D3.Utils.UndefinedOrNull(targetEntity)) { + targetEntity = null; + } this.targetEntity = targetEntity; if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) { - targetOffset = new GameLib.D3.API.Vector3(0, 0, 0); + targetOffset = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); } this.targetOffset = targetOffset; - this.lastTargetQuaternion = new GameLib.D3.API.Vector4(0, 0, 0, 1); - this.rotationSpeed = rotationSpeed || 22.0; -}; + if (GameLib.D3.Utils.UndefinedOrNull(rotationSpeed)) { + rotationSpeed = 22.0; + } + this.rotationSpeed = rotationSpeed; -if(typeof THREE != "undefined") { - ComponentLookAt_rotatedTargetOffset = new THREE.Vector3(); - ComponentLookAt_currentPos = new THREE.Vector3(); - ComponentLookAt_targetPos = new THREE.Vector3(); - ComponentLookAt_upVector = new THREE.Vector3(0, 1, 0); - ComponentLookAt_targetQuaternion = new THREE.Quaternion(0, 0, 0, 1); - ComponentLookAt_tmpQuaternion = new THREE.Quaternion(0, 0, 0, 1); - ComponentLookAt_newRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); - ComponentLookAt_lastRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); - ComponentLookAt_lookAtMatrix = new THREE.Matrix4(); -} + if (GameLib.D3.Utils.UndefinedOrNull(lookAtMatrix)) { + lookAtMatrix = new GameLib.D3.Matrix4( + this.graphics, + this, + new GameLib.D3.API.Matrix4() + ); + } + this.lookAtMatrix = lookAtMatrix; + + if(GameLib.D3.Utils.UndefinedOrNull(up)) { + up = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 1, 0) + ); + } + this.up = up; + + this.targetPosition = new GameLib.D3.Vector3( + this.graphics, + this, + new GameLib.D3.API.Vector3(0, 0, 0) + ); + + this.currentRotation = new GameLib.D3.Vector4( + this.graphics, + this, + new GameLib.D3.API.Vector4() + ); + + GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface); +}; ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentLookAt.prototype.onUpdate = function( deltaTime, parentEntity ) { - if(this.targetEntity) { - var target = this.targetEntity.position; + if (this.targetEntity) { - ComponentLookAt_currentPos.set( - parentEntity.position.x, - parentEntity.position.y, - parentEntity.position.z + this.targetPosition.x = this.targetEntity.position.x + this.targetOffset.x; + this.targetPosition.y = this.targetEntity.position.y + this.targetOffset.y; + this.targetPosition.z = this.targetEntity.position.z + this.targetOffset.z; + + this.targetPosition.updateInstance(); + + this.lookAtMatrix.lookAt( + this.parentEntity.position, + this.targetPosition, + this.up ); - ComponentLookAt_lastRotationQuaternion.set( - this.lastTargetQuaternion.x, - this.lastTargetQuaternion.y, - this.lastTargetQuaternion.z, - this.lastTargetQuaternion.w - ); - - ComponentLookAt_rotatedTargetOffset.set( - this.targetOffset.x, - this.targetOffset.y, - this.targetOffset.z - ); - - ComponentLookAt_targetQuaternion.set( - this.targetEntity.quaternion.x, - this.targetEntity.quaternion.y, - this.targetEntity.quaternion.z, - this.targetEntity.quaternion.w - ); - - ComponentLookAt_rotatedTargetOffset = - ComponentLookAt_rotatedTargetOffset.applyQuaternion( - ComponentLookAt_targetQuaternion - ); - - ComponentLookAt_targetPos.set( - target.x + ComponentLookAt_rotatedTargetOffset.x, - target.y + ComponentLookAt_rotatedTargetOffset.y, - target.z + ComponentLookAt_rotatedTargetOffset.z - ); - - ComponentLookAt_lookAtMatrix.lookAt( - ComponentLookAt_currentPos, - ComponentLookAt_targetPos, - ComponentLookAt_upVector - ); - - ComponentLookAt_tmpQuaternion.setFromRotationMatrix(ComponentLookAt_lookAtMatrix); + this.currentRotation.setFromRotationMatrix(this.lookAtMatrix); var t = deltaTime * this.rotationSpeed; t = t * t * t * (t * (6.0 * t - 15.0) + 10.0); - THREE.Quaternion.slerp(ComponentLookAt_lastRotationQuaternion, ComponentLookAt_tmpQuaternion, ComponentLookAt_newRotationQuaternion, t); + this.currentRotation.slerp(this.currentRotation, t); - this.parentEntity.quaternion.x = this.lastTargetQuaternion.x = ComponentLookAt_newRotationQuaternion.x; - this.parentEntity.quaternion.y = this.lastTargetQuaternion.y = ComponentLookAt_newRotationQuaternion.y; - this.parentEntity.quaternion.z = this.lastTargetQuaternion.z = ComponentLookAt_newRotationQuaternion.z; - this.parentEntity.quaternion.w = this.lastTargetQuaternion.w = ComponentLookAt_newRotationQuaternion.w; + this.parentEntity.quaternion.x = this.currentRotation.x; + this.parentEntity.quaternion.y = this.currentRotation.y; + this.parentEntity.quaternion.z = this.currentRotation.z; + this.parentEntity.quaternion.w = this.currentRotation.w; + + this.parentEntity.quaternion.updateInstance(); } }; \ No newline at end of file diff --git a/src/game-lib-material.js b/src/game-lib-material.js index 91a93cb..b0f5287 100644 --- a/src/game-lib-material.js +++ b/src/game-lib-material.js @@ -271,6 +271,33 @@ GameLib.D3.Material.prototype.createInstance = function(update) { fog: this.fog }); + } else if (this.materialType == GameLib.D3.Material.MATERIAL_TYPE_BASIC) { + + instance = new THREE.MeshBasicMaterial({ + name: this.name, + opacity: this.opacity, + transparent: this.transparent, + blending: this.blending, + blendSrc: this.blendSrc, + blendDst: this.blendDst, + blendEquation: this.blendEquation, + depthTest: this.depthTest, + depthFunc: this.depthFunc, + depthWrite: this.depthWrite, + polygonOffset: this.polygonOffset, + polygonOffsetFactor: this.polygonOffsetFactor, + polygonOffsetUnits: this.polygonOffsetUnits, + alphaTest: this.alphaTest, + clippingPlanes: this.clippingPlanes, + clipShadows: this.clipShadows, + overdraw: this.overdraw, + visible: this.visible, + side: this.side, + color: this.color.instance, + vertexColors: GameLib.D3.Material.TYPE_NO_COLORS, + fog: this.fog + }); + } else { console.log("material type is not implemented yet: " + this.materialType + " - material indexes could be screwed up"); } diff --git a/src/game-lib-matrix-4.js b/src/game-lib-matrix-4.js index 3936b2a..fef1631 100644 --- a/src/game-lib-matrix-4.js +++ b/src/game-lib-matrix-4.js @@ -108,81 +108,6 @@ GameLib.D3.Matrix4.prototype.updateInstance = function() { this.createInstance(true); }; -GameLib.D3.Matrix4.prototype.rotationMatrixX = function (radians) { - this.identity(); - this.rows[1] = new GameLib.D3.API.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0); - this.rows[2] = new GameLib.D3.API.Vector4(0, Math.sin(radians), Math.cos(radians), 0); - return this; -}; - -GameLib.D3.Matrix4.prototype.rotationMatrixY = function (radians) { - this.identity(); - this.rows[0] = new GameLib.D3.API.Vector4( - Math.cos(radians), - 0, - Math.sin(radians), - 0 - ); - this.rows[2] = new GameLib.D3.API.Vector4( - -1 * Math.sin(radians), - 0, - Math.cos(radians), - 0 - ); - return this; -}; - -GameLib.D3.Matrix4.prototype.rotationMatrixZ = function (radians) { - this.identity(); - this.rows[0] = new GameLib.D3.API.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0); - this.rows[1] = new GameLib.D3.API.Vector4(Math.sin(radians), Math.cos(radians), 0, 0); - return this; -}; - -GameLib.D3.Matrix4.prototype.rotateX = function (radians, point) { - this.identity(); - this.rotationMatrixX(radians); - return this.multiply(point); -}; - -GameLib.D3.Matrix4.prototype.rotateY = function (radians, point) { - this.identity(); - this.rotationMatrixY(radians); - return this.multiply(point); -}; - -GameLib.D3.Matrix4.prototype.rotateZ = function (radians, point) { - this.identity(); - this.rotationMatrixZ(radians); - return this.multiply(point); -}; - -GameLib.D3.Matrix4.prototype.multiply = function (mvp) { - if (mvp instanceof GameLib.D3.API.Vector4) { - return new GameLib.D3.API.Vector4( - this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w, - this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w, - this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w, - this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w - ); - } else if (mvp instanceof GameLib.D3.API.Vector3) { - return new GameLib.D3.API.Vector3( - this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z, - this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z, - this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z - ); - } -}; - -GameLib.D3.Matrix4.prototype.identity = function () { - this.rows = [ - new GameLib.D3.API.Vector4(1, 0, 0, 0), - new GameLib.D3.API.Vector4(0, 1, 0, 0), - new GameLib.D3.API.Vector4(0, 0, 1, 0), - new GameLib.D3.API.Vector4(0, 0, 0, 1) - ]; -}; - GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) { this.instance.lookAt(position.instance, target.instance, up.instance); @@ -206,34 +131,5 @@ GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) { 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 6a09757..86f7d79 100644 --- a/src/game-lib-mesh.js +++ b/src/game-lib-mesh.js @@ -23,24 +23,34 @@ GameLib.D3.Mesh = function Mesh( this.position = new GameLib.D3.Vector3( graphics, this, - this.position + this.position, + 0.001 ); this.scale = new GameLib.D3.Vector3( graphics, this, - this.scale + this.scale, + 0.001 ); this.up = new GameLib.D3.Vector3( graphics, this, - this.up + this.up, + 0.001 ); + /** * We don't do a Runtime rotation since it interferes with the quaternion update */ + this.rotation = new GameLib.D3.Vector3( + graphics, + this, + this.rotation, + 0.001 + ); this.quaternion = new GameLib.D3.Vector4( graphics, @@ -322,8 +332,20 @@ GameLib.D3.Mesh.prototype.createInstance = function(update) { instance.up.z = this.up.z; /** - * We don't do rotation - its dealt with by quaternion + * We don't do rotation for now - it should be dealt with by quaternion */ + // instance.rotation.x = this.rotation.x; + // instance.rotation.y = this.rotation.y; + // instance.rotation.z = this.rotation.z; + // + // instance.quaternion.setFromEuler( + // new THREE.Euler( + // instance.rotation.x, + // instance.rotation.y, + // instance.rotation.z + // ) + // ); + // instance.quaternion.x = this.quaternion.x; instance.quaternion.y = this.quaternion.y; instance.quaternion.z = this.quaternion.z; diff --git a/src/game-lib-vector3.js b/src/game-lib-vector3.js index be480cb..2f68d88 100644 --- a/src/game-lib-vector3.js +++ b/src/game-lib-vector3.js @@ -73,238 +73,4 @@ GameLib.D3.Vector3.prototype.toApiVector = function() { this.y, this.z ); -}; - -GameLib.D3.Vector3.prototype.subtract = function (v) { - return new GameLib.D3.Vector3( - this.x - v.x, - this.y - v.y, - this.z - v.z - ); -}; - -GameLib.D3.Vector3.prototype.sub = function (v) { - return new GameLib.D3.Vector3( - this.x - v.x, - this.y - v.y, - this.z - v.z - ); -}; - -GameLib.D3.Vector3.prototype.cross = function (v) { - return new GameLib.D3.Vector3( - this.y * v.z - this.z * v.y, - this.z * v.x - this.x * v.z, - this.x * v.y - this.y * v.x - ); -}; - - -GameLib.D3.Vector3.clockwise = function (u, v, w, viewPoint) { - var normal = GameLib.D3.Vector3.normal(u, v, w); - var uv = u.copy(); - var winding = normal.dot(uv.subtract(viewPoint)); - return (winding > 0); -}; - -GameLib.D3.Vector3.normal = function (u, v, w) { - var vv = v.copy(); - var wv = w.copy(); - return vv.subtract(u).cross(wv.subtract(u)); -}; - -GameLib.D3.Vector3.prototype.lookAt = function (at, up) { - var lookAtMatrix = GameLib.D3.Matrix4.lookAt(this, at, up); - return this.multiply(lookAtMatrix); -}; - -GameLib.D3.Vector3.prototype.translate = function (v) { - this.x += v.x; - this.y += v.y; - this.z += v.z; - return this; -}; - -GameLib.D3.Vector3.prototype.add = function (v) { - return new GameLib.D3.Vector3( - this.x + v.x, - this.y + v.y, - this.z + v.z - ); -}; - -GameLib.D3.Vector3.prototype.squared = function () { - return this.x * this.x + this.y * this.y + this.z * this.z; -}; - -GameLib.D3.Vector3.prototype.copy = function () { - return new GameLib.D3.Vector3( - this.x, - this.y, - this.z - ); -}; - -GameLib.D3.Vector3.prototype.set = function (x, y, z) { - this.x = x; - this.y = y; - this.z = z; -}; - -GameLib.D3.Vector3.prototype.lerp = function ( v, alpha ) { - return new GameLib.D3.Vector3( - this.x + ( v.x - this.x ) * alpha, - this.y + ( v.y - this.y ) * alpha, - this.z + ( v.z - this.z ) * alpha - ); -}; - -GameLib.D3.Vector3.prototype.distanceTo = function(v) { - var dx = this.x - v.x, - dy = this.y - v.y, - dz = this.z - v.z; - return Math.sqrt(dx * dx + dy * dy + dz * dz); -}; - -/** - * @return {number} - */ -GameLib.D3.Vector3.AngleDirection = function(forward, directionToCheck, up) { - var perp = forward.cross(directionToCheck); - var dir = perp.dot(up); - - if (dir > 0.0) { - return 1.0; - } else if (dir < 0.0) { - return -1.0; - } else { - return 0.0; - } - -}; - -GameLib.D3.Vector3.prototype.multiply = function (s) { - if (s instanceof GameLib.D3.Vector3) { - - return new GameLib.D3.Vector3( - this.x * s.x, - this.y * s.y, - this.z * s.z - ) - - } else if (s instanceof GameLib.D3.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; - var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].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; - - return new GameLib.D3.Vector3( - x, - y, - z - ); - - } else if (s instanceof GameLib.D3.Matrix3) { - - var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z; - var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z; - var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z; - - return new GameLib.D3.Vector3( - x, - y, - z - ); - - } else if(!isNaN(parseFloat(s)) && isFinite(s)) { - - return new GameLib.D3.Vector3( - this.x * s, - this.y * s, - this.z * s - ); - - } else { - - console.log("functionality not implemented - please do this"); - throw new Error("not implemented"); - return this; - } -}; - - -GameLib.D3.Vector3.prototype.dot = function (v) { - return (this.x * v.x) + (this.y * v.y) + (this.z * v.z); -}; - -GameLib.D3.Vector3.prototype.normalize = function () { - var EPSILON = 0.000001; - var v2 = this.squared(); - - if (v2 < EPSILON) { - return this; //do nothing for zero vector - } - - var invLength = 1.0 / Math.sqrt(v2); - return new GameLib.D3.Vector3( - this.x * invLength, - this.y * invLength, - this.z * invLength - ); -}; - -GameLib.D3.Vector3.prototype.clone = function () { - return new GameLib.D3.Vector3( - this.x, - this.y, - this.z - ); -}; - -GameLib.D3.Vector3.prototype.applyQuaternion = function(q) { - var x = this.x, y = this.y, z = this.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vector - - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = - qx * x - qy * y - qz * z; - - // calculate result * inverse quat - - return new GameLib.D3.Vector3( - ix * qw + iw * - qx + iy * - qz - iz * - qy, - iy * qw + iw * - qy + iz * - qx - ix * - qz, - iz * qw + iw * - qz + ix * - qy - iy * - qx - ); -}; - -GameLib.D3.Vector3.prototype.clamp = function(min, max) { - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - - return this; -}; - -GameLib.D3.Vector3.prototype.negate = function() { - this.x = -this.x; - this.y = -this.y; - this.z = -this.z; - return this; -}; - -GameLib.D3.Vector3.prototype.length = function() { - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); -}; - -GameLib.D3.Vector3.prototype.reflect = function(normal) { - return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) ); -}; - -GameLib.D3.Vector3.prototype.angleTo = function (v) { - var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); - return Math.acos( exports.Math.clamp( theta, - 1, 1 ) ); }; \ No newline at end of file diff --git a/src/game-lib-vector4.js b/src/game-lib-vector4.js index eda8c5e..b305746 100644 --- a/src/game-lib-vector4.js +++ b/src/game-lib-vector4.js @@ -15,6 +15,8 @@ GameLib.D3.Vector4 = function RuntimeVector4( for (var property in vector4) { if (vector4.hasOwnProperty(property)) { + + this[property] = vector4[property]; } } @@ -82,43 +84,6 @@ GameLib.D3.Vector4.prototype.toApiVector = function() { ); }; -GameLib.D3.Vector4.prototype.translate = function (v) { - this.x += v.x; - this.y += v.y; - this.z += v.z; - return this; -}; - -GameLib.D3.Vector4.prototype.copy = function () { - return new GameLib.D3.Vector4( - this.x, - this.y, - this.z, - this.w - ); -}; - -GameLib.D3.Vector4.prototype.multiply = function (s) { - if (s instanceof GameLib.D3.Vector3) { - this.x *= s.x; - this.y *= s.y; - this.z *= s.z; - } else if (s instanceof GameLib.D3.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; - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } else { - console.log("functionality not implemented - please do this"); - throw new Error("not implemented"); - } -}; - - GameLib.D3.Vector4.prototype.normalize = function () { this.updateInstance(); @@ -129,270 +94,10 @@ GameLib.D3.Vector4.prototype.normalize = function () { 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; }; -GameLib.D3.Vector4.prototype.subtract = function (v) { - - if (v instanceof GameLib.D3.API.Vector3) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - } - - if (v instanceof GameLib.D3.Vector4) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; - } - - return this; -}; - -GameLib.D3.Vector4.Points = function () { - this.vectors = []; -}; - -GameLib.D3.Vector4.Points.prototype.add = function (vector) { - - if (vector instanceof GameLib.D3.API.Vector3) { - vector = new GameLib.D3.Vector4( - vector.x, - vector.y, - vector.z, - 1 - ) - } - - if (!vector instanceof GameLib.D3.Vector4) { - console.warn("Vector needs to be of type Vector4"); - throw new Error("Vector needs to be of type Vector4"); - } - - this.vectors.push(vector); - - return this; -}; - -GameLib.D3.Vector4.Points.prototype.copy = function () { - - var vectors = []; - - for (var i = 0; i < this.vectors.length; i++) { - vectors.push(this.vectors[i].copy()); - } - - return vectors; -}; - -GameLib.D3.Vector4.Points.prototype.maximizeXDistance = function (grain) { - -// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); - - var multiplier = 0; - - var rotationMatrixY = new GameLib.D3.Matrix4().rotationMatrixY(grain); - - var totalRadians = 0; - - var backupVectors = this.copy(); - - var maxXDistance = 0; - - for (var i = 0; i < Math.PI * 2; i += grain) { - - multiplier++; - - for (var j = 0; j < this.vectors.length; j++) { - this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]); - } - - var distances = this.distances(); - - if (distances.x > maxXDistance) { - - maxXDistance = distances.x; - totalRadians = multiplier * grain; - } - } - - this.vectors = backupVectors; - -// console.log("distance: " + maxXDistance + " radians : " + totalRadians); - - var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixY(totalRadians); - - for (var k = 0; k < this.vectors.length; k++) { - this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]); - } - -// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2)); - -}; - -GameLib.D3.Vector4.Points.prototype.maximizeYDistance = function (grain) { - -// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); - - var multiplier = 0; - - var rotationMatrixX = new GameLib.D3.Matrix4().rotationMatrixX(grain); - - var totalRadians = 0; - - var backupVectors = this.copy(); - - var maxYDistance = 0; - - for (var i = 0; i < Math.PI * 2; i += grain) { - - multiplier++; - - for (var j = 0; j < this.vectors.length; j++) { - this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]); - } - - var distances = this.distances(); - - if (distances.y > maxYDistance) { - maxYDistance = distances.y; - totalRadians = multiplier * grain; - } - } - - this.vectors = backupVectors; - -// console.log("distance: " + maxYDistance + " radians : " + totalRadians); - - var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixX(totalRadians); - - for (var k = 0; k < this.vectors.length; k++) { - this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]); - } - -// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2)); - -}; - - -GameLib.D3.Vector4.Points.prototype.lookAt = function (at, up) { - - var polyCenter = this.average(); - - console.log("poly center : " + JSON.stringify(polyCenter)); - - var lookAtMatrix = new GameLib.D3.Matrix4().lookAt(polyCenter, at, up); - - lookAtMatrix.rows[0] = new GameLib.D3.Vector4(1, 0, 0, 0); - lookAtMatrix.rows[1] = new GameLib.D3.Vector4(0, 0, 1, 0); - lookAtMatrix.rows[2] = new GameLib.D3.Vector4(0, 1, 0, 0); - - console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2)); - - for (var i = 0; i < this.vectors.length; i++) { - console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i])); - this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]); - console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i])); - } -}; - -GameLib.D3.Vector4.Points.prototype.distances = function () { - - var minX = this.vectors[0].x; - var minY = this.vectors[0].y; - var minZ = this.vectors[0].z; - - var maxX = this.vectors[0].x; - var maxY = this.vectors[0].y; - var maxZ = this.vectors[0].z; - - for (var i = 0; i < this.vectors.length; i++) { - if (this.vectors[i].x < minX) { - minX = this.vectors[i].x; - } - if (this.vectors[i].y < minY) { - minY = this.vectors[i].y; - } - if (this.vectors[i].z < minZ) { - minZ = this.vectors[i].z; - } - - if (this.vectors[i].x > maxX) { - maxX = this.vectors[i].x; - } - if (this.vectors[i].y > maxY) { - maxY = this.vectors[i].y; - } - if (this.vectors[i].z > maxZ) { - maxZ = this.vectors[i].z; - } - } - - return new GameLib.D3.API.Vector3( - Math.abs(maxX - minX), - Math.abs(maxY - minY), - Math.abs(maxY - minZ) - ) -}; - -GameLib.D3.Vector4.Points.prototype.average = function () { - var averageX = 0; - var averageY = 0; - var averageZ = 0; - - for (var i = 0; i < this.vectors.length; i++) { - averageX += this.vectors[i].x; - averageY += this.vectors[i].y; - averageZ += this.vectors[i].z; - } - - return new GameLib.D3.API.Vector3( - averageX / this.vectors.length, - averageY / this.vectors.length, - averageZ / this.vectors.length - ); -}; - -GameLib.D3.Vector4.Points.prototype.negate = function () { - - for (var i = 0; i < this.vectors.length; i++) { - this.vectors[i].x *= -1; - this.vectors[i].y *= -1; - this.vectors[i].z *= -1; - } - - return this; -}; - - -GameLib.D3.Vector4.Points.prototype.toOrigin = function () { - - var distanceFromOrigin = this.average().negate(); - - for (var i = 0; i < this.vectors.length; i++) { - this.vectors[i].translate(distanceFromOrigin); - } -}; - /** * * @param matrix4 GameLib.D3.Matrix4 @@ -406,3 +111,23 @@ GameLib.D3.Vector4.prototype.setFromRotationMatrix = function(matrix4) { this.z = this.instance.z; this.w = this.instance.w; }; + +/** + * + * @param vector4 GameLib.D3.Vector4 + * @param t + * @returns {GameLib.D3.Vector4} + */ +GameLib.D3.Vector4.prototype.slerp = function (vector4, t) { + + this.updateInstance(); + + this.instance.slerp(vector4.instance, t); + + this.x = this.instance.x; + this.y = this.instance.y; + this.z = this.instance.z; + this.w = this.instance.w; + + return this; +};