From ce4b1cd2601e0cd9394dc199ea5508760ba8034a Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Mon, 11 Sep 2017 17:47:32 +0200 Subject: [PATCH] awesome - sphere shape and plane shape physics working --- src/game-lib-a-1-event.js | 23 +- src/game-lib-a-component-a.js | 54 ++-- src/game-lib-d3-api-mesh.js | 4 +- src/game-lib-d3-api-physics-world.js | 10 +- src/game-lib-d3-custom-code.js | 4 +- src/game-lib-d3-mesh-0.js | 176 +++++++------ src/game-lib-d3-mesh-box.js | 4 + src/game-lib-d3-mesh-cylinder.js | 9 + src/game-lib-d3-mesh-plane.js | 44 ++++ src/game-lib-d3-mesh-sphere.js | 68 +++++ src/game-lib-d3-physics-world.js | 4 +- src/game-lib-d3-rigid-body.js | 15 +- src/game-lib-quaternion.js | 31 +++ src/game-lib-system-gui.js | 8 +- src/game-lib-system-physics.js | 77 ++++-- src/game-lib-system-storage.js | 369 +++++++++++++++------------ src/game-lib-vector3.js | 6 + 17 files changed, 605 insertions(+), 301 deletions(-) diff --git a/src/game-lib-a-1-event.js b/src/game-lib-a-1-event.js index ac4e4cc..b7da5d1 100644 --- a/src/game-lib-a-1-event.js +++ b/src/game-lib-a-1-event.js @@ -78,6 +78,8 @@ GameLib.Event.VISUALIZE = 0x3c; GameLib.Event.STOP_VISUALIZE = 0x3d; GameLib.Event.FETCH_COMPONENT_TYPES = 0x3e; GameLib.Event.FETCH_COMPONENTS = 0x3f; +GameLib.Event.GET_API_URL = 0x40; +GameLib.Event.GET_PHYSICS_ENGINE = 0x41; /** * Returns string name of event ID @@ -151,6 +153,8 @@ GameLib.Event.GetEventName = function(number) { case 0x3d : return 'stop_visualize'; case 0x3e : return 'fetch_component_types'; case 0x3f : return 'fetch_components'; + case 0x40 : return 'get_api_url'; + case 0x41 : return 'get_physics_engine'; break; } @@ -326,13 +330,22 @@ GameLib.Event.EmitInstanceEvents = function(component) { * Publish some event happened with some data * @param eventName * @param data + * @param clientCallback + * @param clientErrorCallback * @returns {number} of callbacks executed */ GameLib.Event.prototype.publish = function( eventName, - data + data, + clientCallback, + clientErrorCallback ) { - return GameLib.Event.Emit(eventName, data); + return GameLib.Event.Emit( + eventName, + data, + clientCallback, + clientErrorCallback + ); }; /** @@ -362,6 +375,12 @@ GameLib.Event.Emit = function( } } ) + } else { + if (clientErrorCallback) { + clientErrorCallback({ + message : 'No subscriptions for event ' + eventName + }) + } } return count; diff --git a/src/game-lib-a-component-a.js b/src/game-lib-a-component-a.js index 9bdc86a..adea05c 100644 --- a/src/game-lib-a-component-a.js +++ b/src/game-lib-a-component-a.js @@ -330,30 +330,44 @@ GameLib.Component.prototype.getStorageDependencies = function() { GameLib.Component.prototype.save = function() { - this.buildIdToObject(); + this.publish( + GameLib.Event.GET_API_URL, + null, + function(data) { + this.buildIdToObject(); - for (var property in this.idToObject) { - if ( - this.idToObject.hasOwnProperty(property) && - this.idToObject[property] instanceof GameLib.Component - ) { + for (var property in this.idToObject) { + if ( + this.idToObject.hasOwnProperty(property) && + this.idToObject[property] instanceof GameLib.Component + ) { - var apiObject = this.idToObject[property].toApiObject(); + var apiObject = this.idToObject[property].toApiObject(); - apiObject.componentType = this.idToObject[property].componentType; + apiObject.componentType = this.idToObject[property].componentType; - var storageDependencies = this.idToObject[property].getStorageDependencies(); + var storageDependencies = this.idToObject[property].getStorageDependencies(); - for (var storageProperty in storageDependencies) { - if (storageDependencies.hasOwnProperty(storageProperty)) { - apiObject[storageProperty] = storageDependencies[storageProperty]; - } - } + for (var storageProperty in storageDependencies) { + if (storageDependencies.hasOwnProperty(storageProperty)) { + apiObject[storageProperty] = storageDependencies[storageProperty]; + } + } + + this.publish( + GameLib.Event.SAVE_COMPONENT, + { + apiUrl : data.apiUrl, + apiObject : apiObject + } + ); + } + } + }.bind(this), + function(error) { + console.error(error); + throw new Error('Failed to get API URL: ' + error.message); + } + ); - this.publish( - GameLib.Event.SAVE_COMPONENT, - apiObject - ); - } - } }; \ No newline at end of file diff --git a/src/game-lib-d3-api-mesh.js b/src/game-lib-d3-api-mesh.js index b635ff0..0b721c0 100644 --- a/src/game-lib-d3-api-mesh.js +++ b/src/game-lib-d3-api-mesh.js @@ -59,7 +59,7 @@ GameLib.D3.API.Mesh = function( this.meshType = meshType; if (GameLib.Utils.UndefinedOrNull(name)) { - name = 'Mesh ' + id; + name = 'Mesh (' + id + ')'; } this.name = name; @@ -99,7 +99,7 @@ GameLib.D3.API.Mesh = function( this.skinWeights = skinWeights; if (GameLib.Utils.UndefinedOrNull(materials)) { - materials = [new GameLib.D3.API.Material(null, GameLib.D3.Material.MATERIAL_TYPE_STANDARD, 'Material Mesh (' + this.id + ')')]; + materials = [new GameLib.D3.API.Material(null, GameLib.D3.Material.MATERIAL_TYPE_STANDARD, 'Material (' + this.name + ')')]; } this.materials = materials; diff --git a/src/game-lib-d3-api-physics-world.js b/src/game-lib-d3-api-physics-world.js index 46fabea..2a2eb7a 100644 --- a/src/game-lib-d3-api-physics-world.js +++ b/src/game-lib-d3-api-physics-world.js @@ -37,12 +37,18 @@ GameLib.D3.API.PhysicsWorld = function( this.gravity = gravity; if (GameLib.Utils.UndefinedOrNull(broadphase)) { - broadphase = null; + broadphase = new GameLib.D3.API.Broadphase( + null, + 'Broadphase (Physics World ' + this.id + ')' + ); } this.broadphase = broadphase; if (GameLib.Utils.UndefinedOrNull(solver)) { - solver = null; + solver = new GameLib.D3.API.Solver( + null, + 'Solver (Physics World ' + this.id + ')' + ) } this.solver = solver; diff --git a/src/game-lib-d3-custom-code.js b/src/game-lib-d3-custom-code.js index 1716914..e72df06 100644 --- a/src/game-lib-d3-custom-code.js +++ b/src/game-lib-d3-custom-code.js @@ -42,7 +42,7 @@ GameLib.D3.CustomCode.prototype.constructor = GameLib.D3.CustomCode; GameLib.D3.CustomCode.prototype.createInstance = function() { try { - var instance = new Function('data', this.code); + var instance = new Function('data', this.code).bind(this); return instance; } catch (error) { /** @@ -58,7 +58,7 @@ GameLib.D3.CustomCode.prototype.createInstance = function() { */ GameLib.D3.CustomCode.prototype.updateInstance = function() { try { - this.instance = new Function('data', this.code); + this.instance = new Function('data', this.code).bind(this); this.publish( GameLib.Event.COMPILE_SUCCESS, { diff --git a/src/game-lib-d3-mesh-0.js b/src/game-lib-d3-mesh-0.js index 9504356..765c1f5 100644 --- a/src/game-lib-d3-mesh-0.js +++ b/src/game-lib-d3-mesh-0.js @@ -177,6 +177,8 @@ GameLib.D3.Mesh = function ( */ this.helper = null; + this.updateRotationFromAxisAngle = true; + GameLib.Component.call( this, componentType, @@ -529,14 +531,22 @@ GameLib.D3.Mesh.prototype.updateInstance = function() { this.instance.geometry = this.createInstanceGeometry(this.instance.geometry); } - this.quaternion.axis.instance.x = this.quaternion.axis.x; - this.quaternion.axis.instance.y = this.quaternion.axis.y; - this.quaternion.axis.instance.z = this.quaternion.axis.z; - // - // var v = new THREE.Vector3(); - // v.applyAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); - - this.quaternion.instance.setFromAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); + if (this.updateRotationFromAxisAngle) { + this.quaternion.axis.instance.x = this.quaternion.axis.x; + this.quaternion.axis.instance.y = this.quaternion.axis.y; + this.quaternion.axis.instance.z = this.quaternion.axis.z; + this.quaternion.instance.setFromAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); + this.instance.quaternion.copy(this.quaternion.instance); + this.quaternion.x = this.quaternion.instance.x; + this.quaternion.y = this.quaternion.instance.y; + this.quaternion.z = this.quaternion.instance.z; + this.quaternion.w = this.quaternion.instance.w; + } else { + this.instance.quaternion.x = this.quaternion.x; + this.instance.quaternion.y = this.quaternion.y; + this.instance.quaternion.z = this.quaternion.z; + this.instance.quaternion.w = this.quaternion.w; + } if (this.parentMesh && this.parentMesh.loaded) { @@ -548,25 +558,12 @@ GameLib.D3.Mesh.prototype.updateInstance = function() { this.instance.position.y = this.localPosition.y; this.instance.position.z = this.localPosition.z; - // this.localRotation.x = this.localRotation.instance.x; - // this.localRotation.y = this.localRotation.instance.y; - // this.localRotation.z = this.localRotation.instance.z; - - // this.instance.rotation.x = this.localRotation.x; - // this.instance.rotation.y = this.localRotation.y; - // this.instance.rotation.z = this.localRotation.z; - this.instance.scale.x = this.localScale.x; this.instance.scale.y = this.localScale.y; this.instance.scale.z = this.localScale.z; } else { - // this.localRotation.instance.applyAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); - // this.localRotation.x = this.localRotation.instance.x; - // this.localRotation.y = this.localRotation.instance.y; - // this.localRotation.z = this.localRotation.instance.z; - this.instance.position.x = this.position.x + this.localPosition.x; this.instance.position.y = this.position.y + this.localPosition.y; this.instance.position.z = this.position.z + this.localPosition.z; @@ -575,13 +572,7 @@ GameLib.D3.Mesh.prototype.updateInstance = function() { this.instance.scale.y = this.scale.y * this.localScale.y; this.instance.scale.z = this.scale.z * this.localScale.z; - - // this.instance.rotateX(this.localRotation.x); - // this.instance.rotateY(this.localRotation.y); - // this.instance.rotateZ(this.localRotation.z); - } - - this.instance.quaternion.copy(this.quaternion.instance); + } this.instance.up.x = this.up.x; this.instance.up.y = this.up.y; @@ -879,9 +870,11 @@ GameLib.D3.Mesh.prototype.createInstanceDefaults = function(instance) { instance.position.y = this.localPosition.y; instance.position.z = this.localPosition.z; - instance.rotation.x = this.localRotation.x; - instance.rotation.y = this.localRotation.y; - instance.rotation.z = this.localRotation.z; + instance.quaternion.x = this.quaternion.x; + instance.quaternion.y = this.quaternion.y; + instance.quaternion.z = this.quaternion.z; + instance.quaternion.w = this.quaternion.w; + instance.quaternion.setFromAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); instance.scale.x = this.localScale.x; instance.scale.y = this.localScale.y; @@ -896,6 +889,7 @@ GameLib.D3.Mesh.prototype.createInstanceDefaults = function(instance) { instance.quaternion.y = this.quaternion.y; instance.quaternion.z = this.quaternion.z; instance.quaternion.w = this.quaternion.w; + instance.quaternion.setFromAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); instance.position.x = this.position.x + this.localPosition.x; instance.position.y = this.position.y + this.localPosition.y; @@ -908,10 +902,6 @@ GameLib.D3.Mesh.prototype.createInstanceDefaults = function(instance) { instance.up.x = this.up.x; instance.up.y = this.up.y; instance.up.z = this.up.z; - - instance.rotateX(this.localRotation.x); - instance.rotateY(this.localRotation.y); - instance.rotateZ(this.localRotation.z); } instance.renderOrder = this.renderOrder; @@ -1044,40 +1034,54 @@ GameLib.D3.Mesh.prototype.applyLocalPositionRotationScale = function() { this.instance.geometry.applyMatrix(this.instance.matrix); - this.instance.position.set(0,0,0); - this.instance.rotation.set(0,0,0); + this.position.x = 0; + this.position.y = 0; + this.position.z = 0; + + this.scale.x = 1; + this.scale.y = 1; + this.scale.z = 1; + + this.quaternion.axis.x = 0; + this.quaternion.axis.y = 0; + this.quaternion.axis.z = 0; + this.quaternion.axis.w = 1; + this.quaternion.angle = 0; + + this.instance.position.set(0,0,0); + this.instance.quaternion.setFromAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); this.instance.scale.set(1,1,1); this.instance.updateMatrix(); this.updateVerticesFromGeometryInstance(this.instance.geometry); - var geometry = this.createInstanceGeometry(); + // var geometry = this.createInstanceGeometry(); + // + // /** + // * The face normals got re-calculated - so update again the faces + // */ + // this.updateVerticesFromGeometryInstance(this.instance.geometry); + // + // this.instance.geometry = geometry; - /** - * The face normals got re-calculated - so update again the faces - */ - this.updateVerticesFromGeometryInstance(this.instance.geometry); - - this.instance.geometry = geometry; - - this.position.x = 0; - this.position.y = 0; - this.position.z = 0; - - this.localPosition.x = 0; - this.localPosition.y = 0; - this.localPosition.z = 0; - - this.localRotation.x = 0; - this.localRotation.y = 0; - this.localRotation.z = 0; - - this.localScale.x = 1; - this.localScale.y = 1; - this.localScale.z = 1; - - this.updateInstance(); + // this.position.x = 0; + // this.position.y = 0; + // this.position.z = 0; + // + // this.localPosition.x = 0; + // this.localPosition.y = 0; + // this.localPosition.z = 0; + // + // this.localRotation.x = 0; + // this.localRotation.y = 0; + // this.localRotation.z = 0; + // + // this.localScale.x = 1; + // this.localScale.y = 1; + // this.localScale.z = 1; + // + // this.updateInstance(); // // this.localPosition.x = this.instance.position.x; // this.localPosition.y = this.instance.position.y; @@ -1106,7 +1110,7 @@ GameLib.D3.Mesh.prototype.applyLocalPositionRotationScale = function() { /** - * Gets all children components of this Mesh + * Gets all children components of this Mesh (all linked objects only - no object references i.e. string ids) * @returns {Array} */ GameLib.D3.Mesh.prototype.getChildrenComponents = function() { @@ -1116,28 +1120,32 @@ GameLib.D3.Mesh.prototype.getChildrenComponents = function() { this.materials.map( function (material) { - GameLib.Utils.PushUnique(components, material); + if (material instanceof GameLib.D3.Material) { + GameLib.Utils.PushUnique(components, material); - for (var property in material.linkedObjects) { - if ( - material.linkedObjects.hasOwnProperty(property) && - material.hasOwnProperty(property) && - material[property] && - property !== 'parentEntity' - ) { - GameLib.Utils.PushUnique(components, material[property]); - for (var tProperty in material[property].linkedObjects) { - if ( - material[property].linkedObjects.hasOwnProperty(tProperty) && - material[property].hasOwnProperty(tProperty) && - material[property][tProperty] && - tProperty !== 'parentEntity' - ) { - GameLib.Utils.PushUnique(components, material[property][tProperty]); - } - } - } - } + for (var property in material.linkedObjects) { + if ( + material.linkedObjects.hasOwnProperty(property) && + material.hasOwnProperty(property) && + material[property] && + typeof material[property] !== 'string' && + property !== 'parentEntity' + ) { + GameLib.Utils.PushUnique(components, material[property]); + for (var tProperty in material[property].linkedObjects) { + if ( + material[property].linkedObjects.hasOwnProperty(tProperty) && + material[property].hasOwnProperty(tProperty) && + material[property][tProperty] && + typeof material[property][tProperty] !== 'string' && + tProperty !== 'parentEntity' + ) { + GameLib.Utils.PushUnique(components, material[property][tProperty]); + } + } + } + } + } }.bind(this) ); diff --git a/src/game-lib-d3-mesh-box.js b/src/game-lib-d3-mesh-box.js index f516a63..a62c458 100644 --- a/src/game-lib-d3-mesh-box.js +++ b/src/game-lib-d3-mesh-box.js @@ -72,6 +72,10 @@ GameLib.D3.Mesh.Box.prototype.updateInstance = function() { this.instance.userData.height !== this.height || this.instance.userData.depth !== this.depth ) { + this.instance.userData.width = this.width; + this.instance.userData.height = this.height; + this.instance.userData.depth = this.depth; + var geometry = new THREE.BoxGeometry( this.width, this.height, diff --git a/src/game-lib-d3-mesh-cylinder.js b/src/game-lib-d3-mesh-cylinder.js index c0a048b..d1bec8e 100644 --- a/src/game-lib-d3-mesh-cylinder.js +++ b/src/game-lib-d3-mesh-cylinder.js @@ -121,6 +121,15 @@ GameLib.D3.Mesh.Cylinder.prototype.updateInstance = function() { this.instance.userData.thetaStart !== this.thetaStart || this.instance.userData.thetaLength !== this.thetaLength ) { + this.instance.userData.radiusTop = this.radiusTop; + this.instance.userData.radiusBottom = this.radiusBottom; + this.instance.userData.height = this.height; + this.instance.userData.radiusSegments = this.radiusSegments; + this.instance.userData.heightSegments = this.heightSegments; + this.instance.userData.openEnded = this.openEnded; + this.instance.userData.thetaStart = this.thetaStart; + this.instance.userData.thetaLength = this.thetaLength; + var geometry = new THREE.CylinderGeometry( this.radiusTop, this.radiusBottom, diff --git a/src/game-lib-d3-mesh-plane.js b/src/game-lib-d3-mesh-plane.js index cc803be..a28e0f3 100644 --- a/src/game-lib-d3-mesh-plane.js +++ b/src/game-lib-d3-mesh-plane.js @@ -275,3 +275,47 @@ GameLib.D3.Mesh.Plane.prototype.generateHeightMapFromBumpMap = function() { // this.updateInstance(); }; + +GameLib.D3.Mesh.Plane.prototype.createPhysicsObjects = function() { + + GameLib.Event.Emit( + GameLib.Event.GET_PHYSICS_ENGINE, + null, + function(data){ + var apiShapeSphere = new GameLib.D3.API.Shape( + null, + 'Shape Plane (' + this.name + ')' + ); + + apiShapeSphere.parentMesh = this; + + var shapeSphere = new GameLib.D3.Shape.Plane( + data.physics, + apiShapeSphere, + this.radius + ); + + var apiRigidBody = new GameLib.D3.API.RigidBody( + null, + 'Rigid Body (' + this.name + ')' + ); + + apiRigidBody.shapes.push(shapeSphere); + + var rigidBody = new GameLib.D3.RigidBody( + data.physics, + apiRigidBody + ); + + rigidBody.parentMesh = this; + + }.bind(this), + function(error){ + console.log(error.message); + throw new Error(error.message); + } + ); + + + +}; \ No newline at end of file diff --git a/src/game-lib-d3-mesh-sphere.js b/src/game-lib-d3-mesh-sphere.js index bccacc6..6a87671 100644 --- a/src/game-lib-d3-mesh-sphere.js +++ b/src/game-lib-d3-mesh-sphere.js @@ -71,6 +71,11 @@ GameLib.D3.Mesh.Sphere.prototype.updateInstance = function() { this.instance.userData.heightSegments !== this.heightSegments || this.instance.userData.radius !== this.radius ) { + + this.instance.userData.widthSegments = this.widthSegments; + this.instance.userData.heightSegments = this.heightSegments; + this.instance.userData.radius = this.radius; + var geometry = new THREE.SphereGeometry( this.radius, this.widthSegments, @@ -103,6 +108,69 @@ GameLib.D3.Mesh.Sphere.prototype.toApiObject = function() { return apiMesh; }; +GameLib.D3.Mesh.Sphere.prototype.createPhysicsObjects = function() { + + GameLib.Event.Emit( + GameLib.Event.GET_PHYSICS_ENGINE, + null, + function(data){ + var apiShapeSphere = new GameLib.D3.API.Shape( + null, + 'Sphere Shape (' + this.name + ')' + ); + + apiShapeSphere.parentMesh = this; + + var shapeSphere = new GameLib.D3.Shape.Sphere( + data.physics, + apiShapeSphere, + this.radius + ); + + var apiRigidBody = new GameLib.D3.API.RigidBody( + null, + 'Rigid Body (' + this.name + ')', + 1, + null, + new GameLib.API.Vector3( + this.position.x, + this.position.y, + this.position.z + ), + new GameLib.API.Quaternion( + this.quaternion.x, + this.quaternion.y, + this.quaternion.z, + this.quaternion.w, + new GameLib.API.Vector3( + this.quaternion.axis.x, + this.quaternion.axis.y, + this.quaternion.axis.z + ), + this.quaternion.angle + ) + ); + + apiRigidBody.shapes.push(shapeSphere); + + var rigidBody = new GameLib.D3.RigidBody( + data.physics, + apiRigidBody + ); + + rigidBody.parentMesh = this; + + }.bind(this), + function(error){ + console.log(error.message); + throw new Error(error.message); + } + ); + + + +}; + /** * Converts a standard object mesh to a GameLib.D3.Mesh * @param graphics GameLib.D3.Graphics diff --git a/src/game-lib-d3-physics-world.js b/src/game-lib-d3-physics-world.js index 0612edd..a646ffc 100644 --- a/src/game-lib-d3-physics-world.js +++ b/src/game-lib-d3-physics-world.js @@ -41,14 +41,14 @@ GameLib.D3.PhysicsWorld = function( } if (this.broadphase instanceof GameLib.D3.API.Broadphase) { - return new GameLib.D3.Broadphase( + this.broadphase = new GameLib.D3.Broadphase( this.physics, this.broadphase ); } if (this.solver instanceof GameLib.D3.API.Solver) { - return new GameLib.D3.Solver( + this.solver = new GameLib.D3.Solver( this.physics, this.solver ); diff --git a/src/game-lib-d3-rigid-body.js b/src/game-lib-d3-rigid-body.js index be56b89..92d9219 100644 --- a/src/game-lib-d3-rigid-body.js +++ b/src/game-lib-d3-rigid-body.js @@ -133,7 +133,20 @@ GameLib.D3.RigidBody.prototype.updateInstance = function() { this.instance.position.y = this.position.y; this.instance.position.z = this.position.z; - this.instance.quaternion.setFromAxisAngle(new CANNON.Vec3(this.quaternion.axis.x, this.quaternion.axis.y, this.quaternion.axis.z), this.quaternion.angle); + this.quaternion.axis.instance.x = this.quaternion.axis.x; + this.quaternion.axis.instance.y = this.quaternion.axis.y; + this.quaternion.axis.instance.z = this.quaternion.axis.z; + + this.instance.quaternion.setFromAxisAngle(this.quaternion.axis.instance, this.quaternion.angle); + + this.quaternion.x = this.instance.quaternion.x; + this.quaternion.y = this.instance.quaternion.y; + this.quaternion.z = this.instance.quaternion.z; + this.quaternion.w = this.instance.quaternion.w; + + this.parentMesh.position.setFrom(this.position); + this.parentMesh.quaternion.setFrom(this.quaternion); + this.parentMesh.updateInstance(); this.instance.velocity.x = this.velocity.x; this.instance.velocity.y = this.velocity.y; diff --git a/src/game-lib-quaternion.js b/src/game-lib-quaternion.js index ba6b3c2..aab20db 100644 --- a/src/game-lib-quaternion.js +++ b/src/game-lib-quaternion.js @@ -138,3 +138,34 @@ GameLib.Quaternion.prototype.toApiObject = function() { this.angle ); }; + +/** + * Checks if quaternion is equal to another quaternion + * @param quaternion + * @returns {boolean} + */ +GameLib.Quaternion.prototype.equals = function(quaternion) { + + return ( + this.x === quaternion.x && + this.y === quaternion.y && + this.z === quaternion.z && + this.w === quaternion.w && + this.axis.equals(quaternion.axis) && + this.angle === quaternion.angle + ); + +}; + +GameLib.Quaternion.prototype.setFrom = function(quaternion) { + this.x = quaternion.x; + this.y = quaternion.y; + this.z = quaternion.z; + this.w = quaternion.w; + this.axis.setFrom(quaternion.axis); + this.angle = quaternion.angle; +}; + +GameLib.Quaternion.prototype.copy = function(quaternion) { +console.log('todo'); +}; \ No newline at end of file diff --git a/src/game-lib-system-gui.js b/src/game-lib-system-gui.js index cdb5f8b..3d2d0b6 100644 --- a/src/game-lib-system-gui.js +++ b/src/game-lib-system-gui.js @@ -1451,7 +1451,8 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { if ( result.template[property] instanceof GameLib.Vector2 || result.template[property] instanceof GameLib.Vector3 || - result.template[property] instanceof GameLib.Vector4 + result.template[property] instanceof GameLib.Vector4 || + result.template[property] instanceof GameLib.Quaternion ) { if (!result.template[property].equals(component[property])) { delete result.template[property]; @@ -1539,7 +1540,10 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { continue; } - if (componentTemplate.template.linkedObjects[templateProperty] instanceof Array) { + if ( + componentTemplate.template.linkedObjects && + componentTemplate.template.linkedObjects[templateProperty] instanceof Array + ) { this.buildArrayManagerControl(folder, componentTemplate, templateProperty); } diff --git a/src/game-lib-system-physics.js b/src/game-lib-system-physics.js index 044d737..176cf0b 100644 --- a/src/game-lib-system-physics.js +++ b/src/game-lib-system-physics.js @@ -23,6 +23,20 @@ GameLib.System.Physics = function( this.afterRenderSubscription = null; + + +}; + +GameLib.System.Physics.prototype = Object.create(GameLib.System.prototype); +GameLib.System.Physics.prototype.constructor = GameLib.System.Physics; + +GameLib.System.Physics.prototype.start = function() { + + this.worlds = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.PhysicsWorld); + this.rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody); + this.wheels = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastWheel); + this.vehicles = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastVehicle); + this.shapeInstanceCreatedSubscription = this.subscribe( GameLib.Event.SHAPE_INSTANCE_CREATED, this.shapeInstanceCreated @@ -46,19 +60,7 @@ GameLib.System.Physics = function( this.arrayItemAddedSubscription = this.subscribe( GameLib.Event.ARRAY_ITEM_ADDED, this.arrayItemAdded - ) - -}; - -GameLib.System.Physics.prototype = Object.create(GameLib.System.prototype); -GameLib.System.Physics.prototype.constructor = GameLib.System.Physics; - -GameLib.System.Physics.prototype.start = function() { - - this.worlds = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.PhysicsWorld); - this.rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody); - this.wheels = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastWheel); - this.vehicles = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastVehicle); + ); this.worlds.map( function(world) { @@ -104,14 +106,39 @@ GameLib.System.Physics.prototype.beforeRender = function(data) { this.worlds.map( function(world) { - world.instance.step(1 / 60.0); + world.instance.step(data.delta); this.rigidBodies.map( function(rigidBody){ + rigidBody.position.x = rigidBody.instance.position.x; + rigidBody.position.y = rigidBody.instance.position.y; + rigidBody.position.z = rigidBody.instance.position.z; + + rigidBody.quaternion.x = rigidBody.instance.quaternion.x; + rigidBody.quaternion.y = rigidBody.instance.quaternion.y; + rigidBody.quaternion.z = rigidBody.instance.quaternion.z; + rigidBody.quaternion.w = rigidBody.instance.quaternion.w; + rigidBody.parentMesh.position.x = rigidBody.instance.position.x; rigidBody.parentMesh.position.y = rigidBody.instance.position.y; rigidBody.parentMesh.position.z = rigidBody.instance.position.z; + + rigidBody.parentMesh.quaternion.x = rigidBody.instance.quaternion.x; + rigidBody.parentMesh.quaternion.y = rigidBody.instance.quaternion.y; + rigidBody.parentMesh.quaternion.z = rigidBody.instance.quaternion.z; + rigidBody.parentMesh.quaternion.w = rigidBody.instance.quaternion.w; + + rigidBody.instance.getVelocityAtWorldPoint(new CANNON.Vec3(0,0,0), rigidBody.velocity.instance); + + rigidBody.velocity.x = rigidBody.velocity.instance.x; + rigidBody.velocity.y = rigidBody.velocity.instance.y; + rigidBody.velocity.z = rigidBody.velocity.instance.z; + + rigidBody.parentMesh.updateRotationFromAxisAngle = false; + rigidBody.parentMesh.updateInstance(); + + rigidBody.parentMesh.updateRotationFromAxisAngle = true; } ) }.bind(this) @@ -119,9 +146,20 @@ GameLib.System.Physics.prototype.beforeRender = function(data) { }; GameLib.System.Physics.prototype.solverInstanceCreated = function(data) { + + console.log(data); + }; GameLib.System.Physics.prototype.arrayItemAdded = function(data) { + + if ( + data.component instanceof GameLib.D3.PhysicsWorld && + data.item instanceof GameLib.D3.RigidBody + ) { + data.component.instance.add(data.item.instance); + } + }; GameLib.System.Physics.prototype.instanceCreated = function(data) { @@ -158,8 +196,17 @@ GameLib.System.Physics.prototype.instanceCreated = function(data) { data.component.parentMesh = mesh; } } - ) + ); + /** + * By default - add this rigidbody to all physics worlds + */ + this.worlds.map(function(world){ + world.rigidBodies.push(data.component); + world.instance.add(data.component.instance); + }); + + this.restart(); } }; diff --git a/src/game-lib-system-storage.js b/src/game-lib-system-storage.js index 4101992..4e4ac08 100644 --- a/src/game-lib-system-storage.js +++ b/src/game-lib-system-storage.js @@ -4,7 +4,6 @@ * @param physics * @param coder * @param apiSystem GameLib.API.System - * @param apiUrl * @param token * @param apiUploadUrl * @param onImageLoaded @@ -20,7 +19,6 @@ GameLib.System.Storage = function( physics, coder, apiSystem, - apiUrl, token, apiUploadUrl, onImageLoaded, @@ -44,12 +42,6 @@ GameLib.System.Storage = function( apiSystem ); - if (GameLib.Utils.UndefinedOrNull(apiUrl)) { - console.warn('Need an API URL for a storage system'); - apiUrl = ''; - } - this.apiUrl = apiUrl; - if (GameLib.Utils.UndefinedOrNull(token)) { token = null; } @@ -159,57 +151,72 @@ GameLib.System.Storage.prototype.start = function() { GameLib.System.Storage.prototype.delete = function(data) { - if (typeof XMLHttpRequest === 'undefined') { - console.log('Implement server side delete here'); - return; - } + this.publish( + GameLib.Event.GET_API_URL, + null, + function(urlData) { - data.ids.map(function(id){ - var xhr = new XMLHttpRequest(); - - xhr.open( - 'POST', - this.apiUrl + '/component/delete/' + id - ); - - xhr.setRequestHeader("Accept", "application/json"); - xhr.setRequestHeader("Content-Type", "application/json"); - - xhr.onreadystatechange = function () { - if (this.readyState === 4) { - try { - var response = JSON.parse(this.responseText) - } catch (error) { - GameLib.Event.Emit( - GameLib.Event.DELETE_COMPONENT_ERROR, - { - message: this.responseText - } - ) - } - - if (response.result === 'success') { - GameLib.Event.Emit( - GameLib.Event.COMPONENT_DELETED, - { - message: response.message || 'Successfully saved the component' - } - ) - } else { - GameLib.Event.Emit( - GameLib.Event.DELETE_COMPONENT_ERROR, - { - message: response.message || 'The server responded but failed to save the component' - } - ) - } + if (typeof XMLHttpRequest === 'undefined') { + console.log('Implement server side delete here'); + return; } - }; - xhr.send(JSON.stringify({ - session : this.token - })); - }.bind(this)); + data.ids.map(function(id){ + + var xhr = new XMLHttpRequest(); + + xhr.open( + 'POST', + urlData.apiUrl + '/component/delete/' + id + ); + + xhr.setRequestHeader("Accept", "application/json"); + xhr.setRequestHeader("Content-Type", "application/json"); + + xhr.onreadystatechange = function () { + if (this.readyState === 4) { + try { + var response = JSON.parse(this.responseText) + } catch (error) { + GameLib.Event.Emit( + GameLib.Event.DELETE_COMPONENT_ERROR, + { + message: this.responseText + } + ) + } + + if (response.result === 'success') { + GameLib.Event.Emit( + GameLib.Event.COMPONENT_DELETED, + { + message: response.message || 'Successfully saved the component' + } + ) + } else { + GameLib.Event.Emit( + GameLib.Event.DELETE_COMPONENT_ERROR, + { + message: response.message || 'The server responded but failed to save the component' + } + ) + } + } + }; + + xhr.send(JSON.stringify({ + session : this.token + })); + + }.bind(this)); + }.bind(this), + function(error) { + console.error(error.message); + throw new Error(error.message); + } + ); + + }; @@ -227,7 +234,7 @@ GameLib.System.Storage.prototype.save = function(data) { xhr.open( 'POST', - this.apiUrl + '/component/create' + data.apiUrl + '/component/create' ); xhr.setRequestHeader("Accept", "application/json"); @@ -265,13 +272,13 @@ GameLib.System.Storage.prototype.save = function(data) { }; xhr.send(JSON.stringify({ - component : data, + component : data.apiObject, session : this.token })); }; -GameLib.System.Storage.prototype.loadComponent = function(toProcess, includeDependencies, clientCallback, clientErrorCallback) { +GameLib.System.Storage.prototype.loadComponent = function(apiUrl, toProcess, includeDependencies, clientCallback, clientErrorCallback) { var loaded = []; @@ -579,7 +586,7 @@ GameLib.System.Storage.prototype.loadComponent = function(toProcess, includeDepe xhr.open( 'GET', - this.apiUrl + '/component/load/' + id + apiUrl + '/component/load/' + id ); xhr.send(); @@ -592,21 +599,32 @@ GameLib.System.Storage.prototype.loadComponent = function(toProcess, includeDepe */ GameLib.System.Storage.prototype.load = function(data, clientCallback, clientErrorCallback) { - if (typeof XMLHttpRequest === 'undefined') { - console.log('Implement server side load here'); - return; - } + this.publish( + GameLib.Event.GET_API_URL, + null, + function(urlData) { + if (typeof XMLHttpRequest === 'undefined') { + console.log('Implement server side load here'); + return; + } - if (data.ids && data.ids.length > 0) { - this.loadComponent( - data.ids, - data.includeDependencies, - clientCallback, - clientErrorCallback - )(data.ids[0], null); - } else { - console.log('No components selected'); - } + if (data.ids && data.ids.length > 0) { + this.loadComponent( + urlData.apiUrl, + data.ids, + data.includeDependencies, + clientCallback, + clientErrorCallback + )(data.ids[0], null); + } else { + console.log('No components selected'); + } + }.bind(this), + function(error) { + console.error(error.message); + throw new Error(error.message); + } + ); }; @@ -840,130 +858,143 @@ GameLib.System.Storage.prototype.loadImage = function(data) { console.log('loading image : ' + data.image.name); - var onLoaded = this.onImageLoaded; + this.publish( + GameLib.Event.GET_API_URL, + null, + function(urlData) { - var onProgress = this.onImageProgress; + var onLoaded = this.onImageLoaded; - var onError = this.onImageError; + var onProgress = this.onImageProgress; - var image = data.image; + var onError = this.onImageError; - var url = this.apiUrl + image.path + image.fileName + image.extension + '?ts=' + Date.now(); + var image = data.image; - var preflight = new XMLHttpRequest(); + var url = urlData.apiUrl + image.path + image.fileName + image.extension + '?ts=' + Date.now(); - preflight.withCredentials = true; + var preflight = new XMLHttpRequest(); - preflight.open( - 'OPTIONS', - url - ); + preflight.withCredentials = true; - preflight.setRequestHeader('Content-Type', 'application/json'); + preflight.open( + 'OPTIONS', + url + ); - preflight.onload = function() { + preflight.setRequestHeader('Content-Type', 'application/json'); - var xhr = new XMLHttpRequest(); + preflight.onload = function() { - xhr.withCredentials = true; + var xhr = new XMLHttpRequest(); - xhr.open('GET', url); + xhr.withCredentials = true; - xhr.setRequestHeader('Content-Type', image.contentType); + xhr.open('GET', url); - xhr.responseType = 'blob'; + xhr.setRequestHeader('Content-Type', image.contentType); - xhr.onload = function() { + xhr.responseType = 'blob'; - try { - if (this.response.type !== 'application/json') { - var url = window.URL.createObjectURL(this.response); - } else { - if (onError) { + xhr.onload = function() { - GameLib.Event.Emit( - GameLib.Event.IMAGE_NOT_FOUND, + try { + if (this.response.type !== 'application/json') { + var url = window.URL.createObjectURL(this.response); + } else { + if (onError) { + + GameLib.Event.Emit( + GameLib.Event.IMAGE_NOT_FOUND, + { + image : image + } + ); + + onError(image, {message:'Image not found'}); + + return; + } + } + } catch (error) { + if (onError) { + + GameLib.Event.Emit( + GameLib.Event.IMAGE_NOT_FOUND, + { + image : image + } + ); + + onError(image, {message:'Image not found'}); + return; + } + } + var img = document.createElement('img'); + + img.onload = function() { + + window.URL.revokeObjectURL(url); + + image.instance = img; + image.loaded = true; + image.publish( + GameLib.Event.IMAGE_INSTANCE_CREATED, { - image : image + image: image } ); - onError(image, {message:'Image not found'}); + if (onLoaded) { + onLoaded(image, data.createTexture); + } + }; - return; + img.src = url; + }; + + xhr.onprogress = function(progressEvent) { + + var progress = 0; + + if (progressEvent.total !== 0) { + progress = Number(progressEvent.loaded / progressEvent.total); + progress *= 100; } - } - } catch (error) { + + if (onProgress) { + onProgress(image, progress); + } + + image.size = progressEvent.total; + }; + + xhr.onerror = function(error) { + console.warn('image load failed for image ' + image.name); + if (onError) { + onError(image, error) + } + }; + + xhr.send(); + }; + + preflight.onerror = function(error) { + console.warn('image pre-flight request failed for image ' + image.name); if (onError) { - - GameLib.Event.Emit( - GameLib.Event.IMAGE_NOT_FOUND, - { - image : image - } - ); - - onError(image, {message:'Image not found'}); - return; - } - } - var img = document.createElement('img'); - - img.onload = function() { - - window.URL.revokeObjectURL(url); - - image.instance = img; - image.loaded = true; - image.publish( - GameLib.Event.IMAGE_INSTANCE_CREATED, - { - image: image - } - ); - - if (onLoaded) { - onLoaded(image, data.createTexture); + onError(image, error); } }; - img.src = url; - }; - - xhr.onprogress = function(progressEvent) { - - var progress = 0; - - if (progressEvent.total !== 0) { - progress = Number(progressEvent.loaded / progressEvent.total); - progress *= 100; - } - - if (onProgress) { - onProgress(image, progress); - } - - image.size = progressEvent.total; - }; - - xhr.onerror = function(error) { - console.warn('image load failed for image ' + image.name); - if (onError) { - onError(image, error) - } - }; - - xhr.send(); - }; - - preflight.onerror = function(error) { - console.warn('image pre-flight request failed for image ' + image.name); - if (onError) { - onError(image, error); + preflight.send(); + }.bind(this), + function(error) { + console.error(error.message); + throw new Error(error.message); } - }; + ); + - preflight.send(); }; GameLib.System.Storage.prototype.stop = function() { diff --git a/src/game-lib-vector3.js b/src/game-lib-vector3.js index 085ee20..45a8b89 100644 --- a/src/game-lib-vector3.js +++ b/src/game-lib-vector3.js @@ -124,3 +124,9 @@ GameLib.Vector3.prototype.copy = function() { this.grain ) }; + +GameLib.Vector3.prototype.setFrom = function(vector3) { + this.x = vector3.x; + this.y = vector3.y; + this.z = vector3.z; +};