diff --git a/game-lib-maths.js b/game-lib-maths.js deleted file mode 100644 index a36988a..0000000 --- a/game-lib-maths.js +++ /dev/null @@ -1,704 +0,0 @@ -function Maths3D() {} - -Maths3D.Vector2 = function(x, y) { - - this.x = 0; - this.y = 0; - - if (x) { - this.x = x; - } - - if (y) { - this.y = y; - } -}; - -Maths3D.Vector3 = function(x, y, z) { - - this.x = 0; - this.y = 0; - this.z = 0; - - if (x) { - this.x = x; - } - - if (y) { - this.y = y; - } - - if (z) { - this.z = z; - } -}; - -Maths3D.Vector4 = function(x, y, z, w) { - - this.x = 0; - this.y = 0; - this.z = 0; - this.w = 0; - - if (x) { - this.x = x; - } - - if (y) { - this.y = y; - } - - if (z) { - this.z = z; - } - - if (w) { - this.w = w; - } -}; - -Maths3D.Matrix3 = function( - row0, - row1, - row2 -) { - this.identity(); - - if (row0) { - this.rows[0] = row0; - } - - if (row1) { - this.rows[1] = row1; - } - - if (row2) { - this.rows[2] = row2; - } -}; - -Maths3D.Matrix4 = function( - row0, - row1, - row2, - row3 -) { - - this.identity(); - - if (row0) { - this.rows[0] = row0; - } - - if (row1) { - this.rows[1] = row1; - } - - if (row2) { - this.rows[2] = row2; - } - - if (row3) { - this.rows[3] = row3; - } -}; - -Maths3D.Color = function(r, g, b, a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; -}; - -Maths3D.Vector2.prototype.copy = function() { - return new Maths3D.Vector2( - this.x, - this.y - ); -}; - -Maths3D.Vector2.prototype.equals = function(v) { - return !!(((this.x == v.x) && - (this.y == v.y)) || - ((this.y == v.x) && - (this.x == v.y))); -}; - - -Maths3D.Matrix4.prototype.rotationMatrixX = function (radians) { - this.identity(); - this.rows[1] = new Maths3D.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0); - this.rows[2] = new Maths3D.Vector4(0, Math.sin(radians), Math.cos(radians), 0); - return this; -}; - -Maths3D.Matrix4.prototype.rotationMatrixY = function (radians) { - this.identity(); - this.rows[0] = new Maths3D.Vector4( - Math.cos(radians), - 0, - Math.sin(radians), - 0 - ); - this.rows[2] = new Maths3D.Vector4( - -1 * Math.sin(radians), - 0, - Math.cos(radians), - 0 - ); - return this; -}; - -Maths3D.Matrix4.prototype.rotationMatrixZ = function (radians) { - this.identity(); - this.rows[0] = new Maths3D.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0); - this.rows[1] = new Maths3D.Vector4(Math.sin(radians), Math.cos(radians), 0, 0); - return this; -}; - -Maths3D.Matrix4.prototype.rotateX = function (radians, point) { - this.identity(); - this.rotationMatrixX(radians); - return this.multiply(point); -}; - -Maths3D.Matrix4.prototype.rotateY = function (radians, point) { - this.identity(); - this.rotationMatrixY(radians); - return this.multiply(point); -}; - -Maths3D.Matrix4.prototype.rotateZ = function (radians, point) { - this.identity(); - this.rotationMatrixZ(radians); - return this.multiply(point); -}; - -Maths3D.Matrix4.prototype.multiply = function (mvp) { - if (mvp instanceof Maths3D.Vector4) { - return new Maths3D.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 Maths3D.Vector3) { - return new Maths3D.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 - ); - } -}; - -Maths3D.Vector4.Points = function () { - this.vectors = []; -}; - -Maths3D.Vector4.Points.prototype.add = function (vector) { - - if (vector instanceof Maths3D.Vector3) { - vector = new Maths3D.Vector4( - vector.x, - vector.y, - vector.z, - 1 - ) - } - - if (!vector instanceof Maths3D.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; -}; - -Maths3D.Vector4.Points.prototype.copy = function () { - - var vectors = []; - - for (var i = 0; i < this.vectors.length; i++) { - vectors.push(this.vectors[i].copy()); - } - - return vectors; -}; - -Maths3D.Vector4.Points.prototype.maximizeXDistance = function (grain) { - -// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); - - var multiplier = 0; - - var rotationMatrixY = new Maths3D.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 Maths3D.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)); - -}; - -Maths3D.Vector4.Points.prototype.maximizeYDistance = function (grain) { - -// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2)); - - var multiplier = 0; - - var rotationMatrixX = new Maths3D.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 Maths3D.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)); - -}; - - -Maths3D.Vector4.Points.prototype.lookAt = function (at, up) { - - var polyCenter = this.average(); - - console.log("poly center : " + JSON.stringify(polyCenter)); - - var lookAtMatrix = new Maths3D.Matrix4().lookAt(polyCenter, at, up); - - lookAtMatrix.rows[0] = new Maths3D.Vector4(1, 0, 0, 0); - lookAtMatrix.rows[1] = new Maths3D.Vector4(0, 0, 1, 0); - lookAtMatrix.rows[2] = new Maths3D.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])); - } -}; - -Maths3D.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 Maths3D.Vector3( - Math.abs(maxX - minX), - Math.abs(maxY - minY), - Math.abs(maxY - minZ) - ) -}; - -Maths3D.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 Maths3D.Vector3( - averageX / this.vectors.length, - averageY / this.vectors.length, - averageZ / this.vectors.length - ); -}; - -Maths3D.Vector4.Points.prototype.negative = 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; -}; - - -Maths3D.Vector4.Points.prototype.toOrigin = function () { - - var distanceFromOrigin = this.average().negative(); - - for (var i = 0; i < this.vectors.length; i++) { - this.vectors[i].translate(distanceFromOrigin); - } -}; - -Maths3D.Vector3.clockwise = function (u, v, w, viewPoint) { - - var normal = Maths3D.Vector3.normal(u, v, w); - - var uv = u.copy(); - - var winding = normal.dot(uv.subtract(viewPoint)); - - return (winding > 0); -}; - -Maths3D.Vector3.normal = function (u, v, w) { - var vv = v.copy(); - var wv = w.copy(); - return vv.subtract(u).cross(wv.subtract(u)); -}; - -Maths3D.Vector3.prototype.lookAt = function (at, up) { - - var lookAtMatrix = Maths3D.Matrix4.lookAt(this, at, up); - - this.multiply(lookAtMatrix); -}; - -Maths3D.Vector3.prototype.translate = function (v) { - this.x += v.x; - this.y += v.y; - this.z += v.z; - return this; -}; - -Maths3D.Vector4.prototype.translate = function (v) { - this.x += v.x; - this.y += v.y; - this.z += v.z; - return this; -}; - -Maths3D.Vector3.prototype.squared = function () { - return this.x * this.x + this.y * this.y + this.z * this.z; -}; - -Maths3D.Vector3.prototype.copy = function () { - return new Maths3D.Vector3( - this.x, - this.y, - this.z - ); -}; - -Maths3D.Vector4.prototype.copy = function () { - return new Maths3D.Vector4( - this.x, - this.y, - this.z, - this.w - ); -}; - -Maths3D.Vector3.prototype.multiply = function (s) { - if (s instanceof Maths3D.Vector3) { - this.x *= s.x; - this.y *= s.y; - this.z *= s.z; - } else if (s instanceof Maths3D.Matrix4) { - 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; - this.x = x; - this.y = y; - this.z = z; - } else { - console.log("functionality not implemented - please do this"); - throw new Error("not implemented"); - } - return this; -}; - -Maths3D.Vector4.prototype.multiply = function (s) { - if (s instanceof Maths3D.Vector3) { - this.x *= s.x; - this.y *= s.y; - this.z *= s.z; - } else if (s instanceof Maths3D.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"); - } -}; - -Maths3D.Vector3.prototype.dot = function (v) { - return (this.x * v.x) + (this.y * v.y) + (this.z * v.z); -}; - -Maths3D.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 / Math.sqrt(v2); - - this.x *= invLength; - this.y *= invLength; - this.z *= invLength; - - return this; -}; - -Maths3D.Vector4.prototype.normalize = function () { - - // 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; -}; - -Maths3D.Matrix3.prototype.identity = function () { - this.rows = [ - new Maths3D.Vector4(1, 0, 0), - new Maths3D.Vector4(0, 1, 0), - new Maths3D.Vector4(0, 0, 1) - ]; -}; - -Maths3D.Matrix4.prototype.identity = function () { - this.rows = [ - new Maths3D.Vector4(1, 0, 0, 0), - new Maths3D.Vector4(0, 1, 0, 0), - new Maths3D.Vector4(0, 0, 1, 0), - new Maths3D.Vector4(0, 0, 0, 1) - ]; -}; - -Maths3D.Matrix4.prototype.lookAt = function (position, target, up) { - - var pv = new Maths3D.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; - - // te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; - // te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; - // te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; - - - // var matrix4 = new Matrix4(); - // - // matrix4.rows[0] = side.negative(); - // matrix4.rows[1] = _up; - // matrix4.rows[2] = forward; - - // - // matrix4.setColumn(0, side.negative()); - // matrix4.setColumn(1, _up); - // matrix4.setColumn(2, forward); - - //return matrix4; - - // return new Matrix4( - // new Vector4( - // side.x, - // side.y, - // side.z, - // side.negative().dot(position) - // ), - // new Vector4( - // _up.x, - // _up.y, - // _up.z, - // _up.negative().dot(position) - // ), - // new Vector4( - // forward.negative().x, - // forward.negative().y, - // forward.negative().z, - // forward.dot(position) - // ) - // ) -}; - -Maths3D.Vector3.prototype.negative = function () { - this.x *= -1; - this.y *= -1; - this.z *= -1; - return this; -}; - -Maths3D.Vector3.prototype.magnitude = function () { - return this.x + this.y + this.z; -}; - -Maths3D.Vector4.prototype.subtract = function (v) { - - if (v instanceof Maths3D.Vector3) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - } - - if (v instanceof Maths3D.Vector4) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; - } - - return this; -}; - -Maths3D.Vector3.prototype.subtract = function (v) { - - if (v instanceof Maths3D.Vector3) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - } - - if (v instanceof Maths3D.Vector4) { - console.warn("trying to subtract vector of bigger length (4 vs 3))"); - } - - return this; -}; - -Maths3D.Vector3.prototype.cross = function (v) { - return new Maths3D.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 - ); -}; - -if (typeof module !== 'undefined') { - module.exports = Maths3D; -} \ No newline at end of file diff --git a/game-lib.js b/game-lib.js deleted file mode 100644 index a32540e..0000000 --- a/game-lib.js +++ /dev/null @@ -1,3712 +0,0 @@ -if (typeof require != 'undefined') { - var Maths3D = require('./game-lib-maths.js'); -} - -if (typeof require != 'undefined') { - var Controls = require('./game-lib-controls.js'); -} - -function GameLib() {} - -/** - * GameLib.D3 connects our GameLib.D3 assets to a graphics library like THREE.js, but could technically be any graphics - * lib - * @param config - * @param Q Q - * @param THREE THREE.js - * @param apiUrl - * @param editorUrl - * @constructor - */ -GameLib.D3 = function( - config, - Q, - THREE, - apiUrl, - editorUrl, - CANNON, - path -){ - this.config = config; - this.Q = Q; - this.THREE = THREE; - this.CANNON = CANNON; - this.textureLoader = new this.THREE.TextureLoader(); - this.apiUrl = apiUrl || this.config.api16.url; - this.editorUrl = editorUrl || this.config.editor.url; - this.path = path; -}; - -if (typeof require == 'undefined' && - typeof Maths3D == 'undefined') { - console.warn("You need a proper Maths3D library in order to use this library"); -} - -if (typeof require == 'undefined' && - typeof Controls == 'undefined') { - console.warn("You need a proper Control library in order to use this library"); -} - -GameLib.D3.Controls = Controls; - -GameLib.D3.Vector2 = Maths3D.Vector2; -GameLib.D3.Vector3 = Maths3D.Vector3; -GameLib.D3.Vector4 = Maths3D.Vector4; -GameLib.D3.Matrix4 = Maths3D.Matrix4; -GameLib.D3.Color = Maths3D.Color; - -/** - * Texture Superset - * @param id - * @param path - * @param name - * @param image - * @param wrapS - * @param wrapT - * @param repeat - * @param data - * @param format - * @param mapping - * @param magFilter - * @param minFilter - * @param textureType - * @param anisotropy - * @param offset - * @param generateMipmaps - * @param flipY - * @param mipmaps - * @param unpackAlignment - * @param premultiplyAlpha - * @param encoding - * @constructor - */ -GameLib.D3.Texture = function( - id, - name, - image, - wrapS, - wrapT, - repeat, - data, - format, - mapping, - magFilter, - minFilter, - textureType, - anisotropy, - offset, - generateMipmaps, - flipY, - mipmaps, - unpackAlignment, - premultiplyAlpha, - encoding -) { - this.id = id; - this.name = name; - this.image = image; - - if (typeof wrapS == 'undefined') { - wrapS = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING; - } - this.wrapS = wrapS; - - if (typeof wrapT == 'undefined') { - wrapT = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING; - } - this.wrapT = wrapT; - - if (typeof repeat == 'undefined') { - repeat = new GameLib.D3.Vector2(1, 1); - } - this.repeat = repeat; - - if (typeof data == 'undefined') { - data = null; - } - this.data = data; - - if (typeof format == 'undefined') { - format = GameLib.D3.Texture.TYPE_RGBA_FORMAT; - } - this.format = format; - - if (typeof mapping == 'undefined') { - mapping = GameLib.D3.Texture.TYPE_UV_MAPPING; - } - this.mapping = mapping; - - if (typeof magFilter == 'undefined') { - magFilter = GameLib.D3.Texture.TYPE_LINEAR_FILTER; - } - this.magFilter = magFilter; - - if (typeof minFilter == 'undefined') { - minFilter = GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER; - } - this.minFilter = minFilter; - - if (typeof textureType == 'undefined') { - textureType = GameLib.D3.Texture.TYPE_UNSIGNED_BYTE; - } - this.textureType = textureType; - - if (typeof anisotropy == 'undefined') { - anisotropy = 1; - } - this.anisotropy = anisotropy; - - if (typeof offset == 'undefined') { - offset = new GameLib.D3.Vector2(0, 0); - } - this.offset = offset; - - if (typeof generateMipmaps == 'undefined') { - generateMipmaps = true; - } - this.generateMipmaps = generateMipmaps; - - if (typeof flipY == 'undefined') { - flipY = true; - } - this.flipY = flipY; - - if (typeof mipmaps == 'undefined') { - mipmaps = []; - } - this.mipmaps = mipmaps; - - if (typeof unpackAlignment == 'undefined') { - unpackAlignment = 4; - } - this.unpackAlignment = unpackAlignment; - - if (typeof premultiplyAlpha == 'undefined') { - premultiplyAlpha = false; - } - this.premultiplyAlpha = premultiplyAlpha; - - if (typeof encoding == 'undefined') { - encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING; - } - this.encoding = encoding; -}; - -/** - * Texture Formats - * @type {number} - */ -GameLib.D3.Texture.TYPE_ALPHA_FORMAT = 1019; -GameLib.D3.Texture.TYPE_RGB_FORMAT = 1020; -GameLib.D3.Texture.TYPE_RGBA_FORMAT = 1021; -GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT = 1022; -GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT = 1023; -GameLib.D3.Texture.TYPE_DEPTH_FORMAT = 1026; - -/** - * Mapping modes - * @type {number} - */ -GameLib.D3.Texture.TYPE_UV_MAPPING = 300; -GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING = 301; -GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING = 302; -GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING = 303; -GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING = 304; -GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING = 305; -GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING = 306; -GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING = 307; - -/** - * Wrapping Modes - * @type {number} - */ -GameLib.D3.Texture.TYPE_REPEAT_WRAPPING = 1000; -GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING = 1001; -GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING = 1002; - -/** - * Mipmap Filters - * @type {number} - */ -GameLib.D3.Texture.TYPE_NEAREST_FILTER = 1003; -GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER = 1004; -GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER = 1005; -GameLib.D3.Texture.TYPE_LINEAR_FILTER = 1006; -GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER = 1007; -GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER = 1008; - -/** - * Texture Data Types - * @type {number} - */ -GameLib.D3.Texture.TYPE_UNSIGNED_BYTE = 1009; -GameLib.D3.Texture.TYPE_BYTE = 1010; -GameLib.D3.Texture.TYPE_SHORT = 1011; -GameLib.D3.Texture.TYPE_UNSIGNED_SHORT = 1012; -GameLib.D3.Texture.TYPE_INT = 1013; -GameLib.D3.Texture.TYPE_UNSIGNED_INT = 1014; -GameLib.D3.Texture.TYPE_FLOAT = 1015; -GameLib.D3.Texture.TYPE_HALF_FLOAT = 1025; - -/** - * Encoding Modes - * @type {number} - */ -GameLib.D3.Texture.TYPE_LINEAR_ENCODING = 3000; // NO ENCODING AT ALL. -GameLib.D3.Texture.TYPE_SRGB_ENCODING = 3001; -GameLib.D3.Texture.TYPE_GAMMA_ENCODING = 3007; // USES GAMMA_FACTOR, FOR BACKWARDS COMPATIBILITY WITH WEBGLRENDERER.GAMMAINPUT/GAMMAOUTPUT -GameLib.D3.Texture.TYPE_RGBE_ENCODING = 3002; // AKA RADIANCE. -GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING = 3003; -GameLib.D3.Texture.TYPE_RGBM7_ENCODING = 3004; -GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005; -GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256. - -/** - * Light Superset - * @param id - * @param lightType - * @param name - * @param color - * @param intensity - * @param position - * @param targetPosition - * @param quaternion - * @param rotation - * @param scale - * @param distance - * @param decay - * @param power - * @param angle - * @param penumbra - * @constructor - */ -GameLib.D3.Light = function( - id, - lightType, - name, - color, - intensity, - position, - targetPosition, - quaternion, - rotation, - scale, - distance, - decay, - power, - angle, - penumbra -) { - this.id = id; - this.lightType = lightType; - this.name = name; - this.color = color; - this.intensity = intensity; - - if (typeof position == 'undefined') { - position = new GameLib.D3.Vector3(0,0,0); - } - this.position = position; - - if (typeof targetPosition == 'undefined') { - targetPosition = new GameLib.D3.Vector3(0,0,0); - } - this.targetPosition = targetPosition; - - if (typeof quaternion == 'undefined'){ - quaternion = new GameLib.D3.Vector4(); - } - this.quaternion = quaternion; - - if (typeof rotation == 'undefined'){ - rotation = new GameLib.D3.Vector3(0,0,0); - } - this.rotation = rotation; - - if (typeof scale == 'undefined'){ - scale = new GameLib.D3.Vector3(1,1,1); - } - this.scale = scale; - - if (typeof distance == 'undefined'){ - distance = 0; - } - this.distance = distance; - - if (typeof decay == 'undefined'){ - decay = 1; - } - this.decay = decay; - - if (typeof power == 'undefined'){ - power = 4 * Math.PI; - } - this.power = power; - - if (typeof angle == 'undefined'){ - angle = Math.PI / 3; - } - this.angle = angle; - - if (typeof penumbra == 'undefined'){ - penumbra = 0; - } - this.penumbra = penumbra; -}; - -/** - * Material Superset - * @param id - * @param path - * @param name - * @param materialType - * @param opacity - * @param side - * @param transparent - * @param maps - * @param specular - * @param lightMapIntensity - * @param aoMapIntensity - * @param color - * @param emissive - * @param emissiveIntensity - * @param combine - * @param shininess - * @param reflectivity - * @param refractionRatio - * @param fog - * @param wireframe - * @param wireframeLineWidth - * @param wireframeLineCap - * @param wireframeLineJoin - * @param vertexColors - * @param skinning - * @param morphTargets - * @param morphNormals - * @param lineWidth - * @param lineCap - * @param lineJoin - * @param dashSize - * @param gapWidth - * @param blending - * @param blendSrc - * @param blendDst - * @param blendEquation - * @param depthTest - * @param depthFunc - * @param depthWrite - * @param polygonOffset - * @param polygonOffsetFactor - * @param polygonOffsetUnits - * @param alphaTest - * @param clippingPlanes - * @param clipShadows - * @param visible - * @param overdraw - * @param shading - * @param bumpScale - * @param normalScale - * @param displacementScale - * @param displacementBias - * @param roughness - * @param metalness - * @param pointSize - * @param pointSizeAttenuation - * @param spriteRotation - * @param envMapIntensity - * @constructor - */ -GameLib.D3.Material = function( - id, - name, - materialType, - opacity, - side, - transparent, - maps, - specular, - lightMapIntensity, - aoMapIntensity, - color, - emissive, - emissiveIntensity, - combine, - shininess, - reflectivity, - refractionRatio, - fog, - wireframe, - wireframeLineWidth, - wireframeLineCap, - wireframeLineJoin, - vertexColors, - skinning, - morphTargets, - morphNormals, - lineWidth, - lineCap, - lineJoin, - dashSize, - gapWidth, - blending, - blendSrc, - blendDst, - blendEquation, - depthTest, - depthFunc, - depthWrite, - polygonOffset, - polygonOffsetFactor, - polygonOffsetUnits, - alphaTest, - clippingPlanes, - clipShadows, - visible, - overdraw, - shading, - bumpScale, - normalScale, - displacementScale, - displacementBias, - roughness, - metalness, - pointSize, - pointSizeAttenuation, - spriteRotation, - envMapIntensity -) { - this.id = id; - this.name = name; - if (typeof materialType == 'undefined') { - materialType = GameLib.D3.Material.TYPE_MESH_STANDARD; - } - this.materialType = materialType; - - if (typeof opacity == 'undefined') { - opacity = 1.0; - } - this.opacity = opacity; - - if (typeof side == 'undefined') { - side = GameLib.D3.Material.TYPE_FRONT_SIDE; - } - this.side = side; - - if (typeof transparent == 'undefined') { - transparent = false; - } - this.transparent = transparent; - - if (typeof maps == 'undefined') { - maps = { - alpha: null, - ao: null, - bump: null, - diffuse: null, - displacement: null, - emissive: null, - environment: null, - light: null, - metalness: null, - normal: null, - roughness: null, - specular: null - }; - } - this.maps = maps; - - if (typeof specular == 'undefined') { - specular = new GameLib.D3.Color(0.06, 0.06, 0.06, 0.06); - } - this.specular = specular; - - if (typeof lightMapIntensity == 'undefined') { - lightMapIntensity = 1; - } - this.lightMapIntensity = lightMapIntensity; - - if (typeof aoMapIntensity == 'undefined') { - aoMapIntensity = 1; - } - this.aoMapIntensity = aoMapIntensity; - - if (typeof color == 'undefined') { - color = new GameLib.D3.Color(1, 1, 1, 1) - } - this.color = color; - - if (typeof emissive == 'undefined') { - emissive = new GameLib.D3.Color(0, 0, 0, 0); - } - this.emissive = emissive; - - if (typeof emissiveIntensity == 'undefined') { - emissiveIntensity = 1; - } - this.emissiveIntensity = emissiveIntensity; - - if (typeof combine == 'undefined') { - combine = GameLib.D3.Material.TYPE_MULTIPLY_OPERATION; - } - this.combine = combine; - - if (typeof shininess == 'undefined') { - shininess = 30; - } - this.shininess = shininess; - - if (typeof reflectivity == 'undefined') { - reflectivity = 1; - } - this.reflectivity = reflectivity; - - if (typeof refractionRatio == 'undefined') { - refractionRatio = 0.98; - } - this.refractionRatio = refractionRatio; - - if (typeof fog == 'undefined') { - fog = true; - } - this.fog = fog; - - if (typeof wireframe == 'undefined') { - wireframe = false; - } - this.wireframe = wireframe; - - if (typeof wireframeLineWidth == 'undefined') { - wireframeLineWidth = 1; - } - this.wireframeLineWidth = wireframeLineWidth; - - if (typeof wireframeLineCap == 'undefined') { - wireframeLineCap = 'round'; - } - this.wireframeLineCap = wireframeLineCap; - - if (typeof wireframeLineJoin == 'undefined') { - wireframeLineJoin = 'round'; - } - this.wireframeLineJoin = wireframeLineJoin; - - if (typeof vertexColors == 'undefined') { - vertexColors = GameLib.D3.Material.TYPE_NO_COLORS; - } - this.vertexColors = vertexColors; - - if (typeof skinning == 'undefined') { - skinning = false; - } - this.skinning = skinning; - - if (typeof morphTargets == 'undefined') { - morphTargets = false; - } - this.morphTargets = morphTargets; - - if (typeof morphNormals == 'undefined') { - morphNormals = false; - } - this.morphNormals = morphNormals; - - if (typeof overdraw == 'undefined') { - overdraw = 0; - } - this.overdraw = overdraw; - - if (typeof lineWidth == 'undefined') { - lineWidth = 1; - } - this.lineWidth = lineWidth; - - if (typeof lineCap == 'undefined') { - lineCap = 'round'; - } - this.lineCap = lineCap; - - if (typeof lineJoin == 'undefined') { - lineJoin = 'round'; - } - this.lineJoin = lineJoin; - - if (typeof dashSize == 'undefined') { - dashSize = 3; - } - this.dashSize = dashSize; - - if (typeof gapWidth == 'undefined') { - gapWidth = 1; - } - this.gapWidth = gapWidth; - - if (typeof blending == 'undefined') { - blending = GameLib.D3.Material.TYPE_NORMAL_BLENDING; - } - this.blending = blending; - - if (typeof blendSrc == 'undefined') { - blendSrc = GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR; - } - this.blendSrc = blendSrc; - - if (typeof blendDst == 'undefined') { - blendDst = GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR; - } - this.blendDst = blendDst; - - if (typeof blendEquation == 'undefined') { - blendEquation = GameLib.D3.Material.TYPE_ADD_EQUATION; - } - this.blendEquation = blendEquation; - - if (typeof depthTest == 'undefined') { - depthTest = true; - } - this.depthTest = depthTest; - - if (typeof depthFunc == 'undefined') { - depthFunc = GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH; - } - this.depthFunc = depthFunc; - - if (typeof depthWrite == 'undefined') { - depthWrite = true; - } - this.depthWrite = depthWrite; - - if (typeof polygonOffset == 'undefined') { - polygonOffset = false; - } - this.polygonOffset = polygonOffset; - - if (typeof polygonOffsetFactor == 'undefined') { - polygonOffsetFactor = 1; - } - this.polygonOffsetFactor = polygonOffsetFactor; - - if (typeof polygonOffsetUnits == 'undefined') { - polygonOffsetUnits = 1; - } - this.polygonOffsetUnits = polygonOffsetUnits; - - if (typeof alphaTest == 'undefined') { - alphaTest = 0; - } - this.alphaTest = alphaTest; - - if (typeof clippingPlanes == 'undefined') { - clippingPlanes = []; - } - this.clippingPlanes = clippingPlanes; - - if (typeof clipShadows == 'undefined') { - clipShadows = false; - } - this.clipShadows = clipShadows; - - if (typeof visible == 'undefined') { - visible = true; - } - this.visible = visible; - - if (typeof shading == 'undefined') { - shading = GameLib.D3.Material.TYPE_FLAT_SHADING; - } - this.shading = shading; - - if (typeof bumpScale == 'undefined') { - bumpScale = 1; - } - this.bumpScale = bumpScale; - - if (typeof normalScale == 'undefined') { - normalScale = 1; - } - this.normalScale = normalScale; - - if (typeof displacementScale == 'undefined') { - displacementScale = 1; - } - this.displacementScale = displacementScale; - - if (typeof displacementBias == 'undefined') { - displacementBias = 0; - } - this.displacementBias = displacementBias; - - if (typeof roughness == 'undefined') { - roughness = 0.5; - } - this.roughness = roughness; - - if (typeof metalness == 'undefined') { - metalness = 0.5; - } - this.metalness = metalness; - - if (typeof pointSize == 'undefined') { - pointSize = 1; - } - this.pointSize = pointSize; - - if (typeof pointSizeAttenuation == 'undefined') { - pointSizeAttenuation = true; - } - this.pointSizeAttenuation = pointSizeAttenuation; - - if (typeof spriteRotation == 'undefined') { - spriteRotation = 0; - } - this.spriteRotation = spriteRotation; - - if (typeof envMapIntensity == 'undefined') { - envMapIntensity = 1.0; - } - this.envMapIntensity = envMapIntensity; - -}; - -/** - * Combine Method - * @type {number} - */ -GameLib.D3.Material.TYPE_MULTIPLY_OPERATION = 0; -GameLib.D3.Material.TYPE_MIX_OPERATION = 1; -GameLib.D3.Material.TYPE_ADD_OPERATION = 2; - -/** - * Vertex Color Mode - * @type {number} - */ -GameLib.D3.Material.TYPE_NO_COLORS = 0; -GameLib.D3.Material.TYPE_FACE_COLORS = 1; -GameLib.D3.Material.TYPE_VERTEX_COLORS = 2; - -/** - * Blending Mode - * @type {number} - */ -GameLib.D3.Material.TYPE_NORMAL_BLENDING = 1; -GameLib.D3.Material.TYPE_ADDITIVE_BLENDING = 2; -GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING = 3; -GameLib.D3.Material.TYPE_MULTIPLY_BLENDING = 4; -GameLib.D3.Material.TYPE_CUSTOM_BLENDING = 5; - -/** - * Blend Source and Destination - * @type {number} - */ -GameLib.D3.Material.TYPE_ZERO_FACTOR = 200; -GameLib.D3.Material.TYPE_ONE_FACTOR = 201; -GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR = 202; -GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR = 203; -GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR = 204; -GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR = 205; -GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR = 206; -GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR = 207; -GameLib.D3.Material.TYPE_DST_COLOR_FACTOR = 208; -GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR = 209; -GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR = 210; - -/** - * Blend Operation - * @type {number} - */ -GameLib.D3.Material.TYPE_ADD_EQUATION = 100; -GameLib.D3.Material.TYPE_SUBTRACT_EQUATION = 101; -GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION = 102; -GameLib.D3.Material.TYPE_MIN_EQUATION = 103; -GameLib.D3.Material.TYPE_MAX_EQUATION = 104; - -/** - * Depth Function - * @type {number} - */ -GameLib.D3.Material.TYPE_NEVER_DEPTH = 0; -GameLib.D3.Material.TYPE_ALWAYS_DEPTH = 1; -GameLib.D3.Material.TYPE_LESS_DEPTH = 2; -GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH = 3; -GameLib.D3.Material.TYPE_EQUAL_DEPTH = 4; -GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH = 5; -GameLib.D3.Material.TYPE_GREATER_DEPTH = 6; -GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH = 7; - -/** - * Culling Mode - * @type {number} - */ -GameLib.D3.Material.TYPE_FRONT_SIDE = 0; -GameLib.D3.Material.TYPE_BACK_SIDE = 1; -GameLib.D3.Material.TYPE_DOUBLE_SIDE = 2; - -/** - * Shading Type - * @type {number} - */ -GameLib.D3.Material.TYPE_FLAT_SHADING = 1; -GameLib.D3.Material.TYPE_SMOOTH_SHADING = 2; - -/** - * Material Type - * @type {string} - */ -GameLib.D3.Material.TYPE_LINE_BASIC = "LineBasicMaterial"; -GameLib.D3.Material.TYPE_LINE_DASHED = "LineDashedMaterial"; -GameLib.D3.Material.TYPE_MESH_BASIC = "MeshBasicMaterial"; -GameLib.D3.Material.TYPE_MESH_DEPTH = "MeshDepthMaterial"; -GameLib.D3.Material.TYPE_MESH_LAMBERT = "MeshLambertMaterial"; -GameLib.D3.Material.TYPE_MESH_NORMAL = "MeshNormalMaterial"; -GameLib.D3.Material.TYPE_MESH_PHONG = "MeshPhongMaterial"; -GameLib.D3.Material.TYPE_MESH_STANDARD = "MeshStandardMaterial"; -GameLib.D3.Material.TYPE_POINTS = "PointsMaterial"; -GameLib.D3.Material.TYPE_SPRITE = "SpriteMaterial"; -GameLib.D3.Material.TYPE_MULTI_MATERIAL= "MultiMaterial"; - -/** - * Skeleton Superset - * @param id - * @param bones GameLib.D3.Bone - * @param boneInverses - * @param useVertexTexture - * @param boneTextureWidth - * @param boneTextureHeight - * @param boneMatrices - * @param boneTexture - * @constructor - */ -GameLib.D3.Skeleton = function( - id, - bones, - boneInverses, - useVertexTexture, - boneTextureWidth, - boneTextureHeight, - boneMatrices, - boneTexture -) { - this.id = id; - - this.bones = bones; - - /** - * An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones. - * @type GameLib.D3.Matrix4[] - */ - if (typeof boneInverses == 'undefined') { - boneInverses = []; - } - this.boneInverses = boneInverses; - - /** - * Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices - * @type {boolean} - */ - if (typeof useVertexTexture == 'undefined') { - useVertexTexture = false; - } - this.useVertexTexture = useVertexTexture; - - if (this.useVertexTexture == true) { - console.warn('support for vertex texture bones is not supported yet - something could break somewhere'); - } - - if (typeof boneTextureWidth == 'undefined') { - boneTextureWidth = 0; - } - this.boneTextureWidth = boneTextureWidth; - - if (typeof boneTextureHeight == 'undefined') { - boneTextureHeight = 0; - } - this.boneTextureHeight = boneTextureHeight; - - if (typeof boneMatrices == 'undefined') { - boneMatrices = []; - } - this.boneMatrices = boneMatrices; - - if (typeof boneTexture == 'undefined') { - boneTexture = []; - } - this.boneTexture = boneTexture; -}; - -/** - * Mesh Superset - * @param id - * @param path - * @param name - * @param meshType - * @param vertices - * @param faces - * @param skeleton - * @param faceVertexUvs - * @param skinIndices - * @param skinWeights - * @param materials - * @param position - * @param quaternion - * @param rotation - * @param scale - * @param up - * @param physics - * @param parentMeshId - * @param parentSceneId - * @param rawData - * @constructor - */ -GameLib.D3.Mesh = function( - id, - path, - name, - meshType, - vertices, - faces, - skeleton, - faceVertexUvs, - skinIndices, - skinWeights, - materials, - position, - quaternion, - rotation, - scale, - up, - physics, - parentMeshId, - parentSceneId, - rawData -) { - this.id = id; - this.path = path; - this.name = name; - this.meshType = meshType; - this.vertices = vertices; - this.faces = faces; - - if (typeof skeleton == 'undefined') { - skeleton = null; - } - this.skeleton = skeleton; - - if (typeof faceVertexUvs == 'undefined') { - faceVertexUvs = []; - } - this.faceVertexUvs = faceVertexUvs; - - if (typeof skinIndices == 'undefined') { - skinIndices = []; - } - this.skinIndices = skinIndices; - - if (typeof skinWeights == 'undefined') { - skinWeights = []; - } - this.skinWeights = skinWeights; - - if (typeof materials == 'undefined') { - materials = []; - } - this.materials = materials; - - if (typeof position == 'undefined') { - position = new GameLib.D3.Vector3(0,0,0); - } - this.position = position; - - if (typeof quaternion == 'undefined') { - new GameLib.D3.Vector4(); - } - this.quaternion = quaternion; - - if (typeof rotation == 'undefined') { - rotation = new GameLib.D3.Vector3(0,0,0); - } - this.rotation = rotation; - - if (typeof scale == 'undefined') { - scale = new GameLib.D3.Vector3(1,1,1); - } - this.scale = scale; - - if (typeof up == 'undefined') { - up = new GameLib.D3.Vector3(0,1,0); - } - this.up = up; - - this.physics = physics; - - this.parentMeshId = parentMeshId; - - this.parentSceneId = parentSceneId; - - this.rawData = null;// rawData; -}; - -/** - * Mesh Type - * @type {number} - */ -GameLib.D3.Mesh.TYPE_NORMAL = 0; -GameLib.D3.Mesh.TYPE_SKINNED = 1; - -/** - * Bone Superset - * @param id - * @param name string - * @param boneId - * @param childBoneIds - * @param parentBoneId - * @param quaternion - * @param position - * @param rotation - * @param scale GameLib.D3.Vector3 - * @param up - * @param rawData - * @constructor - */ -GameLib.D3.Bone = function( - id, - boneId, - name, - childBoneIds, - parentBoneId, - quaternion, - position, - rotation, - scale, - up, - rawData -) { - this.id = id; - this.name = name; - this.boneId = boneId; - - if (typeof childBoneIds == 'undefined') { - childBoneIds = []; - } - this.childBoneIds = childBoneIds; - - if (typeof parentBoneId == 'undefined') { - parentBoneId = null; - } - this.parentBoneId = parentBoneId; - - if (typeof quaternion == 'undefined') { - quaternion = new GameLib.D3.Vector4(); - } - this.quaternion = quaternion; - - if (typeof position == 'undefined') { - position = new GameLib.D3.Vector3(0,0,0); - } - this.position = position; - - if (typeof rotation == 'undefined') { - rotation = new GameLib.D3.Vector3(0,0,0); - } - this.rotation = rotation; - - if (typeof scale == 'undefined') { - scale = new GameLib.D3.Vector3(1,1,1); - } - this.scale = scale; - - if (typeof up == 'undefined') { - up = new GameLib.D3.Vector3(0,1,0); - } - this.up = up; - - this.rawData = null;//rawData; -}; - -/** - * Physics Superset - * @param id - * @param name - * @param engineType - * @param CANNON - * @param Ammo - * @param Goblin - * @param worlds GameLib.D3.Physics.World[] - * @constructor - */ -GameLib.D3.Physics = function( - id, - name, - engineType, - CANNON, - Ammo, - Goblin, - worlds, - customWorlds -) { - - this.id = id; - this.name = name; - this.engineType = engineType; - - this.CANNON = CANNON; - - this.Ammo = Ammo; - - this.Goblin = Goblin; - - this.worlds = []; - - this.customWorlds = []; -}; - -/** - * Physics Engine Types - * @type {number} - */ -GameLib.D3.Physics.TYPE_CANNON = 0x1; -GameLib.D3.Physics.TYPE_AMMO = 0x2; -GameLib.D3.Physics.TYPE_GOBLIN = 0x3; - -/** - * Broadphase Types - * @type {number} - */ -GameLib.D3.Physics.BROADPHASE_TYPE_NAIVE = 0x1; -GameLib.D3.Physics.BROADPHASE_TYPE_GRID = 0x2; -GameLib.D3.Physics.BROADPHASE_TYPE_SAP = 0x3; - -/** - * Solver Types - * @type {number} - */ -GameLib.D3.Physics.SPLIT_SOLVER = 0x1; -GameLib.D3.Physics.GS_SOLVER = 0x2; - -/** - * Physics Solver Superset - * @param id - * @param name - * @param solverType - * @param iterations - * @param tolerance - * @constructor - */ -GameLib.D3.Physics.Solver = function( - id, - name, - solverType, - iterations, - tolerance -) { - this.id = id; - if (typeof name == 'undefined') { - if (solverType == GameLib.D3.Physics.SPLIT_SOLVER) { - name = 'split solver'; - } else if (solverType == GameLib.D3.Physics.GS_SOLVER) { - name = 'gs solver'; - } else { - name = 'unknown solver'; - } - } - this.name = name; - this.solverType = solverType; - this.iterations = iterations; - this.tolerance = tolerance; -}; - -/** - * Physics Broadphase Superset - * @param id - * @param name - * @param broadphaseType - * @constructor - */ -GameLib.D3.Physics.Broadphase = function( - id, - name, - broadphaseType -) { - this.id = id; - - if (typeof name == 'undefined') { - name = 'broadphase-' + broadphaseType; - } - this.name = name; - - if (typeof broadphaseType == 'undefined') { - console.warn('undefined broadphase type'); - throw new Error('undefined broadphase type'); - } - - this.broadphaseType = broadphaseType; -}; - -/** - * Physics World Superset - * @param id - * @param name - * @param physics - * @param gravity - * @param broadphase - * @param solver - * @param rigidBodies - * @constructor - */ -GameLib.D3.Physics.World = function( - id, - name, - physics, - gravity, - broadphase, - solver, - rigidBodies -) { - this.id = id; - - this.name = name; - - if (typeof gravity == 'undefined') { - gravity = new GameLib.D3.Vector3(0, -9.81, 0); - } - this.gravity = gravity; - - if (typeof broadphase == 'undefined') { - broadphase = new GameLib.D3.Physics.Broadphase( - null, - 'broadPhaseNaive', - GameLib.D3.Physics.BROADPHASE_TYPE_NAIVE - ); - } - this.broadphase = broadphase; - - if (typeof solver == 'undefined') { - solver = new GameLib.D3.Physics.Solver( - null, - 'GSSolver', - GameLib.D3.Physics.GS_SOLVER - ); - } - this.solver = solver; - - if (typeof rigidBodies == 'undefined') { - rigidBodies = []; - } - this.rigidBodies = rigidBodies; - - /** - * We only set the physics property if we pass it in the constructor, - * because we don't always want the physics object (ex. when we store this world to the API - we also don't then - * want to store the custom worlds - we want to generate them after loading from API) - */ - if (physics) { - this.physics = physics; - this.physics.worlds.push(this); - this.physics.customWorlds.push(this.getCustomWorld(this)); - } -}; - -/** - * Physics Rigid Body Superset - * @param id - * @param name - * @constructor - */ -GameLib.D3.Physics.RigidBody = function( - id, - name -) { - this.bodyObject = null; -}; - -/** - * Physics Rigid Body Vehicle Superset - * TODO: body + wheels[] - * @constructor - */ -GameLib.D3.Physics.RigidVehicle = function( -) { - this.vehicleObject = null; -}; - -/** - * Physics Raycast Vehicle Superset - * TODO: body + wheels[] - * @constructor - */ -GameLib.D3.Physics.RaycastVehicle = function( -) { - this.vehicleObject = null; -}; - -/** - * Physics Shape Superset - * @constructor - */ -GameLib.D3.Physics.Shape = function( - shapeObject, // Physics engine specific - shapeType -) { - this.shapeObject = shapeObject; - this.shapeType = shapeType; - this.scale = new GameLib.D3.Vector3(1, 1, 1); -}; - -GameLib.D3.Physics.Shape.TYPE_SPHERE = 1; -GameLib.D3.Physics.Shape.TYPE_BOX = 2; -GameLib.D3.Physics.Shape.TYPE_TRIMESH = 3; -GameLib.D3.Physics.Shape.TYPE_CYLINDER = 4; - -/** - * Physics Convex Hull Shape Superset - * @param id - * @param name - * @constructor - */ -GameLib.D3.Physics.Shape.ConvexHull = function( - id, - name -) { - this.id = id; - this.name = name; -}; - -/** - * Physics Triangle Mesh Shape Superset - * @param id - * @param name - * @constructor - */ -GameLib.D3.Physics.Shape.TriangleMesh = function( - id, - name -) { - this.id = id; - this.name = name; -}; - -/** - * TriangleFace - * @param v0 - * @param v1 - * @param v2 - * @param materialIndex - * @param v0uv - * @param v1uv - * @param v2uv - * @param color - * @param vertexColors - * @param vertexNormals - * @param normal - * @constructor - */ -GameLib.D3.TriangleFace = function( - v0, - v1, - v2, - materialIndex, - v0uv, - v1uv, - v2uv, - color, - vertexColors, - vertexNormals, - normal -) { - this.v0 = v0; - this.v1 = v1; - this.v2 = v2; - this.materialIndex = materialIndex; - this.v0uv = v0uv; - this.v1uv = v1uv; - this.v2uv = v2uv; - if (!color) { - color = new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff); - } - this.color = color; - - if (!vertexColors) { - vertexColors = [ - new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), - new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), - new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff) - ]; - } - this.vertexColors = vertexColors; - - if (!vertexNormals) { - vertexNormals = [ - new GameLib.D3.Vector3(), - new GameLib.D3.Vector3(), - new GameLib.D3.Vector3() - ] - } - this.vertexNormals = vertexNormals; - - if (!normal) { - normal = new GameLib.D3.Vector3(0); - } - - this.normal = normal; -}; - -/** - * TriangleEdge - * @param triangle - * @param edge - * @constructor - */ -GameLib.D3.TriangleEdge = function( - triangle, - edge -) { - this.triangle = triangle; - this.edge = edge; -}; - -/** - * Contains a Poly vertex data structure - * @param localIndex - * @param mvertIndex - * @param uv GameLib.D3.Vector2 - * @param materialIndex - * @param edgeIndex - * @constructor - */ -GameLib.D3.PolyVertex = function( - localIndex, - mvertIndex, - uv, - materialIndex, - edgeIndex -) { - this.localIndex = localIndex; - this.mvertIndex = mvertIndex; - this.uv = uv; - this.materialIndex = materialIndex; - this.edgeIndex = edgeIndex; -}; - -/** - * BoneWeight object - associates a vertex to a bone with some weight - * @param boneIndex int - * @param weight float - * @constructor - */ -GameLib.D3.BoneWeight = function( - boneIndex, - weight -) { - this.boneIndex = boneIndex; - this.weight = weight; -}; - -/** - * The normal gets assigned when the face calculates its normal - * @param position - * @param boneWeights GameLib.D3.BoneWeight[] - * @constructor - */ -GameLib.D3.Vertex = function( - position, - boneWeights -) { - this.position = position; - this.boneWeights = boneWeights; -}; - -/** - * Image - * @param id - * @param textureLink - * @param filename - * @param size - * @param contentType - * @constructor - */ -GameLib.D3.Image = function( - id, - textureLink, - filename, - size, - contentType -) { - this.id = id; - - this.filename = filename; - - this.textureLink = textureLink; - - if (typeof size == 'undefined') { - size = 0; - } - this.size = size; - - if (typeof contentType == 'undefined') { - - contentType = 'application/octet-stream'; - - if (this.filename.match(/(png)$/i)) { - contentType = 'image/png'; - } - - if (this.filename.match(/(jpg|jpeg)$/i)) { - contentType = 'image/jpeg'; - } - - if (this.filename.match(/(gif)$/i)) { - contentType = 'image/gif'; - } - } - this.contentType = contentType; - - -}; - -/** - * Scenes are objects putting meshes into 'world space' - * @param id - * @param path String - * @param name String - * @param meshes GameLib.D3.Mesh[] - * @param quaternion - * @param position - * @param rotation - * @param scale - * @param parentSceneId - * @param lights - * @constructor - */ -GameLib.D3.Scene = function( - id, - path, - name, - meshes, - quaternion, - position, - rotation, - scale, - parentSceneId, - lights, - physics -) { - this.id = id; - this.path = path; - this.name = name; - if (this.name.trim() == "") { - this.name = 'unnamed'; - } - this.meshes = meshes; - - if (typeof quaternion == 'undefined') { - quaternion = new GameLib.D3.Vector4(); - } - this.quaternion = quaternion; - - if (typeof position == 'undefined') { - position = new GameLib.D3.Vector3(0,0,0); - } - this.position = position; - - if (typeof rotation == 'undefined') { - rotation = new GameLib.D3.Vector3(0,0,0); - } - this.rotation = rotation; - - if (typeof scale == 'undefined') { - scale = new GameLib.D3.Vector3(1,1,1); - } - this.scale = scale; - - if (typeof parentSceneId == 'undefined') { - parentSceneId = null; - } - this.parentSceneId = parentSceneId; - - if (typeof lights == 'undefined') { - lights = []; - } - this.lights = lights; - - if (typeof physics == 'undefined') { - physics = []; - } - this.physics = physics; -}; - -/** - * Clone a PolyVertex - * @returns {GameLib.D3.PolyVertex} - */ -GameLib.D3.PolyVertex.prototype.clone = function() { - return new GameLib.D3.PolyVertex( - this.localIndex, - this.mvertIndex, - this.uv.copy(), - this.materialIndex, - this.edgeIndex - ) -}; - -/** - * Clone a TriangleFace - * @returns {GameLib.D3.TriangleFace} - */ -GameLib.D3.TriangleFace.prototype.clone = function(){ - return new GameLib.D3.TriangleFace( - this.v0, - this.v1, - this.v2, - this.materialIndex, - this.v0uv.copy(), - this.v1uv.copy(), - this.v2uv.copy() - ); -}; - -/** - * This is a work-around function to fix polys which don't triangulate because - * they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around - * Z then Y axis - * @param verticesFlat [] - * @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY - * @return [] - */ -GameLib.D3.fixPolyZPlane = function(verticesFlat, grain) { - - if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) { - console.log("The vertices are not in the right length : " + verticesFlat.length); - } - - var vertices = []; - - var points = new GameLib.D3.Vector4.Points(); - - for (var i = 0; i < verticesFlat.length; i += 3) { - points.add(new GameLib.D3.Vector3( - verticesFlat[i], - verticesFlat[i + 1], - verticesFlat[i + 2] - )); - } - - points.toOrigin(); - - points.maximizeXDistance(grain); - - points.maximizeYDistance(grain); - - for (i = 0; i < points.vectors.length; i++) { - vertices.push( - [ - points.vectors[i].x, - points.vectors[i].y - ] - ); - } - - return vertices; -}; - -/** - * This function resets the winding order for triangles in faces, given an initial triangle and orientation edge - * used pseudocode from - * http://stackoverflow.com/questions/17036970/how-to-correct-winding-of-triangles-to-counter-clockwise-direction-of-a-3d-mesh - * We need to use a graph traversal algorithm, - * lets assume we have method that returns neighbor of triangle on given edge - * - * neighbor_on_egde( next_tria, edge ) - * - * to_process = set of pairs triangle and orientation edge, initial state is one good oriented triangle with any edge on it - * processed = set of processed triangles; initial empty - * - * while to_process is not empty: - * next_tria, orientation_edge = to_process.pop() - * add next_tria in processed - * if next_tria is not opposite oriented than orientation_edge: - * change next_tria (ABC) orientation (B<->C) - * for each edge (AB) in next_tria: - * neighbor_tria = neighbor_on_egde( next_tria, edge ) - * if neighbor_tria exists and neighbor_tria not in processed: - * to_process add (neighbor_tria, edge opposite oriented (BA)) - * @param faces GameLib.D3.TriangleFace[] - * @param orientationEdge GameLib.D3.Vector2 - * @returns {Array} - */ -GameLib.D3.fixWindingOrder = function(faces, orientationEdge) { - - /** - * Checks if a TriangleFace belonging to a TriangleEdge has already been processed - * @param processed TriangleEdge[] - * @param triangle TriangleFace - * @returns {boolean} - */ - function inProcessed(processed, triangle) { - - for (var i = 0; i < processed.length; i++) { - if (processed[i].triangle.equals(triangle)) { - return true; - } - } - - return false; - } - - /** - * Returns a neighbouring triangle on a specific edge - preserving the edge orientation - * @param edge GameLib.D3.Vector2 - * @param faces GameLib.D3.TriangleFace[] - * @param currentTriangle - * @returns {*} - */ - function neighbourOnEdge(edge, faces, currentTriangle) { - - for (var i = 0; i < faces.length; i++) { - if ( - (faces[i].v0 == edge.x && faces[i].v1 == edge.y) || - (faces[i].v1 == edge.x && faces[i].v2 == edge.y) || - (faces[i].v2 == edge.x && faces[i].v0 == edge.y) || - (faces[i].v0 == edge.y && faces[i].v1 == edge.x) || - (faces[i].v1 == edge.y && faces[i].v2 == edge.x) || - (faces[i].v2 == edge.y && faces[i].v0 == edge.x) - ) { - - var triangle = new GameLib.D3.TriangleFace( - faces[i].v0, - faces[i].v1, - faces[i].v2, - faces[i].materialIndex, - faces[i].v0uv, - faces[i].v1uv, - faces[i].v2uv - ); - - if (triangle.equals(currentTriangle)) { - continue; - } - - return new GameLib.D3.TriangleEdge( - triangle, - edge - ); - } - } - - return null; - } - - var toProcess = [ - new GameLib.D3.TriangleEdge( - new GameLib.D3.TriangleFace( - faces[0].v0, - faces[0].v1, - faces[0].v2, - faces[0].materialIndex, - faces[0].v0uv, - faces[0].v1uv, - faces[0].v2uv - ), - orientationEdge - ) - ]; - - var processed = []; - - while (toProcess.length > 0) { - - var triangleEdge = toProcess.pop(); - - /** - * If edge is the same orientation (i.e. the edge order is the same as the given triangle edge) it needs to be reversed - * to have the same winding order) - */ - if ( - (triangleEdge.triangle.v0 == triangleEdge.edge.x && - triangleEdge.triangle.v1 == triangleEdge.edge.y) || - (triangleEdge.triangle.v1 == triangleEdge.edge.x && - triangleEdge.triangle.v2 == triangleEdge.edge.y) || - (triangleEdge.triangle.v2 == triangleEdge.edge.x && - triangleEdge.triangle.v0 == triangleEdge.edge.y) - ) { - var backupV = triangleEdge.triangle.v1; - triangleEdge.triangle.v1 = triangleEdge.triangle.v2; - triangleEdge.triangle.v2 = backupV; - - var backupUV = triangleEdge.triangle.v1uv; - triangleEdge.triangle.v1uv = triangleEdge.triangle.v2uv; - triangleEdge.triangle.v2uv = backupUV; - } - - processed.push(triangleEdge); - - var edges = [ - new GameLib.D3.Vector2( - triangleEdge.triangle.v0, - triangleEdge.triangle.v1 - ), - new GameLib.D3.Vector2( - triangleEdge.triangle.v1, - triangleEdge.triangle.v2 - ), - new GameLib.D3.Vector2( - triangleEdge.triangle.v2, - triangleEdge.triangle.v0 - ) - ]; - - for (var j = 0; j < edges.length; j++) { - var neighbour = neighbourOnEdge(edges[j], faces, triangleEdge.triangle); - if (neighbour && !inProcessed(processed, neighbour.triangle)) { - toProcess.push(neighbour); - } - } - } - - /** - * In processed - we will have some duplicates - only add the unique ones - * @type {Array} - */ - var triangles = []; - for (var i = 0; i < processed.length; i++) { - var found = false; - for (var k = 0; k < triangles.length; k++) { - if (triangles[k].equals(processed[i].triangle)){ - found = true; - break; - } - } - if (!found) { - triangles.push(processed[i].triangle); - } - } - - return triangles; -}; - -/** - * Returns true if two triangles are equal (their vertex indices match in some order) - * @param triangle - * @returns {boolean} - */ -GameLib.D3.TriangleFace.prototype.equals = function(triangle) { - return !!( - ( - (this.v0 == triangle.v0) && - (this.v1 == triangle.v1) && - (this.v2 == triangle.v2) - ) - || - ( - (this.v0 == triangle.v0) && - (this.v1 == triangle.v2) && - (this.v2 == triangle.v1) - ) - || - ( - (this.v0 == triangle.v1) && - (this.v1 == triangle.v0) && - (this.v2 == triangle.v2) - ) - || - ( - (this.v0 == triangle.v1) && - (this.v1 == triangle.v2) && - (this.v2 == triangle.v0) - ) - || - ( - (this.v0 == triangle.v2) && - (this.v1 == triangle.v0) && - (this.v2 == triangle.v1) - ) - || - ( - (this.v0 == triangle.v2) && - (this.v1 == triangle.v1) && - (this.v2 == triangle.v0) - )); -}; - -GameLib.D3.prototype.invertWindingOrder = function(triangles) { - - for (var i = 0; i < triangles.length; i++) { - var v1 = triangles[i].v1; - triangles[i].v1 = triangles[i].v2; - triangles[i].v2 = v1; - - var backupUV = triangles[i].triangle.v1uv; - triangles[i].triangle.v1uv = triangles[i].triangle.v2uv; - triangles[i].triangle.v2uv = backupUV; - } - - return triangles; -}; - -/** - * This function resets a the winding order of a mesh from a reference point V (the average center of the mesh) - */ -GameLib.D3.prototype.resetWindingOrder = function(faces, vertices) { - - var vertexList = new GameLib.D3.Vector3.Points(); - - for (var v = 0; v < vertices.length; v++) { - vertexList.add(new GameLib.D3.Vector3( - vertices[v].position.x, - vertices[v].position.y, - vertices[v].position.z - )); - } - - var V = vertexList.average(); - - var triangles = []; - - for (var s = 0; s < faces.length; s += 3) { - - var v0 = faces[s]; - var v1 = faces[s+1]; - var v2 = faces[s+2]; - - triangles.push( - { - v0 : v0, - v1 : v1, - v2 : v2, - edges : [ - {v0: v0, v1: v1}, - {v0: v1, v1: v2}, - {v0: v2, v1: v0} - ], - winding : 0, - edgeIndex : -1, - processed : false - } - ); - } - - for (var i = 0; i < triangles.length; i++) { - if ( - GameLib.D3.Vector3.clockwise( - vertices[triangles[i].v0].position, - vertices[triangles[i].v1].position, - vertices[triangles[i].v2].position, - V - ) - ) { - console.log('clockwise'); - var bv1 = triangles[i].v1; - triangles[i].v1 = triangles[i].v2; - triangles[i].v2 = bv1; - } else { - console.log('not clockwise'); - } - } - - return triangles; -}; - -/** - * Defers loading of an image and resolves once image is loaded - * @param gameLibTexture - * @param threeMaterial - * @param threeMaterialMapType - * @returns {Promise} - */ -GameLib.D3.prototype.loadMap = function(gameLibTexture, threeMaterial, threeMaterialMapType) { - - var q = this.Q.defer(); - - var imagePath = null; - - if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.filename) { - /** - * Else, load from upload source - */ - imagePath = this.editorUrl + '/uploads' + this.path + '/' + gameLibTexture.image.filename; - } - - if (imagePath) { - - this.textureLoader.crossOrigin = ''; - - this.textureLoader.load( - imagePath, - function(texture) { - /** - * onLoad - */ - threeMaterial[threeMaterialMapType] = texture; - threeMaterial[threeMaterialMapType].name = gameLibTexture.name; - threeMaterial[threeMaterialMapType].anisotropy = gameLibTexture.anisotropy; - threeMaterial[threeMaterialMapType].encoding = gameLibTexture.encoding; - threeMaterial[threeMaterialMapType].flipY = gameLibTexture.flipY; - /** - * We don't restore the format since this changing from OS to OS and breaks the implementation sometimes - */ - threeMaterial[threeMaterialMapType].generateMipmaps = gameLibTexture.generateMipmaps; - threeMaterial[threeMaterialMapType].magFilter = gameLibTexture.magFilter; - threeMaterial[threeMaterialMapType].minFilter = gameLibTexture.minFilter; - threeMaterial[threeMaterialMapType].mapping = gameLibTexture.mapping; - threeMaterial[threeMaterialMapType].mipmaps = gameLibTexture.mipmaps; - threeMaterial[threeMaterialMapType].offset = new this.THREE.Vector2( - gameLibTexture.offset.x, - gameLibTexture.offset.y - ); - threeMaterial[threeMaterialMapType].premultiplyAlpha = gameLibTexture.premultiplyAlpha; - threeMaterial[threeMaterialMapType].textureType = gameLibTexture.textureType; - threeMaterial[threeMaterialMapType].wrapS = gameLibTexture.wrapS; - threeMaterial[threeMaterialMapType].wrapT = gameLibTexture.wrapT; - threeMaterial[threeMaterialMapType].unpackAlignment = gameLibTexture.unpackAlignment; - threeMaterial.needsUpdate = true; - q.resolve(true); - }, - function(xhr) { - /** - * onProgress - */ - if (this.editor) { - this.editor.setServerStatus(Math.round(xhr.loaded / xhr.total * 100) + '% complete', 'success'); - } - }, - function(error) { - /** - * onError - */ - console.log("an error occurred while trying to load the image : " + imagePath); - q.resolve(null); - } - ); - - } else { - q.resolve(null); - } - - return q.promise; -}; - -/** - * Creates a THREE Mesh from GameLib.D3.Mesh - * @param gameLibMesh - * @param threeGeometry - * @param threeMaterial - * @returns {*} - */ -GameLib.D3.prototype.createThreeMesh = function(gameLibMesh, threeGeometry, threeMaterial) { - - var threeMesh = null; - - if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) { - threeMesh = new this.THREE.Mesh(threeGeometry, threeMaterial); - } - - if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) { - - var bones = gameLibMesh.skeleton.bones; - - var skinIndices = gameLibMesh.skinIndices; - - var skinWeights = gameLibMesh.skinWeights; - - var threeBones = []; - - for (var bi = 0; bi < bones.length; bi++) { - - var bone = new this.THREE.Bone(); - - bone.name = bones[bi].name; - - bone.position.x = bones[bi].position.x; - bone.position.y = bones[bi].position.y; - bone.position.z = bones[bi].position.z; - - bone.rotation.x = bones[bi].rotation.x; - bone.rotation.y = bones[bi].rotation.y; - bone.rotation.z = bones[bi].rotation.z; - - bone.quaternion.x = bones[bi].quaternion.x; - bone.quaternion.y = bones[bi].quaternion.y; - bone.quaternion.z = bones[bi].quaternion.z; - bone.quaternion.w = bones[bi].quaternion.w; - - bone.scale.x = bones[bi].scale.x; - bone.scale.y = bones[bi].scale.y; - bone.scale.z = bones[bi].scale.z; - - bone.up.x = bones[bi].up.x; - bone.up.y = bones[bi].up.y; - bone.up.z = bones[bi].up.z; - - threeBones.push(bone); - } - - /** - * Setup the bone relationships - */ - for (var br = 0; br < bones.length; br++) { - for (var cbi = 0; cbi < bones[br].childBoneIds.length; cbi++) { - threeBones[br].add(threeBones[bones[br].childBoneIds[cbi]]); - } - } - - /** - * Setup bones (indexes) - */ - for (var si = 0; si < skinIndices.length; si++) { - threeGeometry.skinIndices.push( - new this.THREE.Vector4( - skinIndices[si].x, - skinIndices[si].y, - skinIndices[si].z, - skinIndices[si].w - ) - ); - } - - /** - * Setup bones (weights) - */ - for (var sw = 0; sw < skinWeights.length; sw++) { - threeGeometry.skinWeights.push( - new this.THREE.Vector4( - skinWeights[sw].x, - skinWeights[sw].y, - skinWeights[sw].z, - skinWeights[sw].w - ) - ); - } - - threeMesh = new this.THREE.SkinnedMesh(threeGeometry, threeMaterial); - - var skeleton = new this.THREE.Skeleton(threeBones); - - skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture; - - for (var i = 0; i < bones.length; i++) { - if (bones[i].parentBoneId === null) { - threeMesh.add(threeBones[i]); - break; - } - } - - threeMesh.bind(skeleton); - - threeMesh.pose(); - - threeMesh.skeleton.skeletonHelper = new this.THREE.SkeletonHelper(threeMesh); - threeMesh.skeleton.skeletonHelper.material.linewidth = 5; - } - - if (threeMesh == null) { - console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.'); - } - - gameLibMesh.threeMeshId = threeMesh.id; - - return threeMesh; -}; - -/** - * Returns an array of image loading Promises - * @param blenderMaterial - * @param blenderMaps - * @param threeMaterial - * @returns Q[] - */ -GameLib.D3.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMaterial) { - - var textureMaps = []; - - for (var ti = 0; ti < blenderMaps.length; ti++) { - - var map = blenderMaps[ti]; - - if (blenderMaterial.maps.hasOwnProperty(map)) { - - var blenderTexture = blenderMaterial.maps[map]; - - if ( - blenderTexture && - blenderTexture.image && - blenderTexture.image.filename - ) { - - var threeMap = null; - - if (map == 'alpha') { - threeMap = 'alhpaMap'; - } - - if (map == 'ao') { - threeMap = 'aoMap'; - } - - if (map == 'bump') { - threeMap = 'bumpMap'; - } - - if (map == 'displacement') { - threeMap = 'displacementMap'; - } - - if (map == 'emissive') { - threeMap = 'emissiveMap'; - } - - if (map == 'environment') { - threeMap = 'envMap'; - } - - if (map == 'light') { - threeMap = 'lightMap'; - } - - if (map == 'specular') { - threeMap = 'specularMap'; - } - - if (map == 'diffuse') { - threeMap = 'map'; - } - - if (map == 'roughness') { - threeMap = 'roughnessMap'; - } - - if (map == 'metalness') { - threeMap = 'metalnessMap'; - } - - if (threeMap == null) { - console.warn("unsupported map type : " + map); - } - - textureMaps.push(this.loadMap(blenderMaterial.maps[map], threeMaterial, threeMap)); - } - } - } - - return textureMaps; -}; - -/** - * Creates a this.THREE.Material from a GameLib.D3.Material - * @param blenderMaterial GameLib.D3.Material - */ -GameLib.D3.prototype.createThreeMaterial = function(blenderMaterial) { - - var defer = this.Q.defer(); - - var threeMaterial = null; - - var blenderMaps = []; - - if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) { - - threeMaterial = new this.THREE.MeshStandardMaterial({ - name: blenderMaterial.name, - opacity: blenderMaterial.opacity, - transparent: blenderMaterial.transparent, - blending: blenderMaterial.blending, - blendSrc: blenderMaterial.blendSrc, - blendDst: blenderMaterial.blendDst, - blendEquation: blenderMaterial.blendEquation, - depthTest: blenderMaterial.depthTest, - depthFunc: blenderMaterial.depthFunc, - depthWrite: blenderMaterial.depthWrite, - polygonOffset: blenderMaterial.polygonOffset, - polygonOffsetFactor: blenderMaterial.polygonOffsetFactor, - polygonOffsetUnits: blenderMaterial.polygonOffsetUnits, - alphaTest: blenderMaterial.alphaTest, - clippingPlanes: blenderMaterial.clippingPlanes, - clipShadows: blenderMaterial.clipShadows, - overdraw: blenderMaterial.overdraw, - visible: blenderMaterial.visible, - side: blenderMaterial.side, - color: new this.THREE.Color( - blenderMaterial.color.r, - blenderMaterial.color.g, - blenderMaterial.color.b - ), - roughness: blenderMaterial.roughness, - metalness: blenderMaterial.metalness, - lightMapIntensity: blenderMaterial.lightMapIntensity, - aoMapIntensity: blenderMaterial.aoMapIntensity, - emissive: new this.THREE.Color( - blenderMaterial.emissive.r, - blenderMaterial.emissive.g, - blenderMaterial.emissive.b - ), - emissiveIntensity: blenderMaterial.emissiveIntensity, - bumpScale: blenderMaterial.bumpScale, - normalScale: blenderMaterial.normalScale, - displacementScale: blenderMaterial.displacementScale, - refractionRatio: blenderMaterial.refractionRatio, - fog: blenderMaterial.fog, - shading: blenderMaterial.shading, - wireframe: blenderMaterial.wireframe, - wireframeLinewidth: blenderMaterial.wireframeLineWidth, - wireframeLinecap: blenderMaterial.wireframeLineCap, - wireframeLinejoin: blenderMaterial.wireframeLineJoin, - vertexColors: blenderMaterial.vertexColors, - skinning: blenderMaterial.skinning, - morphTargets: blenderMaterial.morphTargets, - morphNormals: blenderMaterial.morphNormals - }); - - blenderMaps.push( - 'diffuse', - 'light', - 'ao', - 'emissive', - 'bump', - 'normal', - 'displacement', - 'roughness', - 'metalness', - 'alpha', - 'environment' - ); - } else if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) { - - threeMaterial = new this.THREE.MeshPhongMaterial({ - name: blenderMaterial.name, - opacity: blenderMaterial.opacity, - transparent: blenderMaterial.transparent, - blending: blenderMaterial.blending, - blendSrc: blenderMaterial.blendSrc, - blendDst: blenderMaterial.blendDst, - blendEquation: blenderMaterial.blendEquation, - depthTest: blenderMaterial.depthTest, - depthFunc: blenderMaterial.depthFunc, - depthWrite: blenderMaterial.depthWrite, - polygonOffset: blenderMaterial.polygonOffset, - polygonOffsetFactor: blenderMaterial.polygonOffsetFactor, - polygonOffsetUnits: blenderMaterial.polygonOffsetUnits, - alphaTest: blenderMaterial.alphaTest, - clippingPlanes: blenderMaterial.clippingPlanes, - clipShadows: blenderMaterial.clipShadows, - overdraw: blenderMaterial.overdraw, - visible: blenderMaterial.visible, - side: blenderMaterial.side, - color: new this.THREE.Color( - blenderMaterial.color.r, - blenderMaterial.color.g, - blenderMaterial.color.b - ), - specular: new this.THREE.Color( - blenderMaterial.specular.r, - blenderMaterial.specular.g, - blenderMaterial.specular.b - ), - shininess: blenderMaterial.shininess, - lightMapIntensity: blenderMaterial.lightMapIntensity, - aoMapIntensity: blenderMaterial.aoMapIntensity, - emissive: new this.THREE.Color( - blenderMaterial.emissive.r, - blenderMaterial.emissive.g, - blenderMaterial.emissive.b - ), - emissiveIntensity: blenderMaterial.emissiveIntensity, - bumpScale: blenderMaterial.bumpScale, - normalScale: blenderMaterial.normalScale, - displacementScale: blenderMaterial.displacementScale, - combine: blenderMaterial.combine, - refractionRatio: blenderMaterial.refractionRatio, - fog: blenderMaterial.fog, - shading: blenderMaterial.shading, - wireframe: blenderMaterial.wireframe, - wireframeLinewidth: blenderMaterial.wireframeLineWidth, - wireframeLinecap: blenderMaterial.wireframeLineCap, - wireframeLinejoin: blenderMaterial.wireframeLineJoin, - vertexColors: blenderMaterial.vertexColors, - skinning: blenderMaterial.skinning, - morphTargets: blenderMaterial.morphTargets, - morphNormals: blenderMaterial.morphNormals - }); - - blenderMaps.push( - 'diffuse', - 'light', - 'ao', - 'emissive', - 'bump', - 'normal', - 'displacement', - 'specular', - 'alpha', - 'environment' - ); - - } else { - console.log("material type is not implemented yet: " + blenderMaterial.materialType + " - material indexes could be screwed up"); - } - - if (blenderMaps.length > 0) { - var textureMaps = this.loadMaps(blenderMaterial, blenderMaps, threeMaterial); - Q.all(textureMaps).then( - function(){ - defer.resolve(threeMaterial); - } - ).catch( - function(error){ - console.log(error); - defer.reject(error); - } - ) - } else { - defer.resolve(threeMaterial); - } - - return defer.promise; -}; - -/** - * Loads a scene directly from the API - * @param sceneName - * @param onLoaded callback - */ -GameLib.D3.prototype.loadSceneFromApi = function(scene, onLoaded) { - - /** - * First check if this is a client or server side request - */ - if (typeof XMLHttpRequest == 'undefined') { - console.warn('implement server side loading from API here'); - return onLoaded(null, new Error('not implemented')); - } - - var xhr = new XMLHttpRequest(); - xhr.open( - 'GET', - this.apiUrl + '/scene/load' + scene.path + '/' + scene.name - ); - - xhr.onreadystatechange = function(xhr, gameLibD3) { - return function() { - if (xhr.readyState == 4) { - - var response = JSON.parse(xhr.responseText); - - if (!response.scene || response.scene.length == 0) { - return onLoaded(null, null, new Error('Could not load scene')); - } - - var scene = response.scene[0]; - - var physics3ds = []; - - if (scene.physics && scene.physics.length > 0) { - - for (var p = 0; p < scene.physics.length; p++) { - - var physics = scene.physics[p]; - - var physics3d = new GameLib.D3.Physics( - physics.id, - physics.name, - physics.engineType, - gameLibD3.CANNON, - null, - null - ); - - var worlds3d = []; - - for (var w = 0; w < physics.worlds.length; w++) { - - var world = physics.worlds[w]; - - var broadphase = world.broadphase; - - var broadphase3d = new GameLib.D3.Physics.Broadphase( - broadphase.id, - broadphase.name, - broadphase.broadphaseType - ); - - var solver = world.solver; - - var solver3d = new GameLib.D3.Physics.Solver( - solver.id, - solver.name, - solver.solverType, - solver.iterations, - solver.tolerance - ); - - var bodies = world.rigidBodies; - - var bodies3d = []; - - for (var b = 0; b < bodies.length; b++) { - - var body = bodies[b]; - - //TODO: add all body properties here - var body3d = new GameLib.D3.Physics.RigidBody( - body.id, - body.name - ); - - bodies3d.push(body3d); - } - - var world3d = new GameLib.D3.Physics.World( - null, - world.name, - physics3d, - new GameLib.D3.Vector3( - world.gravity.x, - world.gravity.y, - world.gravity.z - ), - broadphase3d, - solver3d, - bodies3d - ); - - worlds3d.push(world3d); - } - - physics3ds.push(physics3d); - } - } - - var lights3d = []; - - for (var l = 0; l < scene.lights.length; l++) { - - var light = scene.lights[l]; - - var light3d = new GameLib.D3.Light( - light.id, - light.lightType, - light.name, - new GameLib.D3.Color( - light.color.r, - light.color.g, - light.color.b, - light.color.a - ), - light.intensity, - new GameLib.D3.Vector3( - light.position.x, - light.position.y, - light.position.z - ), - new GameLib.D3.Vector3( - light.targetPosition.x, - light.targetPosition.y, - light.targetPosition.z - ), - new GameLib.D3.Vector4( - light.quaternion.x, - light.quaternion.y, - light.quaternion.z, - light.quaternion.w - ), - new GameLib.D3.Vector3( - light.rotation.x, - light.rotation.y, - light.rotation.z - ), - new GameLib.D3.Vector3( - light.scale.x, - light.scale.y, - light.scale.z - ), - light.distance, - light.decay, - light.power, - light.angle, - light.penumbra - ); - - lights3d.push(light3d); - }; - - var scene3d = new GameLib.D3.Scene( - scene._id || scene.id, - scene.path, - scene.name, - scene.meshes, - new GameLib.D3.Vector4( - scene.quaternion.x, - scene.quaternion.y, - scene.quaternion.z, - scene.quaternion.w - ), - new GameLib.D3.Vector3( - scene.position.x, - scene.position.y, - scene.position.z - ), - new GameLib.D3.Vector3( - scene.rotation.x, - scene.rotation.y, - scene.rotation.z - ), - new GameLib.D3.Vector3( - scene.scale.x, - scene.scale.y, - scene.scale.z - ), - scene.parentSceneId, - lights3d, - physics3ds - ); - - gameLibD3.loadScene(scene3d, onLoaded, false); - } - } - }(xhr, this); - - xhr.send(); -}; - -/** - * Loads a GameLib.D3.Scene object into a ThreeJS Scene object - * @param gameLibScene GameLib.D3.Scene - * @param onLoaded callback when all meshes have loaded - * @param computeNormals set to true to compute new face and vertex normals during load - */ -GameLib.D3.prototype.loadScene = function(gameLibScene, onLoaded, computeNormals) { - - console.log("loading scene " + gameLibScene.name); - - this.path = gameLibScene.path; - - var meshQ = []; - - for (var m = 0; m < gameLibScene.meshes.length; m++) { - - var mesh = gameLibScene.meshes[m]; - - console.log("loading mesh " + mesh.name); - - var geometry = new this.THREE.Geometry(); - - var vertices = mesh.vertices; - - var faces = mesh.faces; - - var faceVertexUvs = mesh.faceVertexUvs; - - var materials = mesh.materials; - - /** - * Setup vertices - */ - for (var v = 0; v < vertices.length; v++) { - geometry.vertices.push( - new this.THREE.Vector3( - vertices[v].position.x, - vertices[v].position.y, - vertices[v].position.z - ) - ) - } - - /** - * Setup faces - */ - for (var f = 0; f < faces.length; f++) { - - var face = new this.THREE.Face3( - faces[f].v0, - faces[f].v1, - faces[f].v2, - new this.THREE.Vector3( - faces[f].normal.x, - faces[f].normal.y, - faces[f].normal.z - ), - new this.THREE.Color( - faces[f].color.r, - faces[f].color.g, - faces[f].color.b - ), - faces[f].materialIndex - ); - - face.vertexColors = [ - new this.THREE.Color( - faces[f].vertexColors[0].r, - faces[f].vertexColors[0].g, - faces[f].vertexColors[0].b - ), - new this.THREE.Color( - faces[f].vertexColors[1].r, - faces[f].vertexColors[1].g, - faces[f].vertexColors[1].b - ), - new this.THREE.Color( - faces[f].vertexColors[2].r, - faces[f].vertexColors[2].g, - faces[f].vertexColors[2].b - ) - ]; - - face.normal = new this.THREE.Vector3( - faces[f].normal.x, - faces[f].normal.y, - faces[f].normal.z - ); - - face.vertexNormals = [ - new this.THREE.Vector3( - faces[f].vertexNormals[0].x, - faces[f].vertexNormals[0].y, - faces[f].vertexNormals[0].z - ), - new this.THREE.Vector3( - faces[f].vertexNormals[1].x, - faces[f].vertexNormals[1].y, - faces[f].vertexNormals[1].z - ), - new this.THREE.Vector3( - faces[f].vertexNormals[2].x, - faces[f].vertexNormals[2].y, - faces[f].vertexNormals[2].z - ) - ]; - - geometry.faces.push(face); - } - - geometry.faceVertexUvs = []; - - /** - * Setup face UVs - */ - for (var fm = 0; fm < faceVertexUvs.length; fm++) { - - var faceMaterialVertexUvs = faceVertexUvs[fm]; - - geometry.faceVertexUvs[fm] = []; - - for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) { - geometry.faceVertexUvs[fm][fuv] = []; - geometry.faceVertexUvs[fm][fuv].push( - new this.THREE.Vector2( - faceMaterialVertexUvs[fuv][0].x, - faceMaterialVertexUvs[fuv][0].y - ), - new this.THREE.Vector2( - faceMaterialVertexUvs[fuv][1].x, - faceMaterialVertexUvs[fuv][1].y - ), - new this.THREE.Vector2( - faceMaterialVertexUvs[fuv][2].x, - faceMaterialVertexUvs[fuv][2].y - ) - ); - } - } - - /** - * Re-calculate normals (if we have to) - * @type {Array} - */ - if (computeNormals) { - geometry.computeFaceNormals(); - geometry.computeVertexNormals(); - } - - var threeMaterialLoaders = []; - - /** - * Setup materials - */ - for (var mi = 0; mi < materials.length; mi++) { - threeMaterialLoaders.push(this.createThreeMaterial(materials[mi])); - } - - var result = this.Q.all(threeMaterialLoaders).then( - function(gl3d, mesh, geometry) { - return function(materials) { - - console.log("loaded material : " + materials[0].name); - - /** - * We don't support MultiMaterial atm - it doesn't work with raycasting - */ - var material = materials[0]; - - var threeMesh = gl3d.createThreeMesh(mesh, geometry, material); - threeMesh.name = mesh.name; - - threeMesh.position.x = mesh.position.x; - threeMesh.position.y = mesh.position.y; - threeMesh.position.z = mesh.position.z; - - threeMesh.rotation.x = mesh.rotation.x; - threeMesh.rotation.y = mesh.rotation.y; - threeMesh.rotation.z = mesh.rotation.z; - - threeMesh.scale.x = mesh.scale.x; - threeMesh.scale.y = mesh.scale.y; - threeMesh.scale.z = mesh.scale.z; - - threeMesh.quaternion.x = mesh.quaternion.x; - threeMesh.quaternion.y = mesh.quaternion.y; - threeMesh.quaternion.z = mesh.quaternion.z; - threeMesh.quaternion.w = mesh.quaternion.w; - - return threeMesh; - }; - }(this, mesh, geometry) - ).catch(function(error){ - console.log(error); - }); - - meshQ.push(result); - } - - this.Q.all(meshQ).then(function(threeMeshes){ - console.log("all meshes have loaded"); - if (typeof onLoaded != 'undefined') { - - var threeLights = []; - - for (var sli = 0; sli < gameLibScene.lights.length; sli++) { - - var blenderLight = gameLibScene.lights[sli]; - - var light = null; - - if (blenderLight.lightType == 'AmbientLight') { - light = new this.THREE.AmbientLight(blenderLight.color, blenderLight.intensity); - } - - if (blenderLight.lightType == 'DirectionalLight') { - light = new this.THREE.DirectionalLight(blenderLight.color, blenderLight.intensity); - } - - if (blenderLight.lightType == 'PointLight') { - light = new this.THREE.PointLight(blenderLight.color, blenderLight.intensity); - light.distance = blenderLight.distance; - light.decay = blenderLight.decay; - } - - if (blenderLight.lightType == 'SpotLight') { - light = new this.THREE.SpotLight(blenderLight.color, blenderLight.intensity); - light.distance = blenderLight.distance; - light.angle = blenderLight.angle; - light.penumbra = blenderLight.penumbra; - light.decay = blenderLight.decay; - } - - light.position.x = blenderLight.position.x; - light.position.y = blenderLight.position.y; - light.position.z = blenderLight.position.z; - - light.rotation.x = blenderLight.rotation.x; - light.rotation.y = blenderLight.rotation.y; - light.rotation.z = blenderLight.rotation.z; - - // light.scale.x = blenderLight.scale.x; - // light.scale.y = blenderLight.scale.y; - // light.scale.z = blenderLight.scale.z; - - if (light == null) { - console.warn('Does not support lights of type :' + blenderLight.lightType + ', not imported'); - } else { - light.name = blenderLight.name; - threeLights.push(light); - } - } - - var threeScene = new this.THREE.Scene(); - - threeScene.name = gameLibScene.name; - - threeScene.position.x = gameLibScene.position.x; - threeScene.position.y = gameLibScene.position.y; - threeScene.position.z = gameLibScene.position.z; - - threeScene.rotation.x = gameLibScene.rotation.x; - threeScene.rotation.y = gameLibScene.rotation.y; - threeScene.rotation.z = gameLibScene.rotation.z; - - threeScene.scale.x = gameLibScene.scale.x; - threeScene.scale.y = gameLibScene.scale.y; - threeScene.scale.z = gameLibScene.scale.z; - - threeScene.quaternion.x = gameLibScene.quaternion.x; - threeScene.quaternion.y = gameLibScene.quaternion.y; - threeScene.quaternion.z = gameLibScene.quaternion.z; - threeScene.quaternion.w = gameLibScene.quaternion.w; - - for (var m = 0; m < threeMeshes.length; m++) { - threeScene.add(threeMeshes[m]); - } - - for (var l = 0; l < threeLights.length; l++) { - threeScene.add(threeLights[l]); - } - - onLoaded( - gameLibScene, - { - scene: threeScene, - lights: threeLights, - meshes: threeMeshes - } - ); - } - }.bind(this)).catch(function(error){ - console.log(error); - }); -}; - -/** --------------- - * Physics - * --------------- */ -/** - * Creates a Custom World object from a GameLib.D3.Physics.World - */ -GameLib.D3.Physics.World.prototype.getCustomWorld = function() { - - var engineType = this.physics.engineType; - - if (engineType != GameLib.D3.Physics.TYPE_CANNON) { - console.warn('Unsupported engine type: ' + engineType); - throw new Error('Unsupported engine type: ' + engineType); - } - - var customWorld = new this.physics.CANNON.World(); - - var cannonBroadphase = null; - - if (this.broadphase.broadphaseType == GameLib.D3.Physics.BROADPHASE_TYPE_NAIVE) { - cannonBroadphase = new this.physics.CANNON.NaiveBroadphase(); - } else if (this.broadphase.broadphaseType == GameLib.D3.Physics.BROADPHASE_TYPE_GRID) { - cannonBroadphase = new this.physics.CANNON.GridBroadphase(); - } else if (this.broadphase.broadphaseType == GameLib.D3.Physics.BROADPHASE_TYPE_SAP) { - cannonBroadphase = new this.physics.CANNON.SAPBroardphase(); - } else { - console.warn('Unsupported broadphase type: ' + this.broadphase.broadphaseType); - throw new Error('Unsupported broadphase type: ' + this.broadphase.broadphaseType); - } - - customWorld.broadphase = cannonBroadphase; - - var cannonSolver = null; - - if (this.solver.solverType == GameLib.D3.Physics.SPLIT_SOLVER) { - cannonSolver = new this.physics.CANNON.SplitSolver(); - } else if (this.solver.solverType == GameLib.D3.Physics.GS_SOLVER) { - cannonSolver = new this.physics.CANNON.GSSolver(); - cannonSolver.iterations = this.solver.iterations; - } - - customWorld.solver = cannonSolver; - - customWorld.gravity.x = this.gravity.x; - customWorld.gravity.y = this.gravity.y; - customWorld.gravity.z = this.gravity.z; - - for (var b = 0; b < this.rigidBodies.length; b++) { - - var customBody = this.createCustomBody(this.rigidBodies[b]); - - //customWorld.AddRigidBody(); - } - - customWorld.name = this.name; - - return customWorld; -}; - - -GameLib.D3.Physics.Shape.prototype.Update = function( - physicsWorld -) { - if(physicsWorld.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - if(this.shapeType === GameLib.D3.Physics.Shape.TYPE_TRIMESH) { - this.shapeObject.setScale(new CANNON.Vec3(this.scale.x, this.scale.y, this.scale.z)); - this.shapeObject.scale.x = this.scale.x; - this.shapeObject.scale.y = this.scale.y; - this.shapeObject.scale.z = this.scale.z; - this.shapeObject.updateAABB(); - this.shapeObject.updateNormals(); - this.shapeObject.updateEdges(); - this.shapeObject.updateBoundingSphereRadius(); - this.shapeObject.updateTree(); - } - } -}; - -GameLib.D3.Physics.World.prototype.AddShape = function( - shape, // d3.physics.shape - rigidBody, - offset, // vec3 - orientation //quaternion -) { - shape.shape = shape; - - if(this.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - - var _offset = null; - var _orientation = null; - - if(offset != null && typeof offset !== 'undefined') { - _offset = new CANNON.Vec3(offset.x, offset.y, offset.z); - } - - if(orientation != null && typeof orientation !== 'undefined') { - _orientation = new CANNON.Quaternion(orientation.x, orientation.y, orientation.z, orientation.w); - } - - rigidBody.bodyObject.addShape(shape.shapeObject, _offset, _orientation); - } -}; - -GameLib.D3.Physics.World.prototype.CreateRigidVehicle = function( - chassisBody // Physics.RigidBody -) { - var rigidVehicle = new GameLib.D3.Physics.RigidVehicle(); - - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - var vehicle = new CANNON.RigidVehicle({ - chassisBody: chassisBody.bodyObject - }); - rigidVehicle.vehicleObject = vehicle; - return rigidVehicle; - } -}; - -GameLib.D3.Physics.World.prototype.CreateRaycastVehicle = function( - chassisBody // Physics.RigidBody -) { - var raycastVehicle = new GameLib.D3.Physics.RaycastVehicle(); - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - var vehicle = new CANNON.RaycastVehicle({ - chassisBody: chassisBody.bodyObject - }); - raycastVehicle.vehicleObject = vehicle; - return raycastVehicle; - } -}; - -GameLib.D3.Physics.World.prototype.AddWheelToRigidVehicle = function( - vehicle, - rigidBody, - position, - axis, - direction -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - vehicle.vehicleObject.addWheel({ - body: rigidBody.bodyObject, - position: new CANNON.Vec3(position.x, position.y, position.z), - axis: new CANNON.Vec3(axis.x, axis.y, axis.z), - direction: new CANNON.Vec3(direction.x, direction.y, direction.z) - }); - } -}; - -GameLib.D3.Physics.World.prototype.AddWheelToRaycastVehicle = function ( - vehicle, // physics.raycastvehicle - options // cannon options -) { - if (this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - vehicle.vehicleObject.addWheel(options); - } else { - console.log("function for engine not implemented"); - } -}; - -GameLib.D3.Physics.RigidVehicle.prototype.GetWheelInfo = function( - -) { - // note: need a way to determine which engine we are currently using - return this.vehicleObject.wheelBodies; -}; - -GameLib.D3.Physics.RaycastVehicle.prototype.GetWheelInfo = function( - -) { - // note: need a way to determine which engine we are currently using - return this.vehicleObject.wheelInfos; -}; - - -GameLib.D3.Physics.World.prototype.CreateRigidBody = function( - mass, - friction, - position, - quaternion, - velocity, - angularVelocity, - linearDamping, - angularDamping, - allowSleep, - sleepSpeedLimit, - sleepTimeLimit, - collisionFilterGroup, - collisionFilterMask, - fixedRotation, - shape -) { - - var rigidBody = new GameLib.D3.Physics.RigidBody(0, "null"); - - position = position || new GameLib.D3.Vector3(); - velocity = velocity || new GameLib.D3.Vector3(); - angularVelocity = angularVelocity || new GameLib.D3.Vector3(); - quaternion = quaternion || new GameLib.D3.Vector4(0, 0, 0, 1); - mass = typeof mass == "undefined" ? 0 : mass; - friction = typeof friction == "undefined" ? 5 : friction; - linearDamping = typeof linearDamping == "undefined" ? 0.01 : linearDamping; - angularDamping = typeof angularDamping == "undefined" ? 0.01 : angularDamping; - allowSleep = typeof allowSleep == "undefined" ? true : allowSleep; - sleepSpeedLimit = typeof sleepSpeedLimit == "undefined" ? 0.1 : sleepSpeedLimit; - sleepTimeLimit = typeof sleepTimeLimit == "undefined" ? 1.0 : sleepTimeLimit; - collisionFilterGroup = typeof collisionFilterGroup == "undefined" ? 1 : collisionFilterGroup; - collisionFilterMask = typeof collisionFilterMask == "undefined" ? 1 : collisionFilterMask; - fixedRotation = typeof fixedRotation == "undefined" ? false : fixedRotation; - shape = typeof shape == "undefined" ? null : shape; - - - // Create the bodyObject - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - rigidBody.bodyObject = new CANNON.Body( - { - mass: mass, - friction: friction, - position: new CANNON.Vec3(position.x, position.y, position.z), - velocity: new CANNON.Vec3(velocity.x, velocity.y, velocity.z), - quaternion: new CANNON.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w), - angularVelocity: new CANNON.Vec3(angularVelocity.x, angularVelocity.y, angularVelocity.z), - linearDamping: linearDamping, - angularDamping: angularDamping, - allowSleep: allowSleep, - sleepSpeedLimit: sleepSpeedLimit, - sleepTimeLimit: sleepTimeLimit, - collisionFilterGroup: collisionFilterGroup, - collisionFilterMask: collisionFilterMask, - fixedRotation: fixedRotation, - shape: shape - } - ); - - return rigidBody; - } -}; - -GameLib.D3.Physics.World.prototype.CreateTriMeshShape = function( - vertices, // flat list of floats - indices // float list of floats -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Trimesh(vertices, indices), GameLib.D3.Physics.Shape.TYPE_TRIMESH); - } -}; - -GameLib.D3.Physics.World.prototype.CreateSphereShape = function ( - radius -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Sphere(radius), GameLib.D3.Physics.Shape.TYPE_SPHERE); - } -}; - -GameLib.D3.Physics.World.prototype.CreateBoxShape = function( - halfExtensions // vec3 -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Box(new CANNON.Vec3(halfExtensions.x, halfExtensions.y, halfExtensions.z)), GameLib.D3.Physics.Shape.TYPE_BOX); - } -}; - -GameLib.D3.Physics.World.prototype.CreateCylinderShape = function( - radiusTop, - radiusBottom, - height, - numSegments -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - return new GameLib.D3.Physics.Shape(new CANNON.Cylinder(radiusTop, radiusBottom, height, numSegments), GameLib.D3.Physics.Shape.TYPE_CYLINDER); - } -}; - -GameLib.D3.Physics.World.prototype.AddRigidBody = function( - rigidBody // Physics.RigidBody -) { - if(this.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - this.worldObject.addBody(rigidBody.bodyObject); - } -}; - -GameLib.D3.Physics.World.prototype.AddVehicle = function( - vehicle // note: physics.vehicle -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - vehicle.vehicleObject.addToWorld(this.worldObject); - } -}; - -GameLib.D3.Physics.World.prototype.Step = function( - timeStep -) { - if(this.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - - // todo: figure out, why this call to internal step is more stable for trimesh collisions..... - //this.worldObject.internalStep(timeStep); - //return; - - var now = performance.now() / 1000; - - if(!this.lastCallTime){ - // last call time not saved, cant guess elapsed time. Take a simple step. - this.worldObject.step(timeStep); - this.lastCallTime = now; - return; - } - - var timeSinceLastCall = now - this.lastCallTime; - - this.worldObject.step(timeStep, timeSinceLastCall); - - this.lastCallTime = now; - } -}; - -GameLib.D3.Physics.World.prototype.GetIndexedVertices = function( - triangleMeshShape -) { - - if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - - return { - vertices : triangleMeshShape.vertices, - indices : triangleMeshShape.indices - }; - - } else { - // todo: implement this for other physics engines. - return null; - } - -}; - -GameLib.D3.Physics.World.prototype.GenerateWireframeViewMesh = function( - triangleMeshShape, - normalLength, - scale, - opacity, - wireframeColor -) { - var geometryTHREE = new THREE.Geometry(); - var wireframeTHREEMesh = new THREE.Mesh - ( - geometryTHREE, - new THREE.MeshBasicMaterial({ - color: wireframeColor ? wireframeColor : 0xfefefe, - wireframe: true, - opacity: opacity ? opacity : 0.5 - }) - ); - - var data = this.GetIndexedVertices(triangleMeshShape); - - for(var i = 0, l = data.vertices.length / 3; i < l; i++) { - geometryTHREE.vertices.push(new THREE.Vector3(data.vertices[i * 3], data.vertices[i * 3 + 1], data.vertices[i * 3 + 2])); - } - - for(var i = 0, l = data.indices.length / 3; i < l; i++) { - var i0 = data.indices[i * 3]; - var i1 = data.indices[i * 3 + 1]; - var i2 = data.indices[i * 3 + 2]; - - geometryTHREE.faces.push(new THREE.Face3(i0, i1, i2)); - - // Create debug view for normals - - // Center point on the mesh itself - var centroid = new THREE.Vector3() - .add(geometryTHREE.vertices[i0]) - .add(geometryTHREE.vertices[i1]) - .add(geometryTHREE.vertices[i2]) - .divideScalar(3); - - var normal = null; - if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - var normal = new CANNON.Vec3(); - triangleMeshShape.getNormal(i, normal); - } else { - // todo: calculate the normal for v0, v1 & v2 here. - } - - var arrow = new THREE.ArrowHelper(new THREE.Vector3(normal.x, normal.y, normal.z), centroid, normalLength, new THREE.Color(normal.x, normal.y, normal.z)); - wireframeTHREEMesh.add( arrow ); - } - - wireframeTHREEMesh.scale.x = scale.x; - wireframeTHREEMesh.scale.y = scale.y; - wireframeTHREEMesh.scale.z = scale.z; - - return wireframeTHREEMesh; -}; - -GameLib.D3.Physics.World.prototype.GenerateTriangleCollisionMesh = function( - threeMesh, - mass, // default = 0 - friction, // default = 10 - createCollisionSubMeshes, // boolean. default = false - facesPerSubsection, // int. default = 0 - subsectionsToMerge // int. default = 0 -) { - var processedFaces = 0; - var facesPerSubSection = facesPerSubsection || 0; - var subMeshesToMerge = subsectionsToMerge || 0; - var totalAmtFaces = threeMesh.geometry.faces.length; - var facesToProcess = createCollisionSubMeshes ? (subMeshesToMerge * facesPerSubSection) : totalAmtFaces; - - var pairs = []; // output - - var vertices = []; - var indicies = []; - - for(var i = 0; i <= totalAmtFaces; i++) { - if(processedFaces == facesToProcess || i == totalAmtFaces) { - - var body = null; - - if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) { - - var meshShape = new CANNON.Trimesh(vertices, indicies); - meshShape.setScale(new CANNON.Vec3(threeMesh.scale.x, threeMesh.scale.y, threeMesh.scale.z)); - meshShape.updateAABB(); - meshShape.updateNormals(); - meshShape.updateEdges(); - meshShape.updateBoundingSphereRadius(); - meshShape.updateTree(); - - body = new CANNON.Body({ mass: mass ? mass : 0, friction: friction ? friction : 10 }); - body.addShape(meshShape); - - } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_AMMO) { - - } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_GOBLIN) { - - } - - pairs.push({ - threeObject : createCollisionSubMeshes ? null : threeMesh, - physicsObject : body - }); - - vertices = []; - indicies = []; - processedFaces = 0; - - if(i == totalAmtFaces) { - return pairs; - } - } - - var face = threeMesh.geometry.faces[i]; - indicies.push(indicies.length); - indicies.push(indicies.length); - indicies.push(indicies.length); - - var v0 = threeMesh.geometry.vertices[face.a]; - var v1 = threeMesh.geometry.vertices[face.b]; - var v2 = threeMesh.geometry.vertices[face.c]; - - vertices.push(v0.x, v0.y, v0.z); - vertices.push(v1.x, v1.y, v1.z); - vertices.push(v2.x, v2.y, v2.z); - - processedFaces++; - } -}; - -// ----------- -// SkyBox -// ----------- - -GameLib.D3.SkyBox = function ( - -) { - this.id = null; - this.texturesFolder = null; -}; - -GameLib.D3.SkyBox.prototype.Load = function ( - texturesFolder -) { - this.texturesFolder = texturesFolder; - this.textures = []; - this.materials = []; - this.mesh = {}; - this.scene = new THREE.Scene(); - this.textureCube = null; - - var textureLoader = new THREE.TextureLoader(); - - // this textures are used to display the skybox - this.textures.push(textureLoader.load(this.texturesFolder + "px.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "nx.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "py.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "ny.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "pz.png")); - this.textures.push(textureLoader.load(this.texturesFolder + "nz.png")); - - // assign textures to each cube face - for (var i = 0; i < 6; i ++) { - this.materials.push(new THREE.MeshBasicMaterial({ map: this.textures[i] })); - } - - // create cube geometry - this.mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshFaceMaterial(this.materials)); - this.mesh.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1)); - this.scene.add(this.mesh); - - // Load env textureCube - // this is used for reflections on meshes - // mesh.material.envMap = this.textureCube; - this.textureCube = new THREE.CubeTextureLoader().load([ - this.texturesFolder + "px.png", this.texturesFolder + "nx.png", - this.texturesFolder + "py.png", this.texturesFolder + "ny.png", - this.texturesFolder + "pz.png", this.texturesFolder + "nz.png" - ]); -}; - -GameLib.D3.SkyBox.prototype.Render = function ( - threeRenderer, - threeCamera -) { - var cameraPosition = new THREE.Vector3(threeCamera.position.x, threeCamera.position.y, threeCamera.position.z); - - threeCamera.position.set(0, 0, 0); - - var gl = threeRenderer.context; - - gl.disable(gl.DEPTH_TEST); - - threeRenderer.render(this.scene, threeCamera); - - gl.enable(gl.DEPTH_TEST); - - threeCamera.position.copy(cameraPosition); -}; - - -// --------- -// Game -// --------- -GameLib.D3.Game = function ( - -) { - this.scenes = {}; - this.physicsWorlds = []; - this.sceneToPhysicsWorldsMap = {}; -}; - -GameLib.D3.Game.prototype.AddScene = function( - scene -) { - this.scenes[scene.name] = scene; -}; - -GameLib.D3.Game.prototype.AddPhysicsWorld = function( - physicsWorld -) { - this.physicsWorlds.push(physicsWorld); -}; - -GameLib.D3.Game.prototype.LinkPhysicsWorldToScene = function( - physicsWorld, - scene -) { - this.sceneToPhysicsWorldsMap[scene.name] = this.sceneToPhysicsWorldsMap[scene.name] || []; - this.sceneToPhysicsWorldsMap[scene.name].push(physicsWorld); -}; - -GameLib.D3.Game.prototype.GetPhysicsWorldsForScene = function ( - scene -) { - return this.sceneToPhysicsWorldsMap[scene.name]; -}; - -GameLib.D3.Game.prototype.ProcessPhysics = function ( - timestep -) { - for(var s in this.sceneToPhysicsWorldsMap) { - - var physicsWorldArray = this.sceneToPhysicsWorldsMap[s]; - var scene = this.scenes[s]; - - if(scene && physicsWorldArray) { - - for(var i = 0, l = physicsWorldArray.length; i < l; i++) { - - var physicsWorld = physicsWorldArray[i]; - physicsWorld.Step(timestep); - - for(var p in physicsWorld.linkedPairs) { - var pair = physicsWorld.linkedPairs[p]; - var mesh = pair.threeMesh; - var body = pair.physicsBody; - - if(mesh) { - if(physicsWorld.engineType === GameLib.D3.Physics.Engine.TYPE_CANNON) { - - var quaternion = new THREE.Quaternion(); - quaternion.copy(body.bodyObject.quaternion); - - var quaternionCopy = quaternion.clone(); - - var position = new THREE.Vector3(); - position.copy(body.bodyObject.position); - - if(mesh.permutate) { - - if(mesh.permutate.offset) { - if(mesh.permutate.offset.quaternion) { - var offsetQuaternion = new THREE.Quaternion(); - offsetQuaternion.copy(mesh.permutate.offset.quaternion); - quaternion = quaternion.multiply(offsetQuaternion).normalize(); - } - - if(mesh.permutate.offset.position) { - var offsetPosition = new THREE.Vector3(); - offsetPosition.copy(mesh.permutate.offset.position); - //position = position.add(offsetPosition); - position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); - } - } - } - - mesh.position.copy(position); - mesh.quaternion.copy(quaternion); - } - } - } - } - } - - } -}; - -GameLib.D3.Game.prototype.LinkPair = function ( - threeMesh, - physicsBody, - physicsWorld -) { - physicsWorld.linkedPairs = physicsWorld.linkedPairs || []; - - physicsWorld.linkedPairs.push({ - threeMesh : threeMesh, - physicsBody : physicsBody - }); -}; - - -/* * * * * * * * * * - * Heightmap Tools - * * * * * * * * * */ - -GameLib.D3.HeightmapData = function ( - sizeX, - sizeY, - matrix -) { - this.sizeX = sizeX || 0; - this.sizeY = sizeY || 0; - - // 2D Array with height data - // Column-major - this.matrix = matrix || []; -}; - - -// Note: this currently only works for cannon! -GameLib.D3.GenerateThreeMeshFromHeightField = function ( - heightFieldShape - // Physics type..... -) { - - var geometry = new THREE.Geometry(); - - var v0 = new CANNON.Vec3(); - var v1 = new CANNON.Vec3(); - var v2 = new CANNON.Vec3(); - - var shape = heightFieldShape; - for (var xi = 0; xi < shape.data.length - 1; xi++) { - for (var yi = 0; yi < shape.data[xi].length - 1; yi++) { - for (var k = 0; k < 2; k++) { - shape.getConvexTrianglePillar(xi, yi, k===0); - v0.copy(shape.pillarConvex.vertices[0]); - v1.copy(shape.pillarConvex.vertices[1]); - v2.copy(shape.pillarConvex.vertices[2]); - v0.vadd(shape.pillarOffset, v0); - v1.vadd(shape.pillarOffset, v1); - v2.vadd(shape.pillarOffset, v2); - geometry.vertices.push( - new THREE.Vector3(v0.x, v0.y, v0.z), - new THREE.Vector3(v1.x, v1.y, v1.z), - new THREE.Vector3(v2.x, v2.y, v2.z) - ); - var i = geometry.vertices.length - 3; - geometry.faces.push(new THREE.Face3(i, i+1, i+2)); - } - } - } - geometry.computeBoundingSphere(); - geometry.computeFaceNormals(); - - return new THREE.Mesh(geometry, new THREE.MeshNormalMaterial({ wireframe : false, shading : THREE.SmoothShading })); -}; - -GameLib.D3.GenerateHeightmapDataFromImage = function ( - imagePath, - callback // receives HeightmapData instance as the first argument -) { - var img = new Image(); - - img.onload = function () { - - var canvas = document.createElement('canvas'); - canvas.width = img.width; - canvas.height = img.height; - - var context = canvas.getContext('2d'); - context.drawImage(img, 0, 0); - - var imgd = context.getImageData(0, 0, img.width, img.height); - var pixels = imgd.data; - - var heightList = []; - for (var i = 0, n = pixels.length; i < n; i += (4)) { - heightList.push(pixels[i]); - } - - var matrix = []; - var sizeX = img.width, - sizeY = img.height; - - for (var i = 0; i < sizeX; i++) { - matrix.push([]); - for (var j = 0; j < sizeY; j++) { - var height = (heightList[(sizeX - i) + j * sizeY] / 255) * 15; - matrix[i].push(height); - } - } - - - // todo: delete canvas here - - callback(new GameLib.D3.HeightmapData(sizeX, sizeY, matrix)); - }; - - img.src = imagePath; -}; - -if (typeof module != 'undefined') { - module.exports = GameLib; -} \ No newline at end of file diff --git a/game.js b/game.js deleted file mode 100644 index 0b724be..0000000 --- a/game.js +++ /dev/null @@ -1,24 +0,0 @@ -function Game() {} - -/** - * Games are collections of scenes and physics worlds - * @param id - * @param name - * @param path - * @param scenes THREE.Scene[] - * @param worlds GameLib.D3.Physics.World[] - * @constructor - */ -Game = function( - id, - name, - path, - scenes, - worlds -) { - this.id = id; - this.name = name; - this.path = path; - this.scenes = scenes; - this.worlds = worlds; -}; \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..fdb7e86 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,26 @@ +var gulp = require('gulp'); +var concat = require('gulp-concat'); +var sort = require('gulp-sort'); +var minify = require('gulp-minify'); + +gulp.task( + 'build', + function() { + return gulp.src('./src/game-lib-*.js') + .pipe(sort()) + .pipe(concat('game-lib.js')) + .pipe(minify({ + ext:{ + src:'-debug.js', + min:'.js' + } + })) + .pipe(gulp.dest('./build/')); + } +); + +gulp.task( + 'default', + ['build'], + function() {} +); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..9382bf4 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "gamewheel-game-lib", + "description": "Gamewheel Game Library", + "version": "0.0.1", + "dependencies": { + "gulp": "^3.9.1", + "gulp-concat": "^2.6.0", + "gulp-minify": "0.0.14", + "gulp-sort": "^2.0.0" + }, + "repository": "https://github.com/ToywheelDev/game-lib.git", + "license": "UNLICENSED" +} diff --git a/src/game-lib-a.js b/src/game-lib-a.js new file mode 100644 index 0000000..1a90a34 --- /dev/null +++ b/src/game-lib-a.js @@ -0,0 +1,7 @@ +if (typeof GameLib == 'undefined') { + function GameLib() {} +} + +if (typeof GameLib.D3 == 'undefined') { + GameLib.D3 = function(){}; +} \ No newline at end of file diff --git a/src/game-lib-bone-weight.js b/src/game-lib-bone-weight.js new file mode 100644 index 0000000..954b81f --- /dev/null +++ b/src/game-lib-bone-weight.js @@ -0,0 +1,13 @@ +/** + * BoneWeight object - associates a vertex to a bone with some weight + * @param boneIndex int + * @param weight float + * @constructor + */ +GameLib.D3.BoneWeight = function( + boneIndex, + weight +) { + this.boneIndex = boneIndex; + this.weight = weight; +}; \ No newline at end of file diff --git a/src/game-lib-bone.js b/src/game-lib-bone.js new file mode 100644 index 0000000..0e8585b --- /dev/null +++ b/src/game-lib-bone.js @@ -0,0 +1,65 @@ +/** + * Bone Superset + * @param id + * @param name string + * @param boneId + * @param childBoneIds + * @param parentBoneId + * @param quaternion + * @param position + * @param rotation + * @param scale GameLib.D3.Vector3 + * @param up + * @constructor + */ +GameLib.D3.Bone = function( + id, + boneId, + name, + childBoneIds, + parentBoneId, + quaternion, + position, + rotation, + scale, + up +) { + this.id = id; + this.name = name; + this.boneId = boneId; + + if (typeof childBoneIds == 'undefined') { + childBoneIds = []; + } + this.childBoneIds = childBoneIds; + + if (typeof parentBoneId == 'undefined') { + parentBoneId = null; + } + this.parentBoneId = parentBoneId; + + if (typeof quaternion == 'undefined') { + quaternion = new GameLib.D3.Vector4(); + } + this.quaternion = quaternion; + + if (typeof position == 'undefined') { + position = new GameLib.D3.Vector3(0,0,0); + } + this.position = position; + + if (typeof rotation == 'undefined') { + rotation = new GameLib.D3.Vector3(0,0,0); + } + this.rotation = rotation; + + if (typeof scale == 'undefined') { + scale = new GameLib.D3.Vector3(1,1,1); + } + this.scale = scale; + + if (typeof up == 'undefined') { + up = new GameLib.D3.Vector3(0,1,0); + } + this.up = up; +}; \ No newline at end of file diff --git a/src/game-lib-broadphase.js b/src/game-lib-broadphase.js new file mode 100644 index 0000000..af8aeaf --- /dev/null +++ b/src/game-lib-broadphase.js @@ -0,0 +1,34 @@ +/** + * Physics Broadphase Superset + * @param id + * @param name + * @param broadphaseType + * @constructor + */ +GameLib.D3.Broadphase = function( + id, + name, + broadphaseType +) { + this.id = id; + + if (typeof name == 'undefined') { + name = 'broadphase-' + broadphaseType; + } + this.name = name; + + if (typeof broadphaseType == 'undefined') { + console.warn('undefined broadphase type'); + throw new Error('undefined broadphase type'); + } + + this.broadphaseType = broadphaseType; +}; + +/** + * Broadphase Types + * @type {number} + */ +GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE = 0x1; +GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID = 0x2; +GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP = 0x3; \ No newline at end of file diff --git a/src/game-lib-color.js b/src/game-lib-color.js new file mode 100644 index 0000000..bf8e40e --- /dev/null +++ b/src/game-lib-color.js @@ -0,0 +1,18 @@ +/** + * Color Superset + * @param r + * @param g + * @param b + * @param a + * @constructor + */ +GameLib.D3.Color = function(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; +}; + +if (typeof module !== 'undefined') { + module.exports = GameLib.D3.Color; +} \ No newline at end of file diff --git a/src/game-lib-engine.js b/src/game-lib-engine.js new file mode 100644 index 0000000..241ed20 --- /dev/null +++ b/src/game-lib-engine.js @@ -0,0 +1,60 @@ +/** + * Engine Superset + * @param engineType + * @param instance + * @constructor + */ +GameLib.D3.Engine = function( + engineType, + instance +) { + this.engineType = engineType; + this.instance = instance; +}; + +/** + * True if CANNON physics + * @returns {boolean} + */ +GameLib.D3.Engine.prototype.isCannon = function() { + return (this.engineType == GameLib.D3.Engine.ENGINE_TYPE_CANNON) +}; + +/** + * Logs a warning and throws an error if not cannon + */ +GameLib.D3.Engine.prototype.isNotCannonThrow = function() { + if (this.engineType != GameLib.D3.Engine.ENGINE_TYPE_CANNON) { + console.warn('Only CANNON supported for this function'); + throw new Error('Only CANNON supported for this function'); + } +}; + + +/** + * True if Ammo physics + * @returns {boolean} + */ +GameLib.D3.Engine.prototype.isAmmo = function() { + return (this.engineType == GameLib.D3.Engine.ENGINE_TYPE_AMMO) +}; + +/** + * True if Goblin physics + * @returns {boolean} + */ +GameLib.D3.Engine.prototype.isGoblin = function() { + return (this.engineType == GameLib.D3.Engine.ENGINE_TYPE_GOBLIN) +}; + +/** + * Physics GameLib.D3.Engine Types + * @type {number} + */ +GameLib.D3.Engine.ENGINE_TYPE_CANNON = 0x1; +GameLib.D3.Engine.ENGINE_TYPE_AMMO = 0x2; +GameLib.D3.Engine.ENGINE_TYPE_GOBLIN = 0x3; + +if (typeof module !== 'undefined') { + module.exports = GameLib.D3.Engine; +} \ No newline at end of file diff --git a/game-lib-controls.js b/src/game-lib-fly-controls.js similarity index 89% rename from game-lib-controls.js rename to src/game-lib-fly-controls.js index 2580743..36d1c80 100644 --- a/game-lib-controls.js +++ b/src/game-lib-fly-controls.js @@ -1,6 +1,11 @@ -function Controls() {} - -Controls.FlyControls = function( +/** + * Fly Controls + * @param camera + * @param THREE + * @param canvas + * @constructor + */ +GameLib.D3.FlyControls = function( camera, THREE, canvas @@ -47,14 +52,14 @@ Controls.FlyControls = function( }; -Controls.FlyControls.prototype.onMouseWheel = function(event) { +GameLib.D3.FlyControls.prototype.onMouseWheel = function(event) { this.moveForward = true; this.applyTranslation(event.wheelDelta * 0.001); event.preventDefault(); this.moveForward = false; }; -Controls.FlyControls.prototype.onMouseDown = function(event) { +GameLib.D3.FlyControls.prototype.onMouseDown = function(event) { // if (event.button == 0) { // this.canRotate = true; @@ -70,7 +75,7 @@ Controls.FlyControls.prototype.onMouseDown = function(event) { } }; -Controls.FlyControls.prototype.onMouseUp = function(event) { +GameLib.D3.FlyControls.prototype.onMouseUp = function(event) { // if (event.button == 0) { // this.canRotate = false; @@ -86,11 +91,11 @@ Controls.FlyControls.prototype.onMouseUp = function(event) { } }; -Controls.FlyControls.prototype.applyRotation = function() { +GameLib.D3.FlyControls.prototype.applyRotation = function() { this.camera.rotation.set(this.pitch, this.yaw, 0, "YXZ"); }; -Controls.FlyControls.prototype.applyTranslation = function(deltaTime) { +GameLib.D3.FlyControls.prototype.applyTranslation = function(deltaTime) { var direction = new this.THREE.Vector3(0, 0, -1); var rotation = new this.THREE.Euler(0, 0, 0, "YXZ"); rotation.set(this.pitch, this.yaw, 0, "YXZ"); @@ -143,12 +148,12 @@ Controls.FlyControls.prototype.applyTranslation = function(deltaTime) { } }; -Controls.FlyControls.prototype.update = function(deltaTime) { +GameLib.D3.FlyControls.prototype.update = function(deltaTime) { this.applyRotation(); this.applyTranslation(deltaTime); }; -Controls.FlyControls.prototype.onMouseMove = function ( event ) { +GameLib.D3.FlyControls.prototype.onMouseMove = function ( event ) { if (this.canRotate) { var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; @@ -158,7 +163,7 @@ Controls.FlyControls.prototype.onMouseMove = function ( event ) { } }; -Controls.FlyControls.prototype.onKeyDown = function ( event ) { +GameLib.D3.FlyControls.prototype.onKeyDown = function ( event ) { switch ( event.keyCode ) { case 87: // w @@ -187,7 +192,7 @@ Controls.FlyControls.prototype.onKeyDown = function ( event ) { } }; -Controls.FlyControls.prototype.onKeyUp = function ( event ) { +GameLib.D3.FlyControls.prototype.onKeyUp = function ( event ) { switch ( event.keyCode ) { case 38: // up @@ -218,8 +223,4 @@ Controls.FlyControls.prototype.onKeyUp = function ( event ) { this.moveDown = false; break; } -}; - -if (typeof module !== 'undefined') { - module.exports = Controls; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/game-lib-game.js b/src/game-lib-game.js new file mode 100644 index 0000000..e40cc81 --- /dev/null +++ b/src/game-lib-game.js @@ -0,0 +1,106 @@ +GameLib.D3.Game = function ( + +) { + this.scenes = {}; + this.physicsWorlds = []; + this.sceneToPhysicsWorldsMap = {}; +}; + +GameLib.D3.Game.prototype.AddScene = function( + scene +) { + this.scenes[scene.name] = scene; +}; + +GameLib.D3.Game.prototype.AddPhysicsWorld = function( + physicsWorld +) { + this.physicsWorlds.push(physicsWorld); +}; + +GameLib.D3.Game.prototype.LinkPhysicsWorldToScene = function( + physicsWorld, + scene +) { + this.sceneToPhysicsWorldsMap[scene.name] = this.sceneToPhysicsWorldsMap[scene.name] || []; + this.sceneToPhysicsWorldsMap[scene.name].push(physicsWorld); +}; + +GameLib.D3.Game.prototype.GetPhysicsWorldsForScene = function ( + scene +) { + return this.sceneToPhysicsWorldsMap[scene.name]; +}; + +GameLib.D3.Game.prototype.ProcessPhysics = function ( + timestep +) { + for(var s in this.sceneToPhysicsWorldsMap) { + + var physicsWorldArray = this.sceneToPhysicsWorldsMap[s]; + var scene = this.scenes[s]; + + if(scene && physicsWorldArray) { + + for(var i = 0, l = physicsWorldArray.length; i < l; i++) { + + var physicsWorld = physicsWorldArray[i]; + physicsWorld.Step(timestep); + + for(var p in physicsWorld.linkedPairs) { + var pair = physicsWorld.linkedPairs[p]; + var mesh = pair.threeMesh; + var body = pair.physicsBody; + + if(mesh) { + if(physicsWorld.engineType === GameLib.D3.Physics.TYPE_CANNON) { + + var quaternion = new THREE.Quaternion(); + quaternion.copy(body.rigidBodyInstance.quaternion); + + var quaternionCopy = quaternion.clone(); + + var position = new THREE.Vector3(); + position.copy(body.rigidBodyInstance.position); + + if(mesh.permutate) { + + if(mesh.permutate.offset) { + if(mesh.permutate.offset.quaternion) { + var offsetQuaternion = new THREE.Quaternion(); + offsetQuaternion.copy(mesh.permutate.offset.quaternion); + quaternion = quaternion.multiply(offsetQuaternion).normalize(); + } + + if(mesh.permutate.offset.position) { + var offsetPosition = new THREE.Vector3(); + offsetPosition.copy(mesh.permutate.offset.position); + //position = position.add(offsetPosition); + position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); + } + } + } + + mesh.position.copy(position); + mesh.quaternion.copy(quaternion); + } + } + } + } + } + + } +}; + +GameLib.D3.Game.prototype.LinkPair = function ( + threeMesh, + physicsBody, + physicsWorld +) { + physicsWorld.linkedPairs = physicsWorld.linkedPairs || []; + + physicsWorld.linkedPairs.push({ + threeMesh : threeMesh, + physicsBody : physicsBody + }); +}; \ No newline at end of file diff --git a/src/game-lib-heightmap.js b/src/game-lib-heightmap.js new file mode 100644 index 0000000..a08ca63 --- /dev/null +++ b/src/game-lib-heightmap.js @@ -0,0 +1,95 @@ +GameLib.D3.HeightmapData = function ( + sizeX, + sizeY, + matrix +) { + this.sizeX = sizeX || 0; + this.sizeY = sizeY || 0; + + // 2D Array with height data + // Column-major + this.matrix = matrix || []; +}; + +// Note: this currently only works for cannon! +GameLib.D3.GenerateThreeMeshFromHeightField = function ( + heightFieldShape + // Physics type..... +) { + + var geometry = new THREE.Geometry(); + + var v0 = new this.physics.CANNON.Vec3(); + var v1 = new this.physics.CANNON.Vec3(); + var v2 = new this.physics.CANNON.Vec3(); + + var shape = heightFieldShape; + for (var xi = 0; xi < shape.data.length - 1; xi++) { + for (var yi = 0; yi < shape.data[xi].length - 1; yi++) { + for (var k = 0; k < 2; k++) { + shape.getConvexTrianglePillar(xi, yi, k===0); + v0.copy(shape.pillarConvex.vertices[0]); + v1.copy(shape.pillarConvex.vertices[1]); + v2.copy(shape.pillarConvex.vertices[2]); + v0.vadd(shape.pillarOffset, v0); + v1.vadd(shape.pillarOffset, v1); + v2.vadd(shape.pillarOffset, v2); + geometry.vertices.push( + new THREE.Vector3(v0.x, v0.y, v0.z), + new THREE.Vector3(v1.x, v1.y, v1.z), + new THREE.Vector3(v2.x, v2.y, v2.z) + ); + var i = geometry.vertices.length - 3; + geometry.faces.push(new THREE.Face3(i, i+1, i+2)); + } + } + } + geometry.computeBoundingSphere(); + geometry.computeFaceNormals(); + + return new THREE.Mesh(geometry, new THREE.MeshNormalMaterial({ wireframe : false, shading : THREE.SmoothShading })); +}; + +GameLib.D3.GenerateHeightmapDataFromImage = function ( + imagePath, + callback // receives HeightmapData instance as the first argument +) { + var img = new Image(); + + img.onload = function () { + + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + + var context = canvas.getContext('2d'); + context.drawImage(img, 0, 0); + + var imgd = context.getImageData(0, 0, img.width, img.height); + var pixels = imgd.data; + + var heightList = []; + for (var i = 0, n = pixels.length; i < n; i += (4)) { + heightList.push(pixels[i]); + } + + var matrix = []; + var sizeX = img.width, + sizeY = img.height; + + for (var i = 0; i < sizeX; i++) { + matrix.push([]); + for (var j = 0; j < sizeY; j++) { + var height = (heightList[(sizeX - i) + j * sizeY] / 255) * 15; + matrix[i].push(height); + } + } + + + // todo: delete canvas here + + callback(new GameLib.D3.HeightmapData(sizeX, sizeY, matrix)); + }; + + img.src = imagePath; +}; \ No newline at end of file diff --git a/src/game-lib-image.js b/src/game-lib-image.js new file mode 100644 index 0000000..e9e82d9 --- /dev/null +++ b/src/game-lib-image.js @@ -0,0 +1,45 @@ +/** + * Image + * @param id + * @param textureLink + * @param filename + * @param size + * @param contentType + * @constructor + */ +GameLib.D3.Image = function( + id, + textureLink, + filename, + size, + contentType +) { + this.id = id; + + this.filename = filename; + + this.textureLink = textureLink; + + if (typeof size == 'undefined') { + size = 0; + } + this.size = size; + + if (typeof contentType == 'undefined') { + + contentType = 'application/octet-stream'; + + if (this.filename.match(/(png)$/i)) { + contentType = 'image/png'; + } + + if (this.filename.match(/(jpg|jpeg)$/i)) { + contentType = 'image/jpeg'; + } + + if (this.filename.match(/(gif)$/i)) { + contentType = 'image/gif'; + } + } + this.contentType = contentType; +}; \ No newline at end of file diff --git a/src/game-lib-light.js b/src/game-lib-light.js new file mode 100644 index 0000000..4a66fc3 --- /dev/null +++ b/src/game-lib-light.js @@ -0,0 +1,92 @@ +/** + * Light Superset + * @param id + * @param lightType + * @param name + * @param color + * @param intensity + * @param position + * @param targetPosition + * @param quaternion + * @param rotation + * @param scale + * @param distance + * @param decay + * @param power + * @param angle + * @param penumbra + * @constructor + */ +GameLib.D3.Light = function( + id, + lightType, + name, + color, + intensity, + position, + targetPosition, + quaternion, + rotation, + scale, + distance, + decay, + power, + angle, + penumbra +) { + this.id = id; + this.lightType = lightType; + this.name = name; + this.color = color; + this.intensity = intensity; + + if (typeof position == 'undefined') { + position = new GameLib.D3.Vector3(0,0,0); + } + this.position = position; + + if (typeof targetPosition == 'undefined') { + targetPosition = new GameLib.D3.Vector3(0,0,0); + } + this.targetPosition = targetPosition; + + if (typeof quaternion == 'undefined'){ + quaternion = new GameLib.D3.Vector4(); + } + this.quaternion = quaternion; + + if (typeof rotation == 'undefined'){ + rotation = new GameLib.D3.Vector3(0,0,0); + } + this.rotation = rotation; + + if (typeof scale == 'undefined'){ + scale = new GameLib.D3.Vector3(1,1,1); + } + this.scale = scale; + + if (typeof distance == 'undefined'){ + distance = 0; + } + this.distance = distance; + + if (typeof decay == 'undefined'){ + decay = 1; + } + this.decay = decay; + + if (typeof power == 'undefined'){ + power = 4 * Math.PI; + } + this.power = power; + + if (typeof angle == 'undefined'){ + angle = Math.PI / 3; + } + this.angle = angle; + + if (typeof penumbra == 'undefined'){ + penumbra = 0; + } + this.penumbra = penumbra; +}; \ No newline at end of file diff --git a/src/game-lib-material.js b/src/game-lib-material.js new file mode 100644 index 0000000..426c7be --- /dev/null +++ b/src/game-lib-material.js @@ -0,0 +1,679 @@ +/** + * Material Superset + * @param id + * @param name + * @param materialType + * @param opacity + * @param side + * @param transparent + * @param maps + * @param specular + * @param lightMapIntensity + * @param aoMapIntensity + * @param color + * @param emissive + * @param emissiveIntensity + * @param combine + * @param shininess + * @param reflectivity + * @param refractionRatio + * @param fog + * @param wireframe + * @param wireframeLineWidth + * @param wireframeLineCap + * @param wireframeLineJoin + * @param vertexColors + * @param skinning + * @param morphTargets + * @param morphNormals + * @param lineWidth + * @param lineCap + * @param lineJoin + * @param dashSize + * @param gapWidth + * @param blending + * @param blendSrc + * @param blendDst + * @param blendEquation + * @param depthTest + * @param depthFunc + * @param depthWrite + * @param polygonOffset + * @param polygonOffsetFactor + * @param polygonOffsetUnits + * @param alphaTest + * @param clippingPlanes + * @param clipShadows + * @param visible + * @param overdraw + * @param shading + * @param bumpScale + * @param normalScale + * @param displacementScale + * @param displacementBias + * @param roughness + * @param metalness + * @param pointSize + * @param pointSizeAttenuation + * @param spriteRotation + * @param envMapIntensity + * @constructor + */ +GameLib.D3.Material = function( + id, + name, + materialType, + opacity, + side, + transparent, + maps, + specular, + lightMapIntensity, + aoMapIntensity, + color, + emissive, + emissiveIntensity, + combine, + shininess, + reflectivity, + refractionRatio, + fog, + wireframe, + wireframeLineWidth, + wireframeLineCap, + wireframeLineJoin, + vertexColors, + skinning, + morphTargets, + morphNormals, + lineWidth, + lineCap, + lineJoin, + dashSize, + gapWidth, + blending, + blendSrc, + blendDst, + blendEquation, + depthTest, + depthFunc, + depthWrite, + polygonOffset, + polygonOffsetFactor, + polygonOffsetUnits, + alphaTest, + clippingPlanes, + clipShadows, + visible, + overdraw, + shading, + bumpScale, + normalScale, + displacementScale, + displacementBias, + roughness, + metalness, + pointSize, + pointSizeAttenuation, + spriteRotation, + envMapIntensity +) { + this.id = id; + this.name = name; + if (typeof materialType == 'undefined') { + materialType = GameLib.D3.Material.TYPE_MESH_STANDARD; + } + this.materialType = materialType; + + if (typeof opacity == 'undefined') { + opacity = 1.0; + } + this.opacity = opacity; + + if (typeof side == 'undefined') { + side = GameLib.D3.Material.TYPE_FRONT_SIDE; + } + this.side = side; + + if (typeof transparent == 'undefined') { + transparent = false; + } + this.transparent = transparent; + + if (typeof maps == 'undefined') { + maps = { + alpha: null, + ao: null, + bump: null, + diffuse: null, + displacement: null, + emissive: null, + environment: null, + light: null, + metalness: null, + normal: null, + roughness: null, + specular: null + }; + } + this.maps = maps; + + if (typeof specular == 'undefined') { + specular = new GameLib.D3.Color(0.06, 0.06, 0.06, 0.06); + } + this.specular = specular; + + if (typeof lightMapIntensity == 'undefined') { + lightMapIntensity = 1; + } + this.lightMapIntensity = lightMapIntensity; + + if (typeof aoMapIntensity == 'undefined') { + aoMapIntensity = 1; + } + this.aoMapIntensity = aoMapIntensity; + + if (typeof color == 'undefined') { + color = new GameLib.D3.Color(1, 1, 1, 1) + } + this.color = color; + + if (typeof emissive == 'undefined') { + emissive = new GameLib.D3.Color(0, 0, 0, 0); + } + this.emissive = emissive; + + if (typeof emissiveIntensity == 'undefined') { + emissiveIntensity = 1; + } + this.emissiveIntensity = emissiveIntensity; + + if (typeof combine == 'undefined') { + combine = GameLib.D3.Material.TYPE_MULTIPLY_OPERATION; + } + this.combine = combine; + + if (typeof shininess == 'undefined') { + shininess = 30; + } + this.shininess = shininess; + + if (typeof reflectivity == 'undefined') { + reflectivity = 1; + } + this.reflectivity = reflectivity; + + if (typeof refractionRatio == 'undefined') { + refractionRatio = 0.98; + } + this.refractionRatio = refractionRatio; + + if (typeof fog == 'undefined') { + fog = true; + } + this.fog = fog; + + if (typeof wireframe == 'undefined') { + wireframe = false; + } + this.wireframe = wireframe; + + if (typeof wireframeLineWidth == 'undefined') { + wireframeLineWidth = 1; + } + this.wireframeLineWidth = wireframeLineWidth; + + if (typeof wireframeLineCap == 'undefined') { + wireframeLineCap = 'round'; + } + this.wireframeLineCap = wireframeLineCap; + + if (typeof wireframeLineJoin == 'undefined') { + wireframeLineJoin = 'round'; + } + this.wireframeLineJoin = wireframeLineJoin; + + if (typeof vertexColors == 'undefined') { + vertexColors = GameLib.D3.Material.TYPE_NO_COLORS; + } + this.vertexColors = vertexColors; + + if (typeof skinning == 'undefined') { + skinning = false; + } + this.skinning = skinning; + + if (typeof morphTargets == 'undefined') { + morphTargets = false; + } + this.morphTargets = morphTargets; + + if (typeof morphNormals == 'undefined') { + morphNormals = false; + } + this.morphNormals = morphNormals; + + if (typeof overdraw == 'undefined') { + overdraw = 0; + } + this.overdraw = overdraw; + + if (typeof lineWidth == 'undefined') { + lineWidth = 1; + } + this.lineWidth = lineWidth; + + if (typeof lineCap == 'undefined') { + lineCap = 'round'; + } + this.lineCap = lineCap; + + if (typeof lineJoin == 'undefined') { + lineJoin = 'round'; + } + this.lineJoin = lineJoin; + + if (typeof dashSize == 'undefined') { + dashSize = 3; + } + this.dashSize = dashSize; + + if (typeof gapWidth == 'undefined') { + gapWidth = 1; + } + this.gapWidth = gapWidth; + + if (typeof blending == 'undefined') { + blending = GameLib.D3.Material.TYPE_NORMAL_BLENDING; + } + this.blending = blending; + + if (typeof blendSrc == 'undefined') { + blendSrc = GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR; + } + this.blendSrc = blendSrc; + + if (typeof blendDst == 'undefined') { + blendDst = GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR; + } + this.blendDst = blendDst; + + if (typeof blendEquation == 'undefined') { + blendEquation = GameLib.D3.Material.TYPE_ADD_EQUATION; + } + this.blendEquation = blendEquation; + + if (typeof depthTest == 'undefined') { + depthTest = true; + } + this.depthTest = depthTest; + + if (typeof depthFunc == 'undefined') { + depthFunc = GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH; + } + this.depthFunc = depthFunc; + + if (typeof depthWrite == 'undefined') { + depthWrite = true; + } + this.depthWrite = depthWrite; + + if (typeof polygonOffset == 'undefined') { + polygonOffset = false; + } + this.polygonOffset = polygonOffset; + + if (typeof polygonOffsetFactor == 'undefined') { + polygonOffsetFactor = 1; + } + this.polygonOffsetFactor = polygonOffsetFactor; + + if (typeof polygonOffsetUnits == 'undefined') { + polygonOffsetUnits = 1; + } + this.polygonOffsetUnits = polygonOffsetUnits; + + if (typeof alphaTest == 'undefined') { + alphaTest = 0; + } + this.alphaTest = alphaTest; + + if (typeof clippingPlanes == 'undefined') { + clippingPlanes = []; + } + this.clippingPlanes = clippingPlanes; + + if (typeof clipShadows == 'undefined') { + clipShadows = false; + } + this.clipShadows = clipShadows; + + if (typeof visible == 'undefined') { + visible = true; + } + this.visible = visible; + + if (typeof shading == 'undefined') { + shading = GameLib.D3.Material.TYPE_FLAT_SHADING; + } + this.shading = shading; + + if (typeof bumpScale == 'undefined') { + bumpScale = 1; + } + this.bumpScale = bumpScale; + + if (typeof normalScale == 'undefined') { + normalScale = 1; + } + this.normalScale = normalScale; + + if (typeof displacementScale == 'undefined') { + displacementScale = 1; + } + this.displacementScale = displacementScale; + + if (typeof displacementBias == 'undefined') { + displacementBias = 0; + } + this.displacementBias = displacementBias; + + if (typeof roughness == 'undefined') { + roughness = 0.5; + } + this.roughness = roughness; + + if (typeof metalness == 'undefined') { + metalness = 0.5; + } + this.metalness = metalness; + + if (typeof pointSize == 'undefined') { + pointSize = 1; + } + this.pointSize = pointSize; + + if (typeof pointSizeAttenuation == 'undefined') { + pointSizeAttenuation = true; + } + this.pointSizeAttenuation = pointSizeAttenuation; + + if (typeof spriteRotation == 'undefined') { + spriteRotation = 0; + } + this.spriteRotation = spriteRotation; + + if (typeof envMapIntensity == 'undefined') { + envMapIntensity = 1.0; + } + this.envMapIntensity = envMapIntensity; + +}; + +/** + * Combine Method + * @type {number} + */ +GameLib.D3.Material.TYPE_MULTIPLY_OPERATION = 0; +GameLib.D3.Material.TYPE_MIX_OPERATION = 1; +GameLib.D3.Material.TYPE_ADD_OPERATION = 2; + +/** + * Vertex Color Mode + * @type {number} + */ +GameLib.D3.Material.TYPE_NO_COLORS = 0; +GameLib.D3.Material.TYPE_FACE_COLORS = 1; +GameLib.D3.Material.TYPE_VERTEX_COLORS = 2; + +/** + * Blending Mode + * @type {number} + */ +GameLib.D3.Material.TYPE_NORMAL_BLENDING = 1; +GameLib.D3.Material.TYPE_ADDITIVE_BLENDING = 2; +GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING = 3; +GameLib.D3.Material.TYPE_MULTIPLY_BLENDING = 4; +GameLib.D3.Material.TYPE_CUSTOM_BLENDING = 5; + +/** + * Blend Source and Destination + * @type {number} + */ +GameLib.D3.Material.TYPE_ZERO_FACTOR = 200; +GameLib.D3.Material.TYPE_ONE_FACTOR = 201; +GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR = 202; +GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR = 203; +GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR = 204; +GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR = 205; +GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR = 206; +GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR = 207; +GameLib.D3.Material.TYPE_DST_COLOR_FACTOR = 208; +GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR = 209; +GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR = 210; + +/** + * Blend Operation + * @type {number} + */ +GameLib.D3.Material.TYPE_ADD_EQUATION = 100; +GameLib.D3.Material.TYPE_SUBTRACT_EQUATION = 101; +GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION = 102; +GameLib.D3.Material.TYPE_MIN_EQUATION = 103; +GameLib.D3.Material.TYPE_MAX_EQUATION = 104; + +/** + * Depth Function + * @type {number} + */ +GameLib.D3.Material.TYPE_NEVER_DEPTH = 0; +GameLib.D3.Material.TYPE_ALWAYS_DEPTH = 1; +GameLib.D3.Material.TYPE_LESS_DEPTH = 2; +GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH = 3; +GameLib.D3.Material.TYPE_EQUAL_DEPTH = 4; +GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH = 5; +GameLib.D3.Material.TYPE_GREATER_DEPTH = 6; +GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH = 7; + +/** + * Culling Mode + * @type {number} + */ +GameLib.D3.Material.TYPE_FRONT_SIDE = 0; +GameLib.D3.Material.TYPE_BACK_SIDE = 1; +GameLib.D3.Material.TYPE_DOUBLE_SIDE = 2; + +/** + * Shading Type + * @type {number} + */ +GameLib.D3.Material.TYPE_FLAT_SHADING = 1; +GameLib.D3.Material.TYPE_SMOOTH_SHADING = 2; + +/** + * Material Type + * @type {string} + */ +GameLib.D3.Material.TYPE_LINE_BASIC = "LineBasicMaterial"; +GameLib.D3.Material.TYPE_LINE_DASHED = "LineDashedMaterial"; +GameLib.D3.Material.TYPE_MESH_BASIC = "MeshBasicMaterial"; +GameLib.D3.Material.TYPE_MESH_DEPTH = "MeshDepthMaterial"; +GameLib.D3.Material.TYPE_MESH_LAMBERT = "MeshLambertMaterial"; +GameLib.D3.Material.TYPE_MESH_NORMAL = "MeshNormalMaterial"; +GameLib.D3.Material.TYPE_MESH_PHONG = "MeshPhongMaterial"; +GameLib.D3.Material.TYPE_MESH_STANDARD = "MeshStandardMaterial"; +GameLib.D3.Material.TYPE_POINTS = "PointsMaterial"; +GameLib.D3.Material.TYPE_SPRITE = "SpriteMaterial"; +GameLib.D3.Material.TYPE_MULTI_MATERIAL= "MultiMaterial"; + +/** + * Creates a this.THREE.Material from a GameLib.D3.Material + * @param blenderMaterial GameLib.D3.Material + */ +GameLib.D3.prototype.createThreeMaterial = function(blenderMaterial) { + + var defer = this.Q.defer(); + + var threeMaterial = null; + + var blenderMaps = []; + + if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) { + + threeMaterial = new this.THREE.MeshStandardMaterial({ + name: blenderMaterial.name, + opacity: blenderMaterial.opacity, + transparent: blenderMaterial.transparent, + blending: blenderMaterial.blending, + blendSrc: blenderMaterial.blendSrc, + blendDst: blenderMaterial.blendDst, + blendEquation: blenderMaterial.blendEquation, + depthTest: blenderMaterial.depthTest, + depthFunc: blenderMaterial.depthFunc, + depthWrite: blenderMaterial.depthWrite, + polygonOffset: blenderMaterial.polygonOffset, + polygonOffsetFactor: blenderMaterial.polygonOffsetFactor, + polygonOffsetUnits: blenderMaterial.polygonOffsetUnits, + alphaTest: blenderMaterial.alphaTest, + clippingPlanes: blenderMaterial.clippingPlanes, + clipShadows: blenderMaterial.clipShadows, + overdraw: blenderMaterial.overdraw, + visible: blenderMaterial.visible, + side: blenderMaterial.side, + color: new this.THREE.Color( + blenderMaterial.color.r, + blenderMaterial.color.g, + blenderMaterial.color.b + ), + roughness: blenderMaterial.roughness, + metalness: blenderMaterial.metalness, + lightMapIntensity: blenderMaterial.lightMapIntensity, + aoMapIntensity: blenderMaterial.aoMapIntensity, + emissive: new this.THREE.Color( + blenderMaterial.emissive.r, + blenderMaterial.emissive.g, + blenderMaterial.emissive.b + ), + emissiveIntensity: blenderMaterial.emissiveIntensity, + bumpScale: blenderMaterial.bumpScale, + normalScale: blenderMaterial.normalScale, + displacementScale: blenderMaterial.displacementScale, + refractionRatio: blenderMaterial.refractionRatio, + fog: blenderMaterial.fog, + shading: blenderMaterial.shading, + wireframe: blenderMaterial.wireframe, + wireframeLinewidth: blenderMaterial.wireframeLineWidth, + wireframeLinecap: blenderMaterial.wireframeLineCap, + wireframeLinejoin: blenderMaterial.wireframeLineJoin, + vertexColors: blenderMaterial.vertexColors, + skinning: blenderMaterial.skinning, + morphTargets: blenderMaterial.morphTargets, + morphNormals: blenderMaterial.morphNormals + }); + + blenderMaps.push( + 'diffuse', + 'light', + 'ao', + 'emissive', + 'bump', + 'normal', + 'displacement', + 'roughness', + 'metalness', + 'alpha', + 'environment' + ); + } else if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) { + + threeMaterial = new this.THREE.MeshPhongMaterial({ + name: blenderMaterial.name, + opacity: blenderMaterial.opacity, + transparent: blenderMaterial.transparent, + blending: blenderMaterial.blending, + blendSrc: blenderMaterial.blendSrc, + blendDst: blenderMaterial.blendDst, + blendEquation: blenderMaterial.blendEquation, + depthTest: blenderMaterial.depthTest, + depthFunc: blenderMaterial.depthFunc, + depthWrite: blenderMaterial.depthWrite, + polygonOffset: blenderMaterial.polygonOffset, + polygonOffsetFactor: blenderMaterial.polygonOffsetFactor, + polygonOffsetUnits: blenderMaterial.polygonOffsetUnits, + alphaTest: blenderMaterial.alphaTest, + clippingPlanes: blenderMaterial.clippingPlanes, + clipShadows: blenderMaterial.clipShadows, + overdraw: blenderMaterial.overdraw, + visible: blenderMaterial.visible, + side: blenderMaterial.side, + color: new this.THREE.Color( + blenderMaterial.color.r, + blenderMaterial.color.g, + blenderMaterial.color.b + ), + specular: new this.THREE.Color( + blenderMaterial.specular.r, + blenderMaterial.specular.g, + blenderMaterial.specular.b + ), + shininess: blenderMaterial.shininess, + lightMapIntensity: blenderMaterial.lightMapIntensity, + aoMapIntensity: blenderMaterial.aoMapIntensity, + emissive: new this.THREE.Color( + blenderMaterial.emissive.r, + blenderMaterial.emissive.g, + blenderMaterial.emissive.b + ), + emissiveIntensity: blenderMaterial.emissiveIntensity, + bumpScale: blenderMaterial.bumpScale, + normalScale: blenderMaterial.normalScale, + displacementScale: blenderMaterial.displacementScale, + combine: blenderMaterial.combine, + refractionRatio: blenderMaterial.refractionRatio, + fog: blenderMaterial.fog, + shading: blenderMaterial.shading, + wireframe: blenderMaterial.wireframe, + wireframeLinewidth: blenderMaterial.wireframeLineWidth, + wireframeLinecap: blenderMaterial.wireframeLineCap, + wireframeLinejoin: blenderMaterial.wireframeLineJoin, + vertexColors: blenderMaterial.vertexColors, + skinning: blenderMaterial.skinning, + morphTargets: blenderMaterial.morphTargets, + morphNormals: blenderMaterial.morphNormals + }); + + blenderMaps.push( + 'diffuse', + 'light', + 'ao', + 'emissive', + 'bump', + 'normal', + 'displacement', + 'specular', + 'alpha', + 'environment' + ); + + } else { + console.log("material type is not implemented yet: " + blenderMaterial.materialType + " - material indexes could be screwed up"); + } + + if (blenderMaps.length > 0) { + var textureMaps = this.loadMaps(blenderMaterial, blenderMaps, threeMaterial); + Q.all(textureMaps).then( + function(){ + defer.resolve(threeMaterial); + } + ).catch( + function(error){ + console.log(error); + defer.reject(error); + } + ) + } else { + defer.resolve(threeMaterial); + } + + return defer.promise; +}; \ No newline at end of file diff --git a/src/game-lib-matrix-3.js b/src/game-lib-matrix-3.js new file mode 100644 index 0000000..e5a0c7c --- /dev/null +++ b/src/game-lib-matrix-3.js @@ -0,0 +1,37 @@ +/** + * Matrix 3 Maths + * @param row0 GameLib.D3.Vector3 + * @param row1 GameLib.D3.Vector3 + * @param row2 GameLib.D3.Vector3 + * @constructor + */ +GameLib.D3.Matrix3 = function( + row0, + row1, + row2 +) { + this.identity(); + + if (row0) { + this.rows[0] = row0; + } + + if (row1) { + this.rows[1] = row1; + } + + if (row2) { + this.rows[2] = row2; + } +}; + +/** + * Set matrix to identity + */ +GameLib.D3.Matrix3.prototype.identity = function () { + this.rows = [ + new GameLib.D3.Vector4(1, 0, 0), + new GameLib.D3.Vector4(0, 1, 0), + new GameLib.D3.Vector4(0, 0, 1) + ]; +}; \ No newline at end of file diff --git a/src/game-lib-matrix-4.js b/src/game-lib-matrix-4.js new file mode 100644 index 0000000..9b43237 --- /dev/null +++ b/src/game-lib-matrix-4.js @@ -0,0 +1,173 @@ +GameLib.D3.Matrix4 = function( + row0, + row1, + row2, + row3 +) { + + this.identity(); + + if (row0) { + this.rows[0] = row0; + } + + if (row1) { + this.rows[1] = row1; + } + + if (row2) { + this.rows[2] = row2; + } + + if (row3) { + this.rows[3] = row3; + } +}; + +GameLib.D3.Matrix4.prototype.rotationMatrixX = function (radians) { + this.identity(); + this.rows[1] = new GameLib.D3.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0); + this.rows[2] = new GameLib.D3.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.Vector4( + Math.cos(radians), + 0, + Math.sin(radians), + 0 + ); + this.rows[2] = new GameLib.D3.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.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0); + this.rows[1] = new GameLib.D3.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.Vector4) { + return new GameLib.D3.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.Vector3) { + return new GameLib.D3.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.Vector4(1, 0, 0, 0), + new GameLib.D3.Vector4(0, 1, 0, 0), + new GameLib.D3.Vector4(0, 0, 1, 0), + new GameLib.D3.Vector4(0, 0, 0, 1) + ]; +}; + +GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) { + + var pv = new GameLib.D3.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; + + // te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; + // te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; + // te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; + + + // var matrix4 = new Matrix4(); + // + // matrix4.rows[0] = side.negative(); + // matrix4.rows[1] = _up; + // matrix4.rows[2] = forward; + + // + // matrix4.setColumn(0, side.negative()); + // matrix4.setColumn(1, _up); + // matrix4.setColumn(2, forward); + + //return matrix4; + + // return new Matrix4( + // new Vector4( + // side.x, + // side.y, + // side.z, + // side.negative().dot(position) + // ), + // new Vector4( + // _up.x, + // _up.y, + // _up.z, + // _up.negative().dot(position) + // ), + // new Vector4( + // forward.negative().x, + // forward.negative().y, + // forward.negative().z, + // forward.dot(position) + // ) + // ) +}; diff --git a/src/game-lib-mesh.js b/src/game-lib-mesh.js new file mode 100644 index 0000000..a557188 --- /dev/null +++ b/src/game-lib-mesh.js @@ -0,0 +1,539 @@ +/** + * Mesh Superset + * @param id + * @param path + * @param name + * @param meshType + * @param vertices + * @param faces + * @param skeleton + * @param faceVertexUvs + * @param skinIndices + * @param skinWeights + * @param materials + * @param position + * @param quaternion + * @param rotation + * @param scale + * @param up + * @param physics + * @param parentMeshId + * @param parentSceneId + * @param rawData + * @constructor + */ +GameLib.D3.Mesh = function( + id, + path, + name, + meshType, + vertices, + faces, + skeleton, + faceVertexUvs, + skinIndices, + skinWeights, + materials, + position, + quaternion, + rotation, + scale, + up, + physics, + parentMeshId, + parentSceneId, + rawData +) { + this.id = id; + this.path = path; + this.name = name; + this.meshType = meshType; + this.vertices = vertices; + this.faces = faces; + + if (typeof skeleton == 'undefined') { + skeleton = null; + } + this.skeleton = skeleton; + + if (typeof faceVertexUvs == 'undefined') { + faceVertexUvs = []; + } + this.faceVertexUvs = faceVertexUvs; + + if (typeof skinIndices == 'undefined') { + skinIndices = []; + } + this.skinIndices = skinIndices; + + if (typeof skinWeights == 'undefined') { + skinWeights = []; + } + this.skinWeights = skinWeights; + + if (typeof materials == 'undefined') { + materials = []; + } + this.materials = materials; + + if (typeof position == 'undefined') { + position = new GameLib.D3.Vector3(0,0,0); + } + this.position = position; + + if (typeof quaternion == 'undefined') { + new GameLib.D3.Vector4(); + } + this.quaternion = quaternion; + + if (typeof rotation == 'undefined') { + rotation = new GameLib.D3.Vector3(0,0,0); + } + this.rotation = rotation; + + if (typeof scale == 'undefined') { + scale = new GameLib.D3.Vector3(1,1,1); + } + this.scale = scale; + + if (typeof up == 'undefined') { + up = new GameLib.D3.Vector3(0,1,0); + } + this.up = up; + + this.physics = physics; + + this.parentMeshId = parentMeshId; + + this.parentSceneId = parentSceneId; + + this.rawData = null;// rawData; +}; + + +/** + * Mesh Type + * @type {number} + */ +GameLib.D3.Mesh.TYPE_NORMAL = 0; +GameLib.D3.Mesh.TYPE_SKINNED = 1; + + +/** + * Creates a THREE Mesh from GameLib.D3.Mesh + * @param gameLibMesh + * @param threeGeometry + * @param threeMaterial + * @returns {*} + */ +GameLib.D3.prototype.createThreeMesh = function(gameLibMesh, threeGeometry, threeMaterial) { + + var threeMesh = null; + + if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) { + threeMesh = new this.THREE.Mesh(threeGeometry, threeMaterial); + } + + if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) { + + var bones = gameLibMesh.skeleton.bones; + + var skinIndices = gameLibMesh.skinIndices; + + var skinWeights = gameLibMesh.skinWeights; + + var threeBones = []; + + for (var bi = 0; bi < bones.length; bi++) { + + var bone = new this.THREE.Bone(); + + bone.name = bones[bi].name; + + bone.position.x = bones[bi].position.x; + bone.position.y = bones[bi].position.y; + bone.position.z = bones[bi].position.z; + + bone.rotation.x = bones[bi].rotation.x; + bone.rotation.y = bones[bi].rotation.y; + bone.rotation.z = bones[bi].rotation.z; + + bone.quaternion.x = bones[bi].quaternion.x; + bone.quaternion.y = bones[bi].quaternion.y; + bone.quaternion.z = bones[bi].quaternion.z; + bone.quaternion.w = bones[bi].quaternion.w; + + bone.scale.x = bones[bi].scale.x; + bone.scale.y = bones[bi].scale.y; + bone.scale.z = bones[bi].scale.z; + + bone.up.x = bones[bi].up.x; + bone.up.y = bones[bi].up.y; + bone.up.z = bones[bi].up.z; + + threeBones.push(bone); + } + + /** + * Setup the bone relationships + */ + for (var br = 0; br < bones.length; br++) { + for (var cbi = 0; cbi < bones[br].childBoneIds.length; cbi++) { + threeBones[br].add(threeBones[bones[br].childBoneIds[cbi]]); + } + } + + /** + * Setup bones (indexes) + */ + for (var si = 0; si < skinIndices.length; si++) { + threeGeometry.skinIndices.push( + new this.THREE.Vector4( + skinIndices[si].x, + skinIndices[si].y, + skinIndices[si].z, + skinIndices[si].w + ) + ); + } + + /** + * Setup bones (weights) + */ + for (var sw = 0; sw < skinWeights.length; sw++) { + threeGeometry.skinWeights.push( + new this.THREE.Vector4( + skinWeights[sw].x, + skinWeights[sw].y, + skinWeights[sw].z, + skinWeights[sw].w + ) + ); + } + + threeMesh = new this.THREE.SkinnedMesh(threeGeometry, threeMaterial); + + var skeleton = new this.THREE.Skeleton(threeBones); + + skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture; + + for (var i = 0; i < bones.length; i++) { + if (bones[i].parentBoneId === null) { + threeMesh.add(threeBones[i]); + break; + } + } + + threeMesh.bind(skeleton); + + threeMesh.pose(); + + threeMesh.skeleton.skeletonHelper = new this.THREE.SkeletonHelper(threeMesh); + threeMesh.skeleton.skeletonHelper.material.linewidth = 5; + } + + if (threeMesh == null) { + console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.'); + } + + gameLibMesh.threeMeshId = threeMesh.id; + + return threeMesh; +}; + +GameLib.D3.prototype.invertWindingOrder = function(triangles) { + + for (var i = 0; i < triangles.length; i++) { + var v1 = triangles[i].v1; + triangles[i].v1 = triangles[i].v2; + triangles[i].v2 = v1; + + var backupUV = triangles[i].triangle.v1uv; + triangles[i].triangle.v1uv = triangles[i].triangle.v2uv; + triangles[i].triangle.v2uv = backupUV; + } + + return triangles; +}; + +/** + * This function resets a the winding order of a mesh from a reference point V (the average center of the mesh) + */ +GameLib.D3.prototype.resetWindingOrder = function(faces, vertices) { + + var vertexList = new GameLib.D3.Vector3.Points(); + + for (var v = 0; v < vertices.length; v++) { + vertexList.add(new GameLib.D3.Vector3( + vertices[v].position.x, + vertices[v].position.y, + vertices[v].position.z + )); + } + + var V = vertexList.average(); + + var triangles = []; + + for (var s = 0; s < faces.length; s += 3) { + + var v0 = faces[s]; + var v1 = faces[s+1]; + var v2 = faces[s+2]; + + triangles.push( + { + v0 : v0, + v1 : v1, + v2 : v2, + edges : [ + {v0: v0, v1: v1}, + {v0: v1, v1: v2}, + {v0: v2, v1: v0} + ], + winding : 0, + edgeIndex : -1, + processed : false + } + ); + } + + for (var i = 0; i < triangles.length; i++) { + if ( + GameLib.D3.Vector3.clockwise( + vertices[triangles[i].v0].position, + vertices[triangles[i].v1].position, + vertices[triangles[i].v2].position, + V + ) + ) { + console.log('clockwise'); + var bv1 = triangles[i].v1; + triangles[i].v1 = triangles[i].v2; + triangles[i].v2 = bv1; + } else { + console.log('not clockwise'); + } + } + + return triangles; +}; + +/** + * This function resets the winding order for triangles in faces, given an initial triangle and orientation edge + * used pseudocode from + * http://stackoverflow.com/questions/17036970/how-to-correct-winding-of-triangles-to-counter-clockwise-direction-of-a-3d-mesh + * We need to use a graph traversal algorithm, + * lets assume we have method that returns neighbor of triangle on given edge + * + * neighbor_on_egde( next_tria, edge ) + * + * to_process = set of pairs triangle and orientation edge, initial state is one good oriented triangle with any edge on it + * processed = set of processed triangles; initial empty + * + * while to_process is not empty: + * next_tria, orientation_edge = to_process.pop() + * add next_tria in processed + * if next_tria is not opposite oriented than orientation_edge: + * change next_tria (ABC) orientation (B<->C) + * for each edge (AB) in next_tria: + * neighbor_tria = neighbor_on_egde( next_tria, edge ) + * if neighbor_tria exists and neighbor_tria not in processed: + * to_process add (neighbor_tria, edge opposite oriented (BA)) + * @param faces GameLib.D3.TriangleFace[] + * @param orientationEdge GameLib.D3.Vector2 + * @returns {Array} + */ +GameLib.D3.fixWindingOrder = function(faces, orientationEdge) { + + /** + * Checks if a TriangleFace belonging to a TriangleEdge has already been processed + * @param processed TriangleEdge[] + * @param triangle TriangleFace + * @returns {boolean} + */ + function inProcessed(processed, triangle) { + + for (var i = 0; i < processed.length; i++) { + if (processed[i].triangle.equals(triangle)) { + return true; + } + } + + return false; + } + + /** + * Returns a neighbouring triangle on a specific edge - preserving the edge orientation + * @param edge GameLib.D3.Vector2 + * @param faces GameLib.D3.TriangleFace[] + * @param currentTriangle + * @returns {*} + */ + function neighbourOnEdge(edge, faces, currentTriangle) { + + for (var i = 0; i < faces.length; i++) { + if ( + (faces[i].v0 == edge.x && faces[i].v1 == edge.y) || + (faces[i].v1 == edge.x && faces[i].v2 == edge.y) || + (faces[i].v2 == edge.x && faces[i].v0 == edge.y) || + (faces[i].v0 == edge.y && faces[i].v1 == edge.x) || + (faces[i].v1 == edge.y && faces[i].v2 == edge.x) || + (faces[i].v2 == edge.y && faces[i].v0 == edge.x) + ) { + + var triangle = new GameLib.D3.TriangleFace( + faces[i].v0, + faces[i].v1, + faces[i].v2, + faces[i].materialIndex, + faces[i].v0uv, + faces[i].v1uv, + faces[i].v2uv + ); + + if (triangle.equals(currentTriangle)) { + continue; + } + + return new GameLib.D3.TriangleEdge( + triangle, + edge + ); + } + } + + return null; + } + + var toProcess = [ + new GameLib.D3.TriangleEdge( + new GameLib.D3.TriangleFace( + faces[0].v0, + faces[0].v1, + faces[0].v2, + faces[0].materialIndex, + faces[0].v0uv, + faces[0].v1uv, + faces[0].v2uv + ), + orientationEdge + ) + ]; + + var processed = []; + + while (toProcess.length > 0) { + + var triangleEdge = toProcess.pop(); + + /** + * If edge is the same orientation (i.e. the edge order is the same as the given triangle edge) it needs to be reversed + * to have the same winding order) + */ + if ( + (triangleEdge.triangle.v0 == triangleEdge.edge.x && + triangleEdge.triangle.v1 == triangleEdge.edge.y) || + (triangleEdge.triangle.v1 == triangleEdge.edge.x && + triangleEdge.triangle.v2 == triangleEdge.edge.y) || + (triangleEdge.triangle.v2 == triangleEdge.edge.x && + triangleEdge.triangle.v0 == triangleEdge.edge.y) + ) { + var backupV = triangleEdge.triangle.v1; + triangleEdge.triangle.v1 = triangleEdge.triangle.v2; + triangleEdge.triangle.v2 = backupV; + + var backupUV = triangleEdge.triangle.v1uv; + triangleEdge.triangle.v1uv = triangleEdge.triangle.v2uv; + triangleEdge.triangle.v2uv = backupUV; + } + + processed.push(triangleEdge); + + var edges = [ + new GameLib.D3.Vector2( + triangleEdge.triangle.v0, + triangleEdge.triangle.v1 + ), + new GameLib.D3.Vector2( + triangleEdge.triangle.v1, + triangleEdge.triangle.v2 + ), + new GameLib.D3.Vector2( + triangleEdge.triangle.v2, + triangleEdge.triangle.v0 + ) + ]; + + for (var j = 0; j < edges.length; j++) { + var neighbour = neighbourOnEdge(edges[j], faces, triangleEdge.triangle); + if (neighbour && !inProcessed(processed, neighbour.triangle)) { + toProcess.push(neighbour); + } + } + } + + /** + * In processed - we will have some duplicates - only add the unique ones + * @type {Array} + */ + var triangles = []; + for (var i = 0; i < processed.length; i++) { + var found = false; + for (var k = 0; k < triangles.length; k++) { + if (triangles[k].equals(processed[i].triangle)){ + found = true; + break; + } + } + if (!found) { + triangles.push(processed[i].triangle); + } + } + + return triangles; +}; + +/** + * This is a work-around function to fix polys which don't triangulate because + * they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around + * Z then Y axis + * @param verticesFlat [] + * @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY + * @return [] + */ +GameLib.D3.fixPolyZPlane = function(verticesFlat, grain) { + + if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) { + console.log("The vertices are not in the right length : " + verticesFlat.length); + } + + var vertices = []; + + var points = new GameLib.D3.Vector4.Points(); + + for (var i = 0; i < verticesFlat.length; i += 3) { + points.add(new GameLib.D3.Vector3( + verticesFlat[i], + verticesFlat[i + 1], + verticesFlat[i + 2] + )); + } + + points.toOrigin(); + + points.maximizeXDistance(grain); + + points.maximizeYDistance(grain); + + for (i = 0; i < points.vectors.length; i++) { + vertices.push( + [ + points.vectors[i].x, + points.vectors[i].y + ] + ); + } + + return vertices; +}; \ No newline at end of file diff --git a/src/game-lib-physics.js b/src/game-lib-physics.js new file mode 100644 index 0000000..3f72cb3 --- /dev/null +++ b/src/game-lib-physics.js @@ -0,0 +1,32 @@ +/** + * Physics SuperSet Namespace Object + * @param id + * @param name + * @param engine GameLib.D3.Engine + * @param worlds + * @returns {{World: World}} + * @constructor + */ +GameLib.D3.Physics = function( + id, + name, + engine, + worlds +) { + this.id = id; + this.name = name; + this.engine = engine; + + if (typeof worlds == 'undefined') { + worlds = []; + } + this.worlds = worlds; +}; + + +/** + * Solver Types + * @type {number} + */ +GameLib.D3.Physics.SPLIT_SOLVER = 0x1; +GameLib.D3.Physics.GS_SOLVER = 0x2; \ No newline at end of file diff --git a/src/game-lib-poly-vertex.js b/src/game-lib-poly-vertex.js new file mode 100644 index 0000000..4ef418b --- /dev/null +++ b/src/game-lib-poly-vertex.js @@ -0,0 +1,36 @@ +/** + * Contains a Poly vertex data structure + * @param localIndex + * @param mvertIndex + * @param uv GameLib.D3.Vector2 + * @param materialIndex + * @param edgeIndex + * @constructor + */ +GameLib.D3.PolyVertex = function( + localIndex, + mvertIndex, + uv, + materialIndex, + edgeIndex +) { + this.localIndex = localIndex; + this.mvertIndex = mvertIndex; + this.uv = uv; + this.materialIndex = materialIndex; + this.edgeIndex = edgeIndex; +}; + +/** + * Clone a PolyVertex + * @returns {GameLib.D3.PolyVertex} + */ +GameLib.D3.PolyVertex.prototype.clone = function() { + return new GameLib.D3.PolyVertex( + this.localIndex, + this.mvertIndex, + this.uv.copy(), + this.materialIndex, + this.edgeIndex + ) +}; \ No newline at end of file diff --git a/src/game-lib-raycast-vehicle.js b/src/game-lib-raycast-vehicle.js new file mode 100644 index 0000000..4b953e2 --- /dev/null +++ b/src/game-lib-raycast-vehicle.js @@ -0,0 +1,10 @@ +/** + * Physics Raycast Vehicle Superset + * TODO: body + wheels[] + * @constructor + */ +GameLib.D3.Physics.RaycastVehicle = function( +) { + this.vehicleObject = null; +}; + diff --git a/src/game-lib-rigid-body-vehicle.js b/src/game-lib-rigid-body-vehicle.js new file mode 100644 index 0000000..410e617 --- /dev/null +++ b/src/game-lib-rigid-body-vehicle.js @@ -0,0 +1,9 @@ +/** + * Physics Rigid Body Vehicle Superset + * TODO: body + wheels[] + * @constructor + */ +GameLib.D3.Physics.RigidVehicle = function( +) { + this.vehicleObject = null; +}; diff --git a/src/game-lib-rigid-body.js b/src/game-lib-rigid-body.js new file mode 100644 index 0000000..b4910df --- /dev/null +++ b/src/game-lib-rigid-body.js @@ -0,0 +1,92 @@ +/** + * RigidBody Superset + * @param mass + * @param friction + * @param position + * @param quaternion + * @param velocity + * @param angularVelocity + * @param linearDamping + * @param angularDamping + * @param allowSleep + * @param sleepSpeedLimit + * @param sleepTimeLimit + * @param collisionFilterGroup + * @param collisionFilterMask + * @param fixedRotation + * @param shape + * @returns {GameLib.D3.Physics.RigidBody} + * @constructor + */ +GameLib.D3.Physics.RigidBody = function( + mass, + friction, + position, + quaternion, + velocity, + angularVelocity, + linearDamping, + angularDamping, + allowSleep, + sleepSpeedLimit, + sleepTimeLimit, + collisionFilterGroup, + collisionFilterMask, + fixedRotation, + shape +) { + + this.position = position || new GameLib.D3.Vector3(); + this.velocity = velocity || new GameLib.D3.Vector3(); + this.angularVelocity = angularVelocity || new GameLib.D3.Vector3(); + this.quaternion = quaternion || new GameLib.D3.Vector4(0, 0, 0, 1); + this.mass = typeof mass == "undefined" ? 0 : mass; + this.friction = typeof friction == "undefined" ? 5 : friction; + this.linearDamping = typeof linearDamping == "undefined" ? 0.01 : linearDamping; + this.angularDamping = typeof angularDamping == "undefined" ? 0.01 : angularDamping; + this.allowSleep = typeof allowSleep == "undefined" ? true : allowSleep; + this.sleepSpeedLimit = typeof sleepSpeedLimit == "undefined" ? 0.1 : sleepSpeedLimit; + this.sleepTimeLimit = typeof sleepTimeLimit == "undefined" ? 1.0 : sleepTimeLimit; + this.collisionFilterGroup = typeof collisionFilterGroup == "undefined" ? 1 : collisionFilterGroup; + this.collisionFilterMask = typeof collisionFilterMask == "undefined" ? 1 : collisionFilterMask; + this.fixedRotation = typeof fixedRotation == "undefined" ? false : fixedRotation; + this.shape = typeof shape == "undefined" ? null : shape; + + this.rigidBodyInstance = this.createRigidBodyInstance(); +}; + +/** + * + * @returns {*} + */ +GameLib.D3.Physics.World.RigidBody.prototype.createRigidBodyInstance = function() { + + var rigidBody = null; + + // Create the bodyObject + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + rigidBody = new this.physics.CANNON.Body( + { + mass: mass, + friction: friction, + position: new this.physics.CANNON.Vec3(position.x, position.y, position.z), + velocity: new this.physics.CANNON.Vec3(velocity.x, velocity.y, velocity.z), + quaternion: new this.physics.CANNON.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w), + angularVelocity: new this.physics.CANNON.Vec3(angularVelocity.x, angularVelocity.y, angularVelocity.z), + linearDamping: linearDamping, + angularDamping: angularDamping, + allowSleep: allowSleep, + sleepSpeedLimit: sleepSpeedLimit, + sleepTimeLimit: sleepTimeLimit, + collisionFilterGroup: collisionFilterGroup, + collisionFilterMask: collisionFilterMask, + fixedRotation: fixedRotation, + shape: shape + } + ); + + } + + return rigidBody; +}; + diff --git a/src/game-lib-scene.js b/src/game-lib-scene.js new file mode 100644 index 0000000..b036a30 --- /dev/null +++ b/src/game-lib-scene.js @@ -0,0 +1,571 @@ +/** + * Scenes are objects putting meshes into 'world space' + * @param id + * @param path String + * @param name String + * @param meshes GameLib.D3.Mesh[] + * @param quaternion + * @param position + * @param rotation + * @param scale + * @param parentSceneId + * @param lights + * @constructor + */ +GameLib.D3.Scene = function( + id, + path, + name, + meshes, + quaternion, + position, + rotation, + scale, + parentSceneId, + lights, + physics +) { + this.id = id; + this.path = path; + this.name = name; + if (this.name.trim() == "") { + this.name = 'unnamed'; + } + this.meshes = meshes; + + if (typeof quaternion == 'undefined') { + quaternion = new GameLib.D3.Vector4(); + } + this.quaternion = quaternion; + + if (typeof position == 'undefined') { + position = new GameLib.D3.Vector3(0,0,0); + } + this.position = position; + + if (typeof rotation == 'undefined') { + rotation = new GameLib.D3.Vector3(0,0,0); + } + this.rotation = rotation; + + if (typeof scale == 'undefined') { + scale = new GameLib.D3.Vector3(1,1,1); + } + this.scale = scale; + + if (typeof parentSceneId == 'undefined') { + parentSceneId = null; + } + this.parentSceneId = parentSceneId; + + if (typeof lights == 'undefined') { + lights = []; + } + this.lights = lights; + + if (typeof physics == 'undefined') { + physics = []; + } + this.physics = physics; +}; + +/** + * Loads a scene directly from the API + * @param sceneName + * @param onLoaded callback + */ +GameLib.D3.prototype.loadSceneFromApi = function(scene, onLoaded) { + + /** + * First check if this is a client or server side request + */ + if (typeof XMLHttpRequest == 'undefined') { + console.warn('implement server side loading from API here'); + return onLoaded(null, new Error('not implemented')); + } + + var xhr = new XMLHttpRequest(); + xhr.open( + 'GET', + this.apiUrl + '/scene/load' + scene.path + '/' + scene.name + ); + + xhr.onreadystatechange = function(xhr, gameLibD3) { + return function() { + if (xhr.readyState == 4) { + + var response = JSON.parse(xhr.responseText); + + if (!response.scene || response.scene.length == 0) { + return onLoaded(null, null, new Error('Could not load scene')); + } + + var scene = response.scene[0]; + + var physics3ds = []; + + if (scene.physics && scene.physics.length > 0) { + + for (var p = 0; p < scene.physics.length; p++) { + + var physics = scene.physics[p]; + + var physics3d = new GameLib.D3.Physics( + physics.id, + physics.name, + physics.engineType, + gameLibD3.CANNON, + null, + null + ); + + var worlds3d = []; + + for (var w = 0; w < physics.worlds.length; w++) { + + var world = physics.worlds[w]; + + var broadphase = world.broadphase; + + var broadphase3d = new GameLib.D3.Physics.Broadphase( + broadphase.id, + broadphase.name, + broadphase.broadphaseType + ); + + var solver = world.solver; + + var solver3d = new GameLib.D3.Physics.Solver( + solver.id, + solver.name, + solver.solverType, + solver.iterations, + solver.tolerance + ); + + var bodies = world.rigidBodies; + + var bodies3d = []; + + for (var b = 0; b < bodies.length; b++) { + + var body = bodies[b]; + + //TODO: add all body properties here + var body3d = new GameLib.D3.Physics.RigidBody( + body.id, + body.name + ); + + bodies3d.push(body3d); + } + + var world3d = new GameLib.D3.Physics.World( + null, + world.name, + physics3d, + new GameLib.D3.Vector3( + world.gravity.x, + world.gravity.y, + world.gravity.z + ), + broadphase3d, + solver3d, + bodies3d + ); + + worlds3d.push(world3d); + } + + physics3ds.push(physics3d); + } + } + + var lights3d = []; + + for (var l = 0; l < scene.lights.length; l++) { + + var light = scene.lights[l]; + + var light3d = new GameLib.D3.Light( + light.id, + light.lightType, + light.name, + new GameLib.D3.Color( + light.color.r, + light.color.g, + light.color.b, + light.color.a + ), + light.intensity, + new GameLib.D3.Vector3( + light.position.x, + light.position.y, + light.position.z + ), + new GameLib.D3.Vector3( + light.targetPosition.x, + light.targetPosition.y, + light.targetPosition.z + ), + new GameLib.D3.Vector4( + light.quaternion.x, + light.quaternion.y, + light.quaternion.z, + light.quaternion.w + ), + new GameLib.D3.Vector3( + light.rotation.x, + light.rotation.y, + light.rotation.z + ), + new GameLib.D3.Vector3( + light.scale.x, + light.scale.y, + light.scale.z + ), + light.distance, + light.decay, + light.power, + light.angle, + light.penumbra + ); + + lights3d.push(light3d); + }; + + var scene3d = new GameLib.D3.Scene( + scene._id || scene.id, + scene.path, + scene.name, + scene.meshes, + new GameLib.D3.Vector4( + scene.quaternion.x, + scene.quaternion.y, + scene.quaternion.z, + scene.quaternion.w + ), + new GameLib.D3.Vector3( + scene.position.x, + scene.position.y, + scene.position.z + ), + new GameLib.D3.Vector3( + scene.rotation.x, + scene.rotation.y, + scene.rotation.z + ), + new GameLib.D3.Vector3( + scene.scale.x, + scene.scale.y, + scene.scale.z + ), + scene.parentSceneId, + lights3d, + physics3ds + ); + + gameLibD3.loadScene(scene3d, onLoaded, false); + } + } + }(xhr, this); + + xhr.send(); +}; + + +/** + * Loads a GameLib.D3.Scene object into a ThreeJS Scene object + * @param gameLibScene GameLib.D3.Scene + * @param onLoaded callback when all meshes have loaded + * @param computeNormals set to true to compute new face and vertex normals during load + */ +GameLib.D3.prototype.loadScene = function(gameLibScene, onLoaded, computeNormals) { + + console.log("loading scene " + gameLibScene.name); + + this.path = gameLibScene.path; + + var meshQ = []; + + for (var m = 0; m < gameLibScene.meshes.length; m++) { + + var mesh = gameLibScene.meshes[m]; + + console.log("loading mesh " + mesh.name); + + var geometry = new this.THREE.Geometry(); + + var vertices = mesh.vertices; + + var faces = mesh.faces; + + var faceVertexUvs = mesh.faceVertexUvs; + + var materials = mesh.materials; + + /** + * Setup vertices + */ + for (var v = 0; v < vertices.length; v++) { + geometry.vertices.push( + new this.THREE.Vector3( + vertices[v].position.x, + vertices[v].position.y, + vertices[v].position.z + ) + ) + } + + /** + * Setup faces + */ + for (var f = 0; f < faces.length; f++) { + + var face = new this.THREE.Face3( + faces[f].v0, + faces[f].v1, + faces[f].v2, + new this.THREE.Vector3( + faces[f].normal.x, + faces[f].normal.y, + faces[f].normal.z + ), + new this.THREE.Color( + faces[f].color.r, + faces[f].color.g, + faces[f].color.b + ), + faces[f].materialIndex + ); + + face.vertexColors = [ + new this.THREE.Color( + faces[f].vertexColors[0].r, + faces[f].vertexColors[0].g, + faces[f].vertexColors[0].b + ), + new this.THREE.Color( + faces[f].vertexColors[1].r, + faces[f].vertexColors[1].g, + faces[f].vertexColors[1].b + ), + new this.THREE.Color( + faces[f].vertexColors[2].r, + faces[f].vertexColors[2].g, + faces[f].vertexColors[2].b + ) + ]; + + face.normal = new this.THREE.Vector3( + faces[f].normal.x, + faces[f].normal.y, + faces[f].normal.z + ); + + face.vertexNormals = [ + new this.THREE.Vector3( + faces[f].vertexNormals[0].x, + faces[f].vertexNormals[0].y, + faces[f].vertexNormals[0].z + ), + new this.THREE.Vector3( + faces[f].vertexNormals[1].x, + faces[f].vertexNormals[1].y, + faces[f].vertexNormals[1].z + ), + new this.THREE.Vector3( + faces[f].vertexNormals[2].x, + faces[f].vertexNormals[2].y, + faces[f].vertexNormals[2].z + ) + ]; + + geometry.faces.push(face); + } + + geometry.faceVertexUvs = []; + + /** + * Setup face UVs + */ + for (var fm = 0; fm < faceVertexUvs.length; fm++) { + + var faceMaterialVertexUvs = faceVertexUvs[fm]; + + geometry.faceVertexUvs[fm] = []; + + for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) { + geometry.faceVertexUvs[fm][fuv] = []; + geometry.faceVertexUvs[fm][fuv].push( + new this.THREE.Vector2( + faceMaterialVertexUvs[fuv][0].x, + faceMaterialVertexUvs[fuv][0].y + ), + new this.THREE.Vector2( + faceMaterialVertexUvs[fuv][1].x, + faceMaterialVertexUvs[fuv][1].y + ), + new this.THREE.Vector2( + faceMaterialVertexUvs[fuv][2].x, + faceMaterialVertexUvs[fuv][2].y + ) + ); + } + } + + /** + * Re-calculate normals (if we have to) + * @type {Array} + */ + if (computeNormals) { + geometry.computeFaceNormals(); + geometry.computeVertexNormals(); + } + + var threeMaterialLoaders = []; + + /** + * Setup materials + */ + for (var mi = 0; mi < materials.length; mi++) { + threeMaterialLoaders.push(this.createThreeMaterial(materials[mi])); + } + + var result = this.Q.all(threeMaterialLoaders).then( + function(gl3d, mesh, geometry) { + return function(materials) { + + console.log("loaded material : " + materials[0].name); + + /** + * We don't support MultiMaterial atm - it doesn't work with raycasting + */ + var material = materials[0]; + + var threeMesh = gl3d.createThreeMesh(mesh, geometry, material); + threeMesh.name = mesh.name; + + threeMesh.position.x = mesh.position.x; + threeMesh.position.y = mesh.position.y; + threeMesh.position.z = mesh.position.z; + + threeMesh.rotation.x = mesh.rotation.x; + threeMesh.rotation.y = mesh.rotation.y; + threeMesh.rotation.z = mesh.rotation.z; + + threeMesh.scale.x = mesh.scale.x; + threeMesh.scale.y = mesh.scale.y; + threeMesh.scale.z = mesh.scale.z; + + threeMesh.quaternion.x = mesh.quaternion.x; + threeMesh.quaternion.y = mesh.quaternion.y; + threeMesh.quaternion.z = mesh.quaternion.z; + threeMesh.quaternion.w = mesh.quaternion.w; + + return threeMesh; + }; + }(this, mesh, geometry) + ).catch(function(error){ + console.log(error); + }); + + meshQ.push(result); + } + + this.Q.all(meshQ).then(function(threeMeshes){ + console.log("all meshes have loaded"); + if (typeof onLoaded != 'undefined') { + + var threeLights = []; + + for (var sli = 0; sli < gameLibScene.lights.length; sli++) { + + var blenderLight = gameLibScene.lights[sli]; + + var light = null; + + if (blenderLight.lightType == 'AmbientLight') { + light = new this.THREE.AmbientLight(blenderLight.color, blenderLight.intensity); + } + + if (blenderLight.lightType == 'DirectionalLight') { + light = new this.THREE.DirectionalLight(blenderLight.color, blenderLight.intensity); + } + + if (blenderLight.lightType == 'PointLight') { + light = new this.THREE.PointLight(blenderLight.color, blenderLight.intensity); + light.distance = blenderLight.distance; + light.decay = blenderLight.decay; + } + + if (blenderLight.lightType == 'SpotLight') { + light = new this.THREE.SpotLight(blenderLight.color, blenderLight.intensity); + light.distance = blenderLight.distance; + light.angle = blenderLight.angle; + light.penumbra = blenderLight.penumbra; + light.decay = blenderLight.decay; + } + + light.position.x = blenderLight.position.x; + light.position.y = blenderLight.position.y; + light.position.z = blenderLight.position.z; + + light.rotation.x = blenderLight.rotation.x; + light.rotation.y = blenderLight.rotation.y; + light.rotation.z = blenderLight.rotation.z; + + // light.scale.x = blenderLight.scale.x; + // light.scale.y = blenderLight.scale.y; + // light.scale.z = blenderLight.scale.z; + + if (light == null) { + console.warn('Does not support lights of type :' + blenderLight.lightType + ', not imported'); + } else { + light.name = blenderLight.name; + threeLights.push(light); + } + } + + var threeScene = new this.THREE.Scene(); + + threeScene.name = gameLibScene.name; + + threeScene.position.x = gameLibScene.position.x; + threeScene.position.y = gameLibScene.position.y; + threeScene.position.z = gameLibScene.position.z; + + threeScene.rotation.x = gameLibScene.rotation.x; + threeScene.rotation.y = gameLibScene.rotation.y; + threeScene.rotation.z = gameLibScene.rotation.z; + + threeScene.scale.x = gameLibScene.scale.x; + threeScene.scale.y = gameLibScene.scale.y; + threeScene.scale.z = gameLibScene.scale.z; + + threeScene.quaternion.x = gameLibScene.quaternion.x; + threeScene.quaternion.y = gameLibScene.quaternion.y; + threeScene.quaternion.z = gameLibScene.quaternion.z; + threeScene.quaternion.w = gameLibScene.quaternion.w; + + for (var m = 0; m < threeMeshes.length; m++) { + threeScene.add(threeMeshes[m]); + } + + for (var l = 0; l < threeLights.length; l++) { + threeScene.add(threeLights[l]); + } + + onLoaded( + gameLibScene, + { + scene: threeScene, + lights: threeLights, + meshes: threeMeshes + } + ); + } + }.bind(this)).catch(function(error){ + console.log(error); + }); +}; \ No newline at end of file diff --git a/src/game-lib-shape.js b/src/game-lib-shape.js new file mode 100644 index 0000000..cc572b8 --- /dev/null +++ b/src/game-lib-shape.js @@ -0,0 +1,37 @@ +/** + * Physics Shape Superset + * @constructor + */ +GameLib.D3.Physics.Shape = function( + shapeObject, // Physics engine specific + shapeType +) { + this.shapeObject = shapeObject; + this.shapeType = shapeType; + this.scale = new GameLib.D3.Vector3(1, 1, 1); +}; + +GameLib.D3.Physics.SHAPE_TYPE_SPHERE = 1; +GameLib.D3.Physics.SHAPE_TYPE_BOX = 2; +GameLib.D3.Physics.SHAPE_TYPE_TRIMESH = 3; +GameLib.D3.Physics.SHAPE_TYPE_CYLINDER = 4; + + +GameLib.D3.Physics.Shape.prototype.Update = function() { + if(this.physics.engineType === GameLib.D3.Physics.TYPE_CANNON) { + if(this.shapeType === GameLib.D3.Physics.SHAPE_TYPE_TRIMESH) { + this.shapeObject.setScale( + new this.physics.CANNON.Vec3( + this.scale.x, + this.scale.y, + this.scale.z + ) + ); + this.shapeObject.updateAABB(); + this.shapeObject.updateNormals(); + this.shapeObject.updateEdges(); + this.shapeObject.updateBoundingSphereRadius(); + this.shapeObject.updateTree(); + } + } +}; diff --git a/src/game-lib-skeleton.js b/src/game-lib-skeleton.js new file mode 100644 index 0000000..d843a5f --- /dev/null +++ b/src/game-lib-skeleton.js @@ -0,0 +1,69 @@ +/** + * Skeleton Superset + * @param id + * @param bones GameLib.D3.Bone + * @param boneInverses + * @param useVertexTexture + * @param boneTextureWidth + * @param boneTextureHeight + * @param boneMatrices + * @param boneTexture + * @constructor + */ +GameLib.D3.Skeleton = function( + id, + bones, + boneInverses, + useVertexTexture, + boneTextureWidth, + boneTextureHeight, + boneMatrices, + boneTexture +) { + this.id = id; + + this.bones = bones; + + /** + * An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones. + * @type GameLib.D3.Matrix4[] + */ + if (typeof boneInverses == 'undefined') { + boneInverses = []; + } + this.boneInverses = boneInverses; + + /** + * Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices + * @type {boolean} + */ + if (typeof useVertexTexture == 'undefined') { + useVertexTexture = false; + } + this.useVertexTexture = useVertexTexture; + + if (this.useVertexTexture == true) { + console.warn('support for vertex texture bones is not supported yet - something could break somewhere'); + } + + if (typeof boneTextureWidth == 'undefined') { + boneTextureWidth = 0; + } + this.boneTextureWidth = boneTextureWidth; + + if (typeof boneTextureHeight == 'undefined') { + boneTextureHeight = 0; + } + this.boneTextureHeight = boneTextureHeight; + + if (typeof boneMatrices == 'undefined') { + boneMatrices = []; + } + this.boneMatrices = boneMatrices; + + if (typeof boneTexture == 'undefined') { + boneTexture = []; + } + this.boneTexture = boneTexture; +}; + diff --git a/src/game-lib-sky-box.js b/src/game-lib-sky-box.js new file mode 100644 index 0000000..e37c343 --- /dev/null +++ b/src/game-lib-sky-box.js @@ -0,0 +1,65 @@ +GameLib.D3.SkyBox = function ( + +) { + this.id = null; + this.texturesFolder = null; +}; + +GameLib.D3.SkyBox.prototype.Load = function ( + texturesFolder +) { + this.texturesFolder = texturesFolder; + this.textures = []; + this.materials = []; + this.mesh = {}; + this.scene = new THREE.Scene(); + this.textureCube = null; + + var textureLoader = new THREE.TextureLoader(); + + // this textures are used to display the skybox + this.textures.push(textureLoader.load(this.texturesFolder + "px.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "nx.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "py.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "ny.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "pz.png")); + this.textures.push(textureLoader.load(this.texturesFolder + "nz.png")); + + // assign textures to each cube face + for (var i = 0; i < 6; i ++) { + this.materials.push(new THREE.MeshBasicMaterial({ map: this.textures[i] })); + } + + // create cube geometry + this.mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshFaceMaterial(this.materials)); + this.mesh.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1)); + this.scene.add(this.mesh); + + // Load env textureCube + // this is used for reflections on meshes + // mesh.material.envMap = this.textureCube; + this.textureCube = new THREE.CubeTextureLoader().load([ + this.texturesFolder + "px.png", this.texturesFolder + "nx.png", + this.texturesFolder + "py.png", this.texturesFolder + "ny.png", + this.texturesFolder + "pz.png", this.texturesFolder + "nz.png" + ]); +}; + +GameLib.D3.SkyBox.prototype.Render = function ( + threeRenderer, + threeCamera +) { + var cameraPosition = new THREE.Vector3(threeCamera.position.x, threeCamera.position.y, threeCamera.position.z); + + threeCamera.position.set(0, 0, 0); + + var gl = threeRenderer.context; + + gl.disable(gl.DEPTH_TEST); + + threeRenderer.render(this.scene, threeCamera); + + gl.enable(gl.DEPTH_TEST); + + threeCamera.position.copy(cameraPosition); +}; diff --git a/src/game-lib-solver.js b/src/game-lib-solver.js new file mode 100644 index 0000000..74f7777 --- /dev/null +++ b/src/game-lib-solver.js @@ -0,0 +1,38 @@ +/** + * Physics Solver Superset + * @param id + * @param name + * @param solverType + * @param iterations + * @param tolerance + * @constructor + */ +GameLib.D3.Physics.Solver = function( + id, + name, + solverType, + iterations, + tolerance +) { + this.id = id; + if (typeof name == 'undefined') { + if (solverType == GameLib.D3.Physics.SPLIT_SOLVER) { + name = 'split solver'; + } else if (solverType == GameLib.D3.Physics.GS_SOLVER) { + name = 'gs solver'; + } else { + name = 'unknown solver'; + } + } + this.name = name; + this.solverType = solverType; + this.iterations = iterations; + this.tolerance = tolerance; +}; + +/** + * Solver Types + * @type {number} + */ +GameLib.D3.Physics.SPLIT_SOLVER = 0x1; +GameLib.D3.Physics.GS_SOLVER = 0x2; diff --git a/src/game-lib-texture.js b/src/game-lib-texture.js new file mode 100644 index 0000000..6c51723 --- /dev/null +++ b/src/game-lib-texture.js @@ -0,0 +1,370 @@ +/** + * Texture Superset + * @param id + * @param path + * @param name + * @param image + * @param wrapS + * @param wrapT + * @param repeat + * @param data + * @param format + * @param mapping + * @param magFilter + * @param minFilter + * @param textureType + * @param anisotropy + * @param offset + * @param generateMipmaps + * @param flipY + * @param mipmaps + * @param unpackAlignment + * @param premultiplyAlpha + * @param encoding + * @constructor + */ +GameLib.D3.Texture = function( + id, + name, + image, + wrapS, + wrapT, + repeat, + data, + format, + mapping, + magFilter, + minFilter, + textureType, + anisotropy, + offset, + generateMipmaps, + flipY, + mipmaps, + unpackAlignment, + premultiplyAlpha, + encoding +) { + this.id = id; + this.name = name; + this.image = image; + + if (typeof wrapS == 'undefined') { + wrapS = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING; + } + this.wrapS = wrapS; + + if (typeof wrapT == 'undefined') { + wrapT = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING; + } + this.wrapT = wrapT; + + if (typeof repeat == 'undefined') { + repeat = new GameLib.D3.Vector2(1, 1); + } + this.repeat = repeat; + + if (typeof data == 'undefined') { + data = null; + } + this.data = data; + + if (typeof format == 'undefined') { + format = GameLib.D3.Texture.TYPE_RGBA_FORMAT; + } + this.format = format; + + if (typeof mapping == 'undefined') { + mapping = GameLib.D3.Texture.TYPE_UV_MAPPING; + } + this.mapping = mapping; + + if (typeof magFilter == 'undefined') { + magFilter = GameLib.D3.Texture.TYPE_LINEAR_FILTER; + } + this.magFilter = magFilter; + + if (typeof minFilter == 'undefined') { + minFilter = GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER; + } + this.minFilter = minFilter; + + if (typeof textureType == 'undefined') { + textureType = GameLib.D3.Texture.TYPE_UNSIGNED_BYTE; + } + this.textureType = textureType; + + if (typeof anisotropy == 'undefined') { + anisotropy = 1; + } + this.anisotropy = anisotropy; + + if (typeof offset == 'undefined') { + offset = new GameLib.D3.Vector2(0, 0); + } + this.offset = offset; + + if (typeof generateMipmaps == 'undefined') { + generateMipmaps = true; + } + this.generateMipmaps = generateMipmaps; + + if (typeof flipY == 'undefined') { + flipY = true; + } + this.flipY = flipY; + + if (typeof mipmaps == 'undefined') { + mipmaps = []; + } + this.mipmaps = mipmaps; + + if (typeof unpackAlignment == 'undefined') { + unpackAlignment = 4; + } + this.unpackAlignment = unpackAlignment; + + if (typeof premultiplyAlpha == 'undefined') { + premultiplyAlpha = false; + } + this.premultiplyAlpha = premultiplyAlpha; + + if (typeof encoding == 'undefined') { + encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING; + } + this.encoding = encoding; +}; + +/** + * Texture Formats + * @type {number} + */ +GameLib.D3.Texture.TYPE_ALPHA_FORMAT = 1019; +GameLib.D3.Texture.TYPE_RGB_FORMAT = 1020; +GameLib.D3.Texture.TYPE_RGBA_FORMAT = 1021; +GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT = 1022; +GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT = 1023; +GameLib.D3.Texture.TYPE_DEPTH_FORMAT = 1026; + +/** + * Mapping modes + * @type {number} + */ +GameLib.D3.Texture.TYPE_UV_MAPPING = 300; +GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING = 301; +GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING = 302; +GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING = 303; +GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING = 304; +GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING = 305; +GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING = 306; +GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING = 307; + +/** + * Wrapping Modes + * @type {number} + */ +GameLib.D3.Texture.TYPE_REPEAT_WRAPPING = 1000; +GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING = 1001; +GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING = 1002; + +/** + * Mipmap Filters + * @type {number} + */ +GameLib.D3.Texture.TYPE_NEAREST_FILTER = 1003; +GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER = 1004; +GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER = 1005; +GameLib.D3.Texture.TYPE_LINEAR_FILTER = 1006; +GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER = 1007; +GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER = 1008; + +/** + * Texture Data Types + * @type {number} + */ +GameLib.D3.Texture.TYPE_UNSIGNED_BYTE = 1009; +GameLib.D3.Texture.TYPE_BYTE = 1010; +GameLib.D3.Texture.TYPE_SHORT = 1011; +GameLib.D3.Texture.TYPE_UNSIGNED_SHORT = 1012; +GameLib.D3.Texture.TYPE_INT = 1013; +GameLib.D3.Texture.TYPE_UNSIGNED_INT = 1014; +GameLib.D3.Texture.TYPE_FLOAT = 1015; +GameLib.D3.Texture.TYPE_HALF_FLOAT = 1025; + +/** + * Encoding Modes + * @type {number} + */ +GameLib.D3.Texture.TYPE_LINEAR_ENCODING = 3000; // NO ENCODING AT ALL. +GameLib.D3.Texture.TYPE_SRGB_ENCODING = 3001; +GameLib.D3.Texture.TYPE_GAMMA_ENCODING = 3007; // USES GAMMA_FACTOR, FOR BACKWARDS COMPATIBILITY WITH WEBGLRENDERER.GAMMAINPUT/GAMMAOUTPUT +GameLib.D3.Texture.TYPE_RGBE_ENCODING = 3002; // AKA RADIANCE. +GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING = 3003; +GameLib.D3.Texture.TYPE_RGBM7_ENCODING = 3004; +GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005; +GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256. + + + +/** + * Defers loading of an image and resolves once image is loaded + * @param gameLibTexture + * @param threeMaterial + * @param threeMaterialMapType + * @returns {Promise} + */ +GameLib.D3.prototype.loadMap = function(gameLibTexture, threeMaterial, threeMaterialMapType) { + + var q = this.Q.defer(); + + var imagePath = null; + + if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.filename) { + /** + * Else, load from upload source + */ + imagePath = this.editorUrl + '/uploads' + this.path + '/' + gameLibTexture.image.filename; + } + + if (imagePath) { + + this.textureLoader.crossOrigin = ''; + + this.textureLoader.load( + imagePath, + function(texture) { + /** + * onLoad + */ + threeMaterial[threeMaterialMapType] = texture; + threeMaterial[threeMaterialMapType].name = gameLibTexture.name; + threeMaterial[threeMaterialMapType].anisotropy = gameLibTexture.anisotropy; + threeMaterial[threeMaterialMapType].encoding = gameLibTexture.encoding; + threeMaterial[threeMaterialMapType].flipY = gameLibTexture.flipY; + /** + * We don't restore the format since this changing from OS to OS and breaks the implementation sometimes + */ + threeMaterial[threeMaterialMapType].generateMipmaps = gameLibTexture.generateMipmaps; + threeMaterial[threeMaterialMapType].magFilter = gameLibTexture.magFilter; + threeMaterial[threeMaterialMapType].minFilter = gameLibTexture.minFilter; + threeMaterial[threeMaterialMapType].mapping = gameLibTexture.mapping; + threeMaterial[threeMaterialMapType].mipmaps = gameLibTexture.mipmaps; + threeMaterial[threeMaterialMapType].offset = new this.THREE.Vector2( + gameLibTexture.offset.x, + gameLibTexture.offset.y + ); + threeMaterial[threeMaterialMapType].premultiplyAlpha = gameLibTexture.premultiplyAlpha; + threeMaterial[threeMaterialMapType].textureType = gameLibTexture.textureType; + threeMaterial[threeMaterialMapType].wrapS = gameLibTexture.wrapS; + threeMaterial[threeMaterialMapType].wrapT = gameLibTexture.wrapT; + threeMaterial[threeMaterialMapType].unpackAlignment = gameLibTexture.unpackAlignment; + threeMaterial.needsUpdate = true; + q.resolve(true); + }, + function(xhr) { + /** + * onProgress + */ + if (this.editor) { + this.editor.setServerStatus(Math.round(xhr.loaded / xhr.total * 100) + '% complete', 'success'); + } + }, + function(error) { + /** + * onError + */ + console.log("an error occurred while trying to load the image : " + imagePath); + q.resolve(null); + } + ); + + } else { + q.resolve(null); + } + + return q.promise; +}; + + +/** + * Returns an array of image loading Promises + * @param blenderMaterial + * @param blenderMaps + * @param threeMaterial + * @returns Q[] + */ +GameLib.D3.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMaterial) { + + var textureMaps = []; + + for (var ti = 0; ti < blenderMaps.length; ti++) { + + var map = blenderMaps[ti]; + + if (blenderMaterial.maps.hasOwnProperty(map)) { + + var blenderTexture = blenderMaterial.maps[map]; + + if ( + blenderTexture && + blenderTexture.image && + blenderTexture.image.filename + ) { + + var threeMap = null; + + if (map == 'alpha') { + threeMap = 'alhpaMap'; + } + + if (map == 'ao') { + threeMap = 'aoMap'; + } + + if (map == 'bump') { + threeMap = 'bumpMap'; + } + + if (map == 'displacement') { + threeMap = 'displacementMap'; + } + + if (map == 'emissive') { + threeMap = 'emissiveMap'; + } + + if (map == 'environment') { + threeMap = 'envMap'; + } + + if (map == 'light') { + threeMap = 'lightMap'; + } + + if (map == 'specular') { + threeMap = 'specularMap'; + } + + if (map == 'diffuse') { + threeMap = 'map'; + } + + if (map == 'roughness') { + threeMap = 'roughnessMap'; + } + + if (map == 'metalness') { + threeMap = 'metalnessMap'; + } + + if (threeMap == null) { + console.warn("unsupported map type : " + map); + } + + textureMaps.push(this.loadMap(blenderMaterial.maps[map], threeMaterial, threeMap)); + } + } + } + + return textureMaps; +}; diff --git a/src/game-lib-triangle-edge.js b/src/game-lib-triangle-edge.js new file mode 100644 index 0000000..5aecd92 --- /dev/null +++ b/src/game-lib-triangle-edge.js @@ -0,0 +1,13 @@ +/** + * TriangleEdge + * @param triangle + * @param edge + * @constructor + */ +GameLib.D3.TriangleEdge = function( + triangle, + edge +) { + this.triangle = triangle; + this.edge = edge; +}; \ No newline at end of file diff --git a/src/game-lib-triangle-face.js b/src/game-lib-triangle-face.js new file mode 100644 index 0000000..aba5f52 --- /dev/null +++ b/src/game-lib-triangle-face.js @@ -0,0 +1,125 @@ +/** + * TriangleFace + * @param v0 + * @param v1 + * @param v2 + * @param materialIndex + * @param v0uv + * @param v1uv + * @param v2uv + * @param color + * @param vertexColors + * @param vertexNormals + * @param normal + * @constructor + */ +GameLib.D3.TriangleFace = function( + v0, + v1, + v2, + materialIndex, + v0uv, + v1uv, + v2uv, + color, + vertexColors, + vertexNormals, + normal +) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.materialIndex = materialIndex; + this.v0uv = v0uv; + this.v1uv = v1uv; + this.v2uv = v2uv; + if (!color) { + color = new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff); + } + this.color = color; + + if (!vertexColors) { + vertexColors = [ + new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), + new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff), + new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff) + ]; + } + this.vertexColors = vertexColors; + + if (!vertexNormals) { + vertexNormals = [ + new GameLib.D3.Vector3(), + new GameLib.D3.Vector3(), + new GameLib.D3.Vector3() + ] + } + this.vertexNormals = vertexNormals; + + if (!normal) { + normal = new GameLib.D3.Vector3(0); + } + + this.normal = normal; +}; + +/** + * Clone a TriangleFace + * @returns {GameLib.D3.TriangleFace} + */ +GameLib.D3.TriangleFace.prototype.clone = function(){ + return new GameLib.D3.TriangleFace( + this.v0, + this.v1, + this.v2, + this.materialIndex, + this.v0uv.copy(), + this.v1uv.copy(), + this.v2uv.copy() + ); +}; + +/** + * Returns true if two triangles are equal (their vertex indices match in some order) + * @param triangle + * @returns {boolean} + */ +GameLib.D3.TriangleFace.prototype.equals = function(triangle) { + return !!( + ( + (this.v0 == triangle.v0) && + (this.v1 == triangle.v1) && + (this.v2 == triangle.v2) + ) + || + ( + (this.v0 == triangle.v0) && + (this.v1 == triangle.v2) && + (this.v2 == triangle.v1) + ) + || + ( + (this.v0 == triangle.v1) && + (this.v1 == triangle.v0) && + (this.v2 == triangle.v2) + ) + || + ( + (this.v0 == triangle.v1) && + (this.v1 == triangle.v2) && + (this.v2 == triangle.v0) + ) + || + ( + (this.v0 == triangle.v2) && + (this.v1 == triangle.v0) && + (this.v2 == triangle.v1) + ) + || + ( + (this.v0 == triangle.v2) && + (this.v1 == triangle.v1) && + (this.v2 == triangle.v0) + )); +}; + diff --git a/src/game-lib-vector-2.js b/src/game-lib-vector-2.js new file mode 100644 index 0000000..460e5a9 --- /dev/null +++ b/src/game-lib-vector-2.js @@ -0,0 +1,27 @@ +GameLib.D3.Vector2 = function(x, y) { + + this.x = 0; + this.y = 0; + + if (x) { + this.x = x; + } + + if (y) { + this.y = y; + } +}; + +GameLib.D3.Vector2.prototype.copy = function() { + return new GameLib.D3.Vector2( + this.x, + this.y + ); +}; + +GameLib.D3.Vector2.prototype.equals = function(v) { + return !!(((this.x == v.x) && + (this.y == v.y)) || + ((this.y == v.x) && + (this.x == v.y))); +}; diff --git a/src/game-lib-vector-3.js b/src/game-lib-vector-3.js new file mode 100644 index 0000000..fee45c1 --- /dev/null +++ b/src/game-lib-vector-3.js @@ -0,0 +1,134 @@ +GameLib.D3.Vector3 = function(x, y, z) { + + this.x = 0; + this.y = 0; + this.z = 0; + + if (x) { + this.x = x; + } + + if (y) { + this.y = y; + } + + if (z) { + this.z = z; + } +}; + +GameLib.D3.Vector3.prototype.subtract = function (v) { + + if (v instanceof GameLib.D3.Vector3) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + } + + if (v instanceof GameLib.D3.Vector4) { + console.warn("trying to subtract vector of bigger length (4 vs 3))"); + } + + return this; +}; + +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.prototype.negative = function () { + this.x *= -1; + this.y *= -1; + this.z *= -1; + return this; +}; + +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); + + 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.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.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; + 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; + this.x = x; + this.y = y; + this.z = z; + } 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 / Math.sqrt(v2); + + this.x *= invLength; + this.y *= invLength; + this.z *= invLength; + + return this; +}; diff --git a/src/game-lib-vector-4-points.js b/src/game-lib-vector-4-points.js new file mode 100644 index 0000000..15fad95 --- /dev/null +++ b/src/game-lib-vector-4-points.js @@ -0,0 +1,224 @@ +GameLib.D3.Vector4.Points = function () { + this.vectors = []; +}; + +GameLib.D3.Vector4.Points.prototype.add = function (vector) { + + if (vector instanceof GameLib.D3.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.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.Vector3( + averageX / this.vectors.length, + averageY / this.vectors.length, + averageZ / this.vectors.length + ); +}; + +GameLib.D3.Vector4.Points.prototype.negative = 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().negative(); + + 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-vector-4.js b/src/game-lib-vector-4.js new file mode 100644 index 0000000..18ee60f --- /dev/null +++ b/src/game-lib-vector-4.js @@ -0,0 +1,99 @@ +GameLib.D3.Vector4 = function(x, y, z, w) { + + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + + if (x) { + this.x = x; + } + + if (y) { + this.y = y; + } + + if (z) { + this.z = z; + } + + if (w) { + this.w = w; + } +}; + +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 () { + + // 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.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; +}; + diff --git a/src/game-lib-vertex.js b/src/game-lib-vertex.js new file mode 100644 index 0000000..2e09dae --- /dev/null +++ b/src/game-lib-vertex.js @@ -0,0 +1,13 @@ +/** + * The normal gets assigned when the face calculates its normal + * @param position + * @param boneWeights GameLib.D3.BoneWeight[] + * @constructor + */ +GameLib.D3.Vertex = function( + position, + boneWeights +) { + this.position = position; + this.boneWeights = boneWeights; +}; \ No newline at end of file diff --git a/src/game-lib-world.js b/src/game-lib-world.js new file mode 100644 index 0000000..d9f8854 --- /dev/null +++ b/src/game-lib-world.js @@ -0,0 +1,448 @@ +/** + * World SuperSet - contains the custom world instance + * @param id + * @param name + * @param engine + * @param gravity + * @param broadphase + * @param solver + * @param rigidBodies + * @constructor + */ +GameLib.D3.World = function( + id, + name, + engine, + gravity, + broadphase, + solver, + rigidBodies +) { + + this.id = id; + + this.name = name; + + if (typeof gravity == 'undefined') { + gravity = new GameLib.D3.Vector3(0, -9.81, 0); + } + this.gravity = gravity; + + if (typeof broadphase == 'undefined') { + broadphase = new GameLib.D3.Physics.Broadphase( + null, + 'broadPhaseNaive', + GameLib.D3.Physics.BROADPHASE_TYPE_NAIVE + ); + } + this.broadphase = broadphase; + + if (typeof solver == 'undefined') { + solver = new GameLib.D3.Physics.Solver( + null, + 'GSSolver', + GameLib.D3.Physics.GS_SOLVER + ); + } + this.solver = solver; + + if (typeof rigidBodies == 'undefined') { + rigidBodies = []; + } + this.rigidBodies = rigidBodies; + + this.engine = null; + + this.worldInstance = null; + + /** + * We only set the physics property if we pass it in the constructor, + * because we don't always want the physics object (ex. when we store this world to the API - we also don't then + * want to store the custom worlds - we want to generate them after loading from API) + */ + if (engine) { + this.engine = engine; + this.worldInstance = this.createWorldInstance(); + } +}; + + +GameLib.D3.World.prototype.createWorldInstance = function() { + + this.engine.isNotCannonThrow(); + + var customWorld = new this.engine.instance.World(); + + var cannonBroadphase = null; + + if (this.broadphase.broadphaseType == GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE) { + cannonBroadphase = new this.engine.instance.NaiveBroadphase(); + } else if (this.broadphase.broadphaseType == GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID) { + cannonBroadphase = new this.engine.instance.GridBroadphase(); + } else if (this.broadphase.broadphaseType == GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP) { + cannonBroadphase = new this.engine.instance.SAPBroardphase(); + } else { + console.warn('Unsupported broadphase type: ' + this.broadphase.broadphaseType); + throw new Error('Unsupported broadphase type: ' + this.broadphase.broadphaseType); + } + + customWorld.broadphase = cannonBroadphase; + + var cannonSolver = null; + + if (this.solver.solverType == GameLib.D3.Physics.SPLIT_SOLVER) { + cannonSolver = new this.engine.instance.SplitSolver(); + } else if (this.solver.solverType == GameLib.D3.Physics.GS_SOLVER) { + cannonSolver = new this.engine.instance.GSSolver(); + cannonSolver.iterations = this.solver.iterations; + } + + customWorld.solver = cannonSolver; + + customWorld.gravity.x = this.gravity.x; + customWorld.gravity.y = this.gravity.y; + customWorld.gravity.z = this.gravity.z; + + for (var b = 0; b < this.rigidBodies.length; b++) { + + var customBody = this.createCustomBody(this.rigidBodies[b]); + + //customWorld.AddRigidBody(); + } + + customWorld.name = this.name; + + return customWorld; +}; + +GameLib.D3.Physics.World.prototype.AddShape = function( + shape, // d3.physics.shape + rigidBody, + offset, // vec3 + orientation //quaternion +) { + shape.shape = shape; + + /** + * TODO:: fix this? + */ + if (this.physics.engineType === GameLib.D3.Physics.TYPE_CANNON) { + + var _offset = null; + var _orientation = null; + + if(offset != null && typeof offset !== 'undefined') { + _offset = new this.physics.CANNON.Vec3(offset.x, offset.y, offset.z); + } + + if(orientation != null && typeof orientation !== 'undefined') { + _orientation = new this.physics.CANNON.Quaternion(orientation.x, orientation.y, orientation.z, orientation.w); + } + + rigidBody.bodyObject.addShape(shape.shapeObject, _offset, _orientation); + } +}; + +GameLib.D3.Physics.World.prototype.Wheel = function() { + +}; + +GameLib.D3.Physics.World.prototype.CreateRigidVehicle = function( + chassisBody // Physics.RigidBody +) { + var rigidVehicle = new GameLib.D3.Physics.RigidVehicle(); + + if (this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + var vehicle = new this.physics.CANNON.RigidVehicle({ + chassisBody: chassisBody.bodyObject + }); + rigidVehicle.vehicleObject = vehicle; + return rigidVehicle; + } +}; + +GameLib.D3.Physics.World.prototype.CreateRaycastVehicle = function( + chassisBody // Physics.RigidBody +) { + var raycastVehicle = new GameLib.D3.Physics.RaycastVehicle(); + + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + var vehicle = new this.physics.CANNON.RaycastVehicle({ + chassisBody: chassisBody.bodyObject + }); + raycastVehicle.vehicleObject = vehicle; + return raycastVehicle; + } +}; + +GameLib.D3.Physics.World.prototype.AddWheelToRigidVehicle = function( + vehicle, + rigidBody, + position, + axis, + direction +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + vehicle.vehicleObject.addWheel({ + body: rigidBody.bodyObject, + position: new this.physics.CANNON.Vec3(position.x, position.y, position.z), + axis: new this.physics.CANNON.Vec3(axis.x, axis.y, axis.z), + direction: new this.physics.CANNON.Vec3(direction.x, direction.y, direction.z) + }); + } +}; + +GameLib.D3.Physics.World.prototype.AddWheelToRaycastVehicle = function ( + vehicle, // physics.raycastvehicle + options // cannon options +) { + if (this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + vehicle.vehicleObject.addWheel(options); + } else { + console.log("function for engine not implemented"); + } +}; + +GameLib.D3.Physics.World.prototype.RigidVehicle.prototype.GetWheelInfo = function( + +) { + // note: need a way to determine which engine we are currently using + return this.vehicleObject.wheelBodies; +}; + +GameLib.D3.Physics.World.prototype.RaycastVehicle.prototype.GetWheelInfo = function( + +) { + // note: need a way to determine which engine we are currently using + return this.vehicleObject.wheelInfos; +}; + + +GameLib.D3.Physics.World.prototype.CreateTriMeshShape = function( + vertices, // flat list of floats + indices // flat list of floats +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Trimesh(vertices, indices), GameLib.D3.Physics.SHAPE_TYPE_TRIMESH); + } +}; + +GameLib.D3.Physics.World.prototype.CreateSphereShape = function ( + radius +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Sphere(radius), GameLib.D3.Physics.SHAPE_TYPE_SPHERE); + } +}; + +GameLib.D3.Physics.World.prototype.CreateBoxShape = function( + halfExtensions // vec3 +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Box(new this.physics.CANNON.Vec3(halfExtensions.x, halfExtensions.y, halfExtensions.z)), GameLib.D3.Physics.SHAPE_TYPE_BOX); + } +}; + +GameLib.D3.Physics.World.prototype.CreateCylinderShape = function( + radiusTop, + radiusBottom, + height, + numSegments +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + return new GameLib.D3.Physics.Shape(new this.physics.CANNON.Cylinder(radiusTop, radiusBottom, height, numSegments), GameLib.D3.Physics.SHAPE_TYPE_CYLINDER); + } +}; + +GameLib.D3.Physics.World.prototype.AddRigidBody = function( + rigidBody // Physics.RigidBody +) { + if(this.physics.engineType === GameLib.D3.Physics.TYPE_CANNON) { + this.worldObject.addBody(rigidBody.bodyObject); + } +}; + +GameLib.D3.Physics.World.prototype.AddVehicle = function( + vehicle // note: physics.vehicle +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + vehicle.vehicleObject.addToWorld(this.worldObject); + } +}; + +GameLib.D3.Physics.World.prototype.Step = function( + timeStep +) { + if(this.physics.engineType == GameLib.D3.Physics.TYPE_CANNON) { + + // todo: figure out, why this call to internal step is more stable for trimesh collisions..... + //this.worldObject.internalStep(timeStep); + //return; + + var now = performance.now() / 1000; + + if(!this.lastCallTime){ + // last call time not saved, cant guess elapsed time. Take a simple step. + this.worldObject.step(timeStep); + this.lastCallTime = now; + return; + } + + var timeSinceLastCall = now - this.lastCallTime; + + this.worldObject.step(timeStep, timeSinceLastCall); + + this.lastCallTime = now; + } +}; + +GameLib.D3.Physics.World.prototype.GetIndexedVertices = function( + triangleMeshShape +) { + + if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) { + + return { + vertices : triangleMeshShape.vertices, + indices : triangleMeshShape.indices + }; + + } else { + // todo: implement this for other physics engines. + return null; + } + +}; + +GameLib.D3.Physics.World.prototype.GenerateWireframeViewMesh = function( + triangleMeshShape, + normalLength, + scale, + opacity, + wireframeColor +) { + var geometryTHREE = new THREE.Geometry(); + var wireframeTHREEMesh = new THREE.Mesh + ( + geometryTHREE, + new THREE.MeshBasicMaterial({ + color: wireframeColor ? wireframeColor : 0xfefefe, + wireframe: true, + opacity: opacity ? opacity : 0.5 + }) + ); + + var data = this.GetIndexedVertices(triangleMeshShape); + + for(var i = 0, l = data.vertices.length / 3; i < l; i++) { + geometryTHREE.vertices.push(new THREE.Vector3(data.vertices[i * 3], data.vertices[i * 3 + 1], data.vertices[i * 3 + 2])); + } + + for(var i = 0, l = data.indices.length / 3; i < l; i++) { + var i0 = data.indices[i * 3]; + var i1 = data.indices[i * 3 + 1]; + var i2 = data.indices[i * 3 + 2]; + + geometryTHREE.faces.push(new THREE.Face3(i0, i1, i2)); + + // Create debug view for normals + + // Center point on the mesh itself + var centroid = new THREE.Vector3() + .add(geometryTHREE.vertices[i0]) + .add(geometryTHREE.vertices[i1]) + .add(geometryTHREE.vertices[i2]) + .divideScalar(3); + + var normal = null; + if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) { + var normal = new this.physics.CANNON.Vec3(); + triangleMeshShape.getNormal(i, normal); + } else { + // todo: calculate the normal for v0, v1 & v2 here. + } + + var arrow = new THREE.ArrowHelper(new THREE.Vector3(normal.x, normal.y, normal.z), centroid, normalLength, new THREE.Color(normal.x, normal.y, normal.z)); + wireframeTHREEMesh.add( arrow ); + } + + wireframeTHREEMesh.scale.x = scale.x; + wireframeTHREEMesh.scale.y = scale.y; + wireframeTHREEMesh.scale.z = scale.z; + + return wireframeTHREEMesh; +}; + +GameLib.D3.Physics.World.prototype.GenerateTriangleCollisionMesh = function( + threeMesh, + mass, // default = 0 + friction, // default = 10 + createCollisionSubMeshes, // boolean. default = false + facesPerSubsection, // int. default = 0 + subsectionsToMerge // int. default = 0 +) { + var processedFaces = 0; + var facesPerSubSection = facesPerSubsection || 0; + var subMeshesToMerge = subsectionsToMerge || 0; + var totalAmtFaces = threeMesh.geometry.faces.length; + var facesToProcess = createCollisionSubMeshes ? (subMeshesToMerge * facesPerSubSection) : totalAmtFaces; + + var pairs = []; // output + + var vertices = []; + var indicies = []; + + for(var i = 0; i <= totalAmtFaces; i++) { + if(processedFaces == facesToProcess || i == totalAmtFaces) { + + var body = null; + + if(this.engine.engineType == GameLib.D3.Physics.TYPE_CANNON) { + + var meshShape = new this.physics.CANNON.Trimesh(vertices, indicies); + meshShape.setScale(new this.physics.CANNON.Vec3(threeMesh.scale.x, threeMesh.scale.y, threeMesh.scale.z)); + meshShape.updateAABB(); + meshShape.updateNormals(); + meshShape.updateEdges(); + meshShape.updateBoundingSphereRadius(); + meshShape.updateTree(); + + body = new this.physics.CANNON.Body({ mass: mass ? mass : 0, friction: friction ? friction : 10 }); + body.addShape(meshShape); + + } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_AMMO) { + + } else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_GOBLIN) { + + } + + pairs.push({ + threeObject : createCollisionSubMeshes ? null : threeMesh, + physicsObject : body + }); + + vertices = []; + indicies = []; + processedFaces = 0; + + if(i == totalAmtFaces) { + return pairs; + } + } + + var face = threeMesh.geometry.faces[i]; + indicies.push(indicies.length); + indicies.push(indicies.length); + indicies.push(indicies.length); + + var v0 = threeMesh.geometry.vertices[face.a]; + var v1 = threeMesh.geometry.vertices[face.b]; + var v2 = threeMesh.geometry.vertices[face.c]; + + vertices.push(v0.x, v0.y, v0.z); + vertices.push(v1.x, v1.y, v1.z); + vertices.push(v2.x, v2.y, v2.z); + + processedFaces++; + } +}; diff --git a/src/game-lib-z.js b/src/game-lib-z.js new file mode 100644 index 0000000..771958c --- /dev/null +++ b/src/game-lib-z.js @@ -0,0 +1,3 @@ +if (typeof module !== 'undefined') { + module.exports = GameLib; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..f462b5b --- /dev/null +++ b/src/index.js @@ -0,0 +1,94 @@ +if (typeof GameLib === 'undefined') { + function GameLib() {} +} + +if (typeof GameLib.D3 === 'undefined') { + GameLib.D3 = function() {}; +} + +if (typeof require != 'undefined') { + GameLib.D3.Bone = require('./game-lib-bone.js'); + GameLib.D3.BoneWeight = require('./game-lib-bone-weight'); + GameLib.D3.Broadphase = require('./game-lib-broadphase'); + GameLib.D3.Color = require('./game-lib-color'); + GameLib.D3.FlyControls = require('./game-lib-fly-controls'); + GameLib.D3.Engine = require('./game-lib-engine'); + GameLib.D3.Game = require('./game-lib-game'); + GameLib.D3.Heightmap = require('./game-lib-heightmap'); + GameLib.D3.Image = require('./game-lib-image'); + GameLib.D3.Light = require('./game-lib-light'); + GameLib.D3.Material = require('./game-lib-material'); + GameLib.D3.Matrix3 = require('./game-lib-matrix-3'); + GameLib.D3.Matrix4 = require('./game-lib-matrix-4'); + GameLib.D3.Mesh = require('./game-lib-mesh'); + GameLib.D3.Physics = require('./game-lib-physics'); + GameLib.D3.PolyVertex = require('./game-lib-poly-vertex'); + GameLib.D3.RaycastVehicle = require('./game-lib-raycast-vehicle'); + GameLib.D3.RigidBody = require('./game-lib-rigid-body'); + GameLib.D3.RigidBodyVehicle = require('./game-lib-rigid-body-vehicle'); + GameLib.D3.Scene = require('./game-lib-scene'); + GameLib.D3.Shape = require('./game-lib-shape'); + GameLib.D3.Skeleton = require('./game-lib-skeleton'); + GameLib.D3.SkyBox = require('./game-lib-sky-box'); + GameLib.D3.Solver = require('./game-lib-solver'); + GameLib.D3.Texture = require('./game-lib-texture'); + GameLib.D3.TriangleEdge = require('./game-lib-triangle-edge'); + GameLib.D3.TriangleFace = require('./game-lib-triangle-face'); + GameLib.D3.Vector2 = require('./game-lib-vector-2'); + GameLib.D3.Vector3 = require('./game-lib-vector-3'); + GameLib.D3.Vector4 = require('./game-lib-vector-4'); + GameLib.D3.Vector4.Points = require('./game-lib-vector-4-points'); + GameLib.D3.Vertex = require('./game-lib-vertex'); + GameLib.D3.World = require('./game-lib-world'); +} + +if (typeof module != 'undefined') { + module.exports = GameLib; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +if (typeof module != 'undefined') { + module.exports = GameLib; +} \ No newline at end of file