From b6ac86ce7ed39b1e959d8d5f7238c2f3ee875c48 Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Tue, 5 Sep 2017 05:22:52 +0200 Subject: [PATCH] cylinders, boxes, spheres --- src/game-lib-a-1-event.js | 56 +++- src/game-lib-a-component-a.js | 4 +- src/game-lib-d3-api-face.js | 2 +- src/game-lib-d3-api-mesh.js | 2 +- ...ld.js => game-lib-d3-api-physics-world.js} | 22 +- src/game-lib-d3-api-raycast-vehicle.js | 16 ++ src/game-lib-d3-api-rigid-body.js | 10 +- src/game-lib-d3-face.js | 30 +- src/game-lib-d3-mesh-0.js | 100 ++++--- src/game-lib-d3-mesh-box.js | 125 +++++++++ src/game-lib-d3-mesh-cylinder.js | 188 +++++++++++++ src/game-lib-d3-mesh-plane.js | 18 +- src/game-lib-d3-mesh-sphere.js | 30 +- ...-world.js => game-lib-d3-physics-world.js} | 98 +++++-- src/game-lib-d3-raycast-vehicle.js | 42 ++- src/game-lib-d3-rigid-body.js | 29 +- src/game-lib-d3-shape-0.js | 22 +- src/game-lib-d3-shape-height-map.js | 30 +- src/game-lib-system-0.js | 21 +- src/game-lib-system-animation.js | 26 ++ src/game-lib-system-gui.js | 42 ++- src/game-lib-system-linking.js | 72 ++--- src/game-lib-system-physics.js | 257 ++++++++++++++---- src/game-lib-system-render.js | 13 +- src/game-lib-system-storage.js | 2 +- src/game-lib-system-visualization.js | 99 +++++++ 26 files changed, 1106 insertions(+), 250 deletions(-) rename src/{game-lib-d3-api-world.js => game-lib-d3-api-physics-world.js} (68%) create mode 100644 src/game-lib-d3-mesh-box.js create mode 100644 src/game-lib-d3-mesh-cylinder.js rename src/{game-lib-d3-world.js => game-lib-d3-physics-world.js} (90%) create mode 100644 src/game-lib-system-animation.js create mode 100644 src/game-lib-system-visualization.js diff --git a/src/game-lib-a-1-event.js b/src/game-lib-a-1-event.js index 5101f63..8868556 100644 --- a/src/game-lib-a-1-event.js +++ b/src/game-lib-a-1-event.js @@ -31,7 +31,7 @@ GameLib.Event.LOGGED_IN = 0xd; GameLib.Event.COMPONENT_CREATED = 0xe; GameLib.Event.SCENE_INSTANCE_CREATED = 0xf; GameLib.Event.SCENE_OBJECT_INSTANCE_CREATED = 0x10; -GameLib.Event.WORLD_INSTANCE_CREATED = 0x11; +GameLib.Event.PHYSICS_WORLD_INSTANCE_CREATED = 0x11; GameLib.Event.RIGID_BODY_INSTANCE_CREATED = 0x12; GameLib.Event.TEXTURE_INSTANCE_CREATED = 0x13; GameLib.Event.TEXTURE_INSTANCE_UPDATED = 0x14; @@ -69,6 +69,13 @@ GameLib.Event.COMPONENT_DELETED = 0x33; GameLib.Event.COMPONENT_TYPES_UPDATED = 0x34; GameLib.Event.SHAPE_INSTANCE_CREATED = 0x35; GameLib.Event.COMPONENT_LINKED = 0x36; +GameLib.Event.SOLVER_INSTANCE_CREATED = 0x37; +GameLib.Event.BEFORE_RENDER = 0x38; +GameLib.Event.AFTER_RENDER = 0x39; +GameLib.Event.ARRAY_ITEM_ADDED = 0x3a; +GameLib.Event.INSTANCE_CREATED = 0x3b; +GameLib.Event.VISUALIZE = 0x3c; +GameLib.Event.STOP_VISUALIZE = 0x3d; /** * Returns string name of event ID @@ -133,6 +140,11 @@ GameLib.Event.GetEventName = function(number) { case 0x34 : return 'component_types_updated'; case 0x35 : return 'shape_instance_created'; case 0x36 : return 'component_linked'; + case 0x37 : return 'solver_instance_created'; + case 0x38 : return 'before_render'; + case 0x39 : return 'after_render'; + case 0x3a : return 'array_item_added'; + case 0x3b : return 'instance_created'; break; } @@ -161,7 +173,9 @@ GameLib.Event.EmitInstanceEvents = function(component) { { mesh: component } - ) + ); + + return; } if ( @@ -172,7 +186,9 @@ GameLib.Event.EmitInstanceEvents = function(component) { { light: component } - ) + ); + + return; } if ( @@ -184,6 +200,8 @@ GameLib.Event.EmitInstanceEvents = function(component) { scene: component } ); + + return; } if ( @@ -195,6 +213,8 @@ GameLib.Event.EmitInstanceEvents = function(component) { material: component } ); + + return; } if ( @@ -206,6 +226,8 @@ GameLib.Event.EmitInstanceEvents = function(component) { texture: component } ); + + return; } if ( @@ -216,7 +238,9 @@ GameLib.Event.EmitInstanceEvents = function(component) { { image: component } - ) + ); + + return; } if ( @@ -227,8 +251,30 @@ GameLib.Event.EmitInstanceEvents = function(component) { { shape: component } - ) + ); + + return; } + + if ( + component instanceof GameLib.D3.PhysicsWorld + ) { + GameLib.Event.Emit( + GameLib.Event.PHYSICS_WORLD_INSTANCE_CREATED, + { + world: component + } + ); + + return; + } + + GameLib.Event.Emit( + GameLib.Event.INSTANCE_CREATED, + { + component: component + } + ) }; // /** diff --git a/src/game-lib-a-component-a.js b/src/game-lib-a-component-a.js index cae8706..9bdc86a 100644 --- a/src/game-lib-a-component-a.js +++ b/src/game-lib-a-component-a.js @@ -130,7 +130,7 @@ GameLib.Component.COMPONENT_ENTITY = 0x20; GameLib.Component.COMPONENT_MESH_SPHERE = 0x21; GameLib.Component.COMPONENT_MESH_PLANE = 0x22; GameLib.Component.COMPONENT_MESH_CURVE = 0x23; -GameLib.Component.COMPONENT_WORLD = 0x24; +GameLib.Component.COMPONENT_PHYSICS_WORLD = 0x24; GameLib.Component.COMPONENT_BROADPHASE = 0x25; GameLib.Component.COMPONENT_SOLVER = 0x26; GameLib.Component.COMPONENT_RIGID_BODY = 0x27; @@ -193,7 +193,7 @@ GameLib.Component.GetComponentName = function(number) { case 0x21 : return 'GameLib.D3.Mesh.Sphere'; case 0x22 : return 'GameLib.D3.Mesh.Plane'; case 0x23 : return 'GameLib.D3.Mesh.Curve'; - case 0x24 : return 'GameLib.D3.World'; + case 0x24 : return 'GameLib.D3.PhysicsWorld'; case 0x25 : return 'GameLib.D3.Broadphase'; case 0x26 : return 'GameLib.D3.Solver'; case 0x27 : return 'GameLib.D3.RigidBody'; diff --git a/src/game-lib-d3-api-face.js b/src/game-lib-d3-api-face.js index 5bab8eb..55ea21c 100644 --- a/src/game-lib-d3-api-face.js +++ b/src/game-lib-d3-api-face.js @@ -58,7 +58,7 @@ GameLib.D3.API.Face = function( this.materialIndex = materialIndex; if (GameLib.Utils.UndefinedOrNull(uvs)) { - uvs = [[]]; + uvs = [[new GameLib.API.Vector2(0,0), new GameLib.API.Vector2(0,0), new GameLib.API.Vector2(0,0)]]; } this.uvs = uvs; diff --git a/src/game-lib-d3-api-mesh.js b/src/game-lib-d3-api-mesh.js index dc9432e..3257967 100644 --- a/src/game-lib-d3-api-mesh.js +++ b/src/game-lib-d3-api-mesh.js @@ -99,7 +99,7 @@ GameLib.D3.API.Mesh = function( this.skinWeights = skinWeights; if (GameLib.Utils.UndefinedOrNull(materials)) { - materials = []; + materials = [new GameLib.D3.API.Material(null, GameLib.D3.Material.MATERIAL_TYPE_BASIC)]; } this.materials = materials; diff --git a/src/game-lib-d3-api-world.js b/src/game-lib-d3-api-physics-world.js similarity index 68% rename from src/game-lib-d3-api-world.js rename to src/game-lib-d3-api-physics-world.js index e03aa13..46fabea 100644 --- a/src/game-lib-d3-api-world.js +++ b/src/game-lib-d3-api-physics-world.js @@ -6,16 +6,18 @@ * @param broadphase * @param solver * @param rigidBodies + * @param contactMaterials * @param parentEntity * @constructor */ -GameLib.D3.API.World = function( +GameLib.D3.API.PhysicsWorld = function( id, name, gravity, broadphase, solver, rigidBodies, + contactMaterials, parentEntity ) { @@ -25,7 +27,7 @@ GameLib.D3.API.World = function( this.id = id; if (GameLib.Utils.UndefinedOrNull(name)) { - name = 'World (' + this.id + ')'; + name = 'Physics World (' + this.id + ')'; } this.name = name; @@ -49,28 +51,34 @@ GameLib.D3.API.World = function( } this.rigidBodies = rigidBodies; + if (GameLib.Utils.UndefinedOrNull(contactMaterials)) { + contactMaterials = []; + } + this.contactMaterials = contactMaterials; + if (GameLib.Utils.UndefinedOrNull(parentEntity)) { parentEntity = null; } this.parentEntity = parentEntity; }; -GameLib.D3.API.World.prototype = Object.create(GameLib.Component.prototype); -GameLib.D3.API.World.prototype.constructor = GameLib.D3.API.World; +GameLib.D3.API.PhysicsWorld.prototype = Object.create(GameLib.Component.prototype); +GameLib.D3.API.PhysicsWorld.prototype.constructor = GameLib.D3.API.PhysicsWorld; /** * Creates an API World from an Object World * @param objectWorld * @constructor */ -GameLib.D3.API.World.FromObject = function(objectWorld) { - return new GameLib.D3.API.World( +GameLib.D3.API.PhysicsWorld.FromObject = function(objectWorld) { + return new GameLib.D3.API.PhysicsWorld( objectWorld.id, objectWorld.name, - objectWorld.gravity, + GameLib.API.Vector3.FromObject(objectWorld.gravity), objectWorld.broadphase, objectWorld.solver, objectWorld.rigidBodies, + objectWorld.contactMaterials, objectWorld.parentEntity ); }; diff --git a/src/game-lib-d3-api-raycast-vehicle.js b/src/game-lib-d3-api-raycast-vehicle.js index a708a79..bc7c3b3 100644 --- a/src/game-lib-d3-api-raycast-vehicle.js +++ b/src/game-lib-d3-api-raycast-vehicle.js @@ -4,6 +4,8 @@ * @param name * @param chassis * @param wheels + * @param raycastWheels + * @param parentWorld * @param parentEntity * @constructor */ @@ -12,6 +14,8 @@ GameLib.D3.API.RaycastVehicle = function( name, chassis, wheels, + raycastWheels, + parentWorld, parentEntity ) { @@ -35,6 +39,16 @@ GameLib.D3.API.RaycastVehicle = function( } this.wheels = wheels; + if (GameLib.Utils.UndefinedOrNull(raycastWheels)) { + raycastWheels = []; + } + this.raycastWheels = raycastWheels; + + if (GameLib.Utils.UndefinedOrNull(parentWorld)) { + parentWorld = null; + } + this.parentWorld = parentWorld; + if (GameLib.Utils.UndefinedOrNull(parentEntity)) { parentEntity = null; } @@ -55,6 +69,8 @@ GameLib.D3.API.RaycastVehicle.FromObject = function(objectRaycastVehicle) { objectRaycastVehicle.name, objectRaycastVehicle.chassis, objectRaycastVehicle.wheels, + objectRaycastVehicle.raycastWheels, + objectRaycastVehicle.parentWorld, objectRaycastVehicle.parentEntity ); }; diff --git a/src/game-lib-d3-api-rigid-body.js b/src/game-lib-d3-api-rigid-body.js index b78ba9c..6c548c4 100644 --- a/src/game-lib-d3-api-rigid-body.js +++ b/src/game-lib-d3-api-rigid-body.js @@ -18,6 +18,7 @@ * @param fixedRotation * @param shapes * @param kinematic + * @param parentMesh * @param parentEntity * @constructor */ @@ -40,6 +41,7 @@ GameLib.D3.API.RigidBody = function( fixedRotation, shapes, kinematic, + parentMesh, parentEntity ) { @@ -132,7 +134,12 @@ GameLib.D3.API.RigidBody = function( kinematic = false; } this.kinematic = kinematic; - + + if (GameLib.Utils.UndefinedOrNull(parentMesh)) { + parentMesh = null; + } + this.parentMesh = parentMesh; + if (GameLib.Utils.UndefinedOrNull(parentEntity)) { parentEntity = null; } @@ -167,6 +174,7 @@ GameLib.D3.API.RigidBody.FromObject = function(objectRigidBody) { objectRigidBody.fixedRotation, objectRigidBody.shapes, objectRigidBody.kinematic, + objectRigidBody.parentMesh, objectRigidBody.parentEntity ); }; diff --git a/src/game-lib-d3-face.js b/src/game-lib-d3-face.js index 1ed01d3..9f560ab 100644 --- a/src/game-lib-d3-face.js +++ b/src/game-lib-d3-face.js @@ -69,21 +69,21 @@ GameLib.D3.Face = function Face( } - this.vertexNormals = this.vertexNormals.map(function(vertexNormal){ - if (vertexNormal instanceof GameLib.Vector3) { - return vertexNormal; - } - - if (vertexNormal instanceof GameLib.API.Vector3) { - return new GameLib.Vector3( - this.graphics, - vertexNormal, - this - ) - } - - console.warn('unknown vertex normal type', vertexNormal); - }.bind(this)); + // this.vertexNormals = this.vertexNormals.map(function(vertexNormal){ + // if (vertexNormal instanceof GameLib.Vector3) { + // return vertexNormal; + // } + // + // if (vertexNormal instanceof GameLib.API.Vector3) { + // return new GameLib.Vector3( + // this.graphics, + // vertexNormal, + // this + // ) + // } + // + // console.warn('unknown vertex normal type', vertexNormal); + // }.bind(this)); this.normal = new GameLib.Vector3( this.implementation, diff --git a/src/game-lib-d3-mesh-0.js b/src/game-lib-d3-mesh-0.js index e501dd0..1c76ecb 100644 --- a/src/game-lib-d3-mesh-0.js +++ b/src/game-lib-d3-mesh-0.js @@ -223,6 +223,8 @@ GameLib.D3.Mesh.MESH_TYPE_SKINNED = 0x1; GameLib.D3.Mesh.MESH_TYPE_CURVE = 0x2; GameLib.D3.Mesh.MESH_TYPE_SPHERE = 0x3; GameLib.D3.Mesh.MESH_TYPE_PLANE = 0x4; +GameLib.D3.Mesh.MESH_TYPE_BOX = 0x5; +GameLib.D3.Mesh.MESH_TYPE_CYLINDER = 0x6; GameLib.D3.Mesh.prototype.createInstanceGeometry = function(instanceGeometry) { @@ -436,10 +438,13 @@ GameLib.D3.Mesh.prototype.createInstanceGeometry = function(instanceGeometry) { ); geometry.verticesNeedUpdate = true; - /** - * UV data - */ - geometry.faceVertexUvs = [standardUvs]; + + /** + * UV data - but only if it exists + */ + if (standardUvs.length > 0) { + geometry.faceVertexUvs = [standardUvs]; + } /** * Re-compute normals - we don't do this for buffer geometry because it assigns to every vertex normal the face @@ -569,7 +574,9 @@ GameLib.D3.Mesh.prototype.updateInstance = function() { this.instance.renderOrder = this.renderOrder; if (this.helper) { - this.helper.updateInstance(); + this.removeHelper(); + this.createHelper(); + // this.helper.updateInstance(); } this.computeBoundingBox(this.instance.geometry); @@ -714,43 +721,43 @@ GameLib.D3.Mesh.prototype.updateVerticesFromGeometryInstance = function(geometry x: geometryInstance.faceVertexUvs[0][faceIndex][2].x, y: geometryInstance.faceVertexUvs[0][faceIndex][2].y } - ]] - // new GameLib.Color( - // this.graphics, - // new GameLib.API.Color( - // face.color.r, - // face.color.g, - // face.color.b - // ) - // ), - // face.vertexColors.map(function(vertexColor){ - // return new GameLib.Color( - // this.graphics, - // new GameLib.API.Color( - // vertexColor.r, - // vertexColor.g, - // vertexColor.b - // ) - // ) - // }.bind(this)), - // face.vertexNormals.map(function(vertexNormal){ - // return new GameLib.Vector3( - // this.graphics, - // new GameLib.API.Vector3( - // vertexNormal.x, - // vertexNormal.y, - // vertexNormal.z - // ) - // ) - // }.bind(this)), - // new GameLib.Vector3( - // this.graphics, - // new GameLib.API.Vector3( - // face.normal.x, - // face.normal.y, - // face.normal.z - // ) - // ) + ]], + new GameLib.Color( + this.graphics, + new GameLib.API.Color( + face.color.r, + face.color.g, + face.color.b + ) + ), + face.vertexColors.map(function(vertexColor){ + return new GameLib.Color( + this.graphics, + new GameLib.API.Color( + vertexColor.r, + vertexColor.g, + vertexColor.b + ) + ) + }.bind(this)), + face.vertexNormals.map(function(vertexNormal){ + return new GameLib.Vector3( + this.graphics, + new GameLib.API.Vector3( + vertexNormal.x, + vertexNormal.y, + vertexNormal.z + ) + ) + }.bind(this)), + new GameLib.Vector3( + this.graphics, + new GameLib.API.Vector3( + face.normal.x, + face.normal.y, + face.normal.z + ) + ) ) ) ) @@ -1025,8 +1032,17 @@ GameLib.D3.Mesh.prototype.applyLocalPositionRotationScale = function() { var geometry = this.createInstanceGeometry(); + /** + * 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; diff --git a/src/game-lib-d3-mesh-box.js b/src/game-lib-d3-mesh-box.js new file mode 100644 index 0000000..f516a63 --- /dev/null +++ b/src/game-lib-d3-mesh-box.js @@ -0,0 +1,125 @@ +/** + * Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created + * @param graphics GameLib.D3.Graphics + * @param apiMesh GameLib.D3.API.Mesh + * @param width + * @param height + * @param depth + * @constructor + */ +GameLib.D3.Mesh.Box = function ( + graphics, + apiMesh, + width, + height, + depth +) { + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (GameLib.Utils.UndefinedOrNull(width)) { + width = 1; + } + this.width = width; + + if (GameLib.Utils.UndefinedOrNull(height)) { + height = 1; + } + this.height = height; + + if (GameLib.Utils.UndefinedOrNull(depth)) { + depth = 1; + } + this.depth = depth; + + GameLib.D3.Mesh.call( + this, + this.graphics, + apiMesh + ); +}; + +GameLib.D3.Mesh.Box.prototype = Object.create(GameLib.D3.Mesh.prototype); +GameLib.D3.Mesh.Box.prototype.constructor = GameLib.D3.Mesh.Box; + +GameLib.D3.Mesh.Box.prototype.createInstance = function() { + + var geometry = null; + + if (this.vertices.length === 0) { + geometry = new THREE.BoxGeometry( + this.width, + this.height, + this.depth + ); + + this.updateVerticesFromGeometryInstance(geometry); + } + + var instance = GameLib.D3.Mesh.prototype.createInstance.call(this); + + instance.userData.width = this.width; + instance.userData.height = this.height; + instance.userData.depth = this.depth; + + return instance; +}; + +GameLib.D3.Mesh.Box.prototype.updateInstance = function() { + + if ( + 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, + this.depth + ); + + this.updateVerticesFromGeometryInstance(geometry); + + geometry = this.createInstanceGeometry(); + + this.instance.geometry = geometry; + } + + GameLib.D3.Mesh.prototype.updateInstance.call(this); + +}; + +/** + * Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh + * @returns {GameLib.D3.API.Mesh} + */ +GameLib.D3.Mesh.Box.prototype.toApiObject = function() { + + var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this); + + apiMesh.width = this.width; + apiMesh.height = this.height; + apiMesh.depth = this.depth; + + return apiMesh; +}; + +/** + * Converts a standard object mesh to a GameLib.D3.Mesh + * @param graphics GameLib.D3.Graphics + * @param objectMesh {Object} + * @constructor + */ +GameLib.D3.Mesh.Box.FromObject = function(graphics, objectMesh) { + + var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh); + + return new GameLib.D3.Mesh.Box( + graphics, + apiMesh, + objectMesh.width, + objectMesh.height, + objectMesh.depth + ); + +}; diff --git a/src/game-lib-d3-mesh-cylinder.js b/src/game-lib-d3-mesh-cylinder.js new file mode 100644 index 0000000..c0a048b --- /dev/null +++ b/src/game-lib-d3-mesh-cylinder.js @@ -0,0 +1,188 @@ +/** + * Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created + * @param graphics GameLib.D3.Graphics + * @param apiMesh GameLib.D3.API.Mesh + * @param radiusTop + * @param radiusBottom + * @param height + * @param radiusSegments + * @param heightSegments + * @param openEnded + * @param thetaStart + * @param thetaLength + * @constructor + */ +GameLib.D3.Mesh.Cylinder = function ( + graphics, + apiMesh, + radiusTop, + radiusBottom, + height, + radiusSegments, + heightSegments, + openEnded, + thetaStart, + thetaLength +) { + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (GameLib.Utils.UndefinedOrNull(radiusTop)) { + radiusTop = 1; + } + this.radiusTop = radiusTop; + + if (GameLib.Utils.UndefinedOrNull(radiusBottom)) { + radiusBottom = 1; + } + this.radiusBottom = radiusBottom; + + if (GameLib.Utils.UndefinedOrNull(height)) { + height = 5; + } + this.height = height; + + if (GameLib.Utils.UndefinedOrNull(radiusSegments)) { + radiusSegments = 10; + } + this.radiusSegments = radiusSegments; + + if (GameLib.Utils.UndefinedOrNull(heightSegments)) { + heightSegments = 10; + } + this.heightSegments = heightSegments; + + if (GameLib.Utils.UndefinedOrNull(openEnded)) { + openEnded = false; + } + this.openEnded = openEnded; + + if (GameLib.Utils.UndefinedOrNull(thetaStart)) { + thetaStart = 0; + } + this.thetaStart = thetaStart; + + if (GameLib.Utils.UndefinedOrNull(thetaLength)) { + thetaLength = Math.PI * 2; + } + this.thetaLength = thetaLength; + + GameLib.D3.Mesh.call( + this, + this.graphics, + apiMesh + ); +}; + +GameLib.D3.Mesh.Cylinder.prototype = Object.create(GameLib.D3.Mesh.prototype); +GameLib.D3.Mesh.Cylinder.prototype.constructor = GameLib.D3.Mesh.Cylinder; + +GameLib.D3.Mesh.Cylinder.prototype.createInstance = function() { + + var geometry = null; + + if (this.vertices.length === 0) { + geometry = new THREE.CylinderGeometry( + this.radiusTop, + this.radiusBottom, + this.height, + this.radiusSegments, + this.heightSegments, + this.openEnded, + this.thetaStart, + this.thetaLength + ); + this.updateVerticesFromGeometryInstance(geometry); + } + + var instance = GameLib.D3.Mesh.prototype.createInstance.call(this); + + instance.userData.radiusTop = this.radiusTop; + instance.userData.radiusBottom = this.radiusBottom; + instance.userData.height = this.height; + instance.userData.radiusSegments = this.radiusSegments; + instance.userData.heightSegments = this.heightSegments; + instance.userData.openEnded = this.openEnded; + instance.userData.thetaStart = this.thetaStart; + instance.userData.thetaLength = this.thetaLength; + + return instance; +}; + +GameLib.D3.Mesh.Cylinder.prototype.updateInstance = function() { + + if ( + 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, + this.height, + this.radiusSegments, + this.heightSegments, + this.openEnded, + this.thetaStart, + this.thetaLength + ); + this.updateVerticesFromGeometryInstance(geometry); + + geometry = this.createInstanceGeometry(); + + this.instance.geometry = geometry; + } + + GameLib.D3.Mesh.prototype.updateInstance.call(this); + +}; + +/** + * Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh + * @returns {GameLib.D3.API.Mesh} + */ +GameLib.D3.Mesh.Cylinder.prototype.toApiObject = function() { + + var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this); + + apiMesh.radiusTop = this.radiusTop; + apiMesh.radiusBottom = this.radiusBottom; + apiMesh.height = this.height; + apiMesh.radiusSegments = this.radiusSegments; + apiMesh.heightSegments = this.heightSegments; + apiMesh.openEnded = this.openEnded; + apiMesh.thetaStart = this.thetaStart; + apiMesh.thetaLength = this.thetaLength; + + return apiMesh; +}; + +/** + * Converts a standard object mesh to a GameLib.D3.Mesh + * @param graphics GameLib.D3.Graphics + * @param objectMesh {Object} + * @constructor + */ +GameLib.D3.Mesh.Cylinder.FromObject = function(graphics, objectMesh) { + + var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh); + + return new GameLib.D3.Mesh.Cylinder( + graphics, + apiMesh, + objectMesh.radiusTop, + objectMesh.radiusBottom, + objectMesh.height, + objectMesh.radiusSegments, + objectMesh.heightSegments, + objectMesh.openEnded, + objectMesh.thetaStart, + objectMesh.thetaLength + ); + +}; diff --git a/src/game-lib-d3-mesh-plane.js b/src/game-lib-d3-mesh-plane.js index 5ad6e2d..9d9e0b3 100644 --- a/src/game-lib-d3-mesh-plane.js +++ b/src/game-lib-d3-mesh-plane.js @@ -6,6 +6,8 @@ * @param height * @param widthSegments * @param heightSegments + * @param heightMapScale + * @param isHeightMap * @constructor */ GameLib.D3.Mesh.Plane = function ( @@ -89,15 +91,15 @@ GameLib.D3.Mesh.Plane.prototype.createInstance = function() { 'Material Plane ' + this.id ) ) - ) - } + ); - /** - * If this is a heightmap - first generate the z-coordinates - */ - if (this.isHeightMap) { - this.generateHeightMapFromBumpMap(); - } + /** + * If this is a heightmap - first generate the z-coordinates + */ + if (this.isHeightMap) { + this.generateHeightMapFromBumpMap(); + } + } /** * Now construct the mesh instance diff --git a/src/game-lib-d3-mesh-sphere.js b/src/game-lib-d3-mesh-sphere.js index 9867e03..bccacc6 100644 --- a/src/game-lib-d3-mesh-sphere.js +++ b/src/game-lib-d3-mesh-sphere.js @@ -46,10 +46,7 @@ GameLib.D3.Mesh.Sphere.prototype.createInstance = function() { var geometry = null; - if (this.vertices.length > 0) { - geometry = new THREE.Geometry(); - this.applyVertexDataToInstance(geometry); - } else { + if (this.vertices.length === 0) { geometry = new THREE.SphereGeometry( this.radius, this.widthSegments, @@ -58,31 +55,21 @@ GameLib.D3.Mesh.Sphere.prototype.createInstance = function() { this.updateVerticesFromGeometryInstance(geometry); } - this.applyBones(geometry); - - var instance = null; - - if (this.skeleton) { - instance = new THREE.SkinnedMesh(geometry) - } else { - instance = new THREE.Mesh(geometry); - } + var instance = GameLib.D3.Mesh.prototype.createInstance.call(this); instance.userData.radius = this.radius; instance.userData.widthSegments = this.widthSegments; instance.userData.heightSegments = this.heightSegments; - this.createInstanceDefaults(instance); - return instance; }; GameLib.D3.Mesh.Sphere.prototype.updateInstance = function() { if ( - this.instance.userData.widthSegments !== this.widthSegments || - 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, @@ -90,9 +77,11 @@ GameLib.D3.Mesh.Sphere.prototype.updateInstance = function() { this.heightSegments ); - this.instance.geometry = geometry; - this.updateVerticesFromGeometryInstance(geometry); + + geometry = this.createInstanceGeometry(); + + this.instance.geometry = geometry; } GameLib.D3.Mesh.prototype.updateInstance.call(this); @@ -115,7 +104,6 @@ GameLib.D3.Mesh.Sphere.prototype.toApiObject = function() { }; /** - * TODO fix all this weird loading shit * Converts a standard object mesh to a GameLib.D3.Mesh * @param graphics GameLib.D3.Graphics * @param objectMesh {Object} diff --git a/src/game-lib-d3-world.js b/src/game-lib-d3-physics-world.js similarity index 90% rename from src/game-lib-d3-world.js rename to src/game-lib-d3-physics-world.js index 5fb6c5f..0612edd 100644 --- a/src/game-lib-d3-world.js +++ b/src/game-lib-d3-physics-world.js @@ -4,7 +4,7 @@ * @param physics * @param apiWorld */ -GameLib.D3.World = function( +GameLib.D3.PhysicsWorld = function( physics, apiWorld ) { @@ -16,11 +16,11 @@ GameLib.D3.World = function( apiWorld = {}; } - if (apiWorld instanceof GameLib.D3.World) { + if (apiWorld instanceof GameLib.D3.PhysicsWorld) { return apiWorld; } - GameLib.D3.API.World.call( + GameLib.D3.API.PhysicsWorld.call( this, apiWorld.id, apiWorld.name, @@ -28,6 +28,7 @@ GameLib.D3.World = function( apiWorld.broadphase, apiWorld.solver, apiWorld.rigidBodies, + apiWorld.contactMaterials, apiWorld.parentEntity ); @@ -53,25 +54,50 @@ GameLib.D3.World = function( ); } + this.rigidBodies = this.rigidBodies.map( + function(rigidBody) { + if (rigidBody instanceof GameLib.D3.API.RigidBody) { + return new GameLib.D3.RigidBody( + this.physics, + rigidBody + ); + } + return rigidBody; + }.bind(this) + ); + + this.contactMaterials = this.contactMaterials.map( + function(contactMaterial) { + if (contactMaterial instanceof GameLib.D3.API.FrictionContactMaterial) { + return new GameLib.D3.FrictionContactMaterial( + this.physics, + contactMaterial + ); + } + return contactMaterial; + }.bind(this) + ); + GameLib.Component.call( this, - GameLib.Component.COMPONENT_WORLD, + GameLib.Component.COMPONENT_PHYSICS_WORLD, { 'broadphase' : GameLib.D3.Broadphase, 'solver' : GameLib.D3.Solver, - 'rigidBodies' : [GameLib.D3.RigidBody] + 'rigidBodies' : [GameLib.D3.RigidBody], + 'contactMaterials' : [GameLib.D3.FrictionContactMaterial] } ); }; -GameLib.D3.World.prototype = Object.create(GameLib.D3.API.World.prototype); -GameLib.D3.World.prototype.constructor = GameLib.D3.World; +GameLib.D3.PhysicsWorld.prototype = Object.create(GameLib.D3.API.PhysicsWorld.prototype); +GameLib.D3.PhysicsWorld.prototype.constructor = GameLib.D3.PhysicsWorld; /** * private - * @returns {GameLib.D3.World|GameLib.D3.Physics.World|*} + * @returns {GameLib.D3.PhysicsWorld|GameLib.D3.Physics.World|*} */ -GameLib.D3.World.prototype.createInstance = function() { +GameLib.D3.PhysicsWorld.prototype.createInstance = function() { if (this.broadphase && this.broadphase.instance && this.solver && this.solver.instance) { @@ -80,16 +106,27 @@ GameLib.D3.World.prototype.createInstance = function() { instance.broadphase = this.broadphase.instance; instance.solver = this.solver.instance; instance.gravity = this.gravity.instance; + + this.contactMaterials.map( + function(contactMaterial) { + if (contactMaterial && contactMaterial.instance) { + instance.addContactMaterial(contactMaterial.instance); + } + } + ); + return instance; + } - return true; + + return false; }; /** * */ -GameLib.D3.World.prototype.updateInstance = function() { +GameLib.D3.PhysicsWorld.prototype.updateInstance = function() { if (!this.instance) { console.log('no world instance'); @@ -99,15 +136,17 @@ GameLib.D3.World.prototype.updateInstance = function() { this.instance.broadphase = this.broadphase.instance; this.instance.solver = this.solver.instance; this.instance.gravity = this.gravity.instance; + + //TODO add contact materials }; /** - * GameLib.D3.World to GameLib.D3.API.World - * @returns {GameLib.D3.API.World} + * GameLib.D3.PhysicsWorld to GameLib.D3.API.PhysicsWorld + * @returns {GameLib.D3.API.PhysicsWorld} */ -GameLib.D3.World.prototype.toApiObject = function() { +GameLib.D3.PhysicsWorld.prototype.toApiObject = function() { - var apiWorld = new GameLib.D3.API.World( + var apiWorld = new GameLib.D3.API.PhysicsWorld( this.id, this.name, this.gravity.toApiObject(), @@ -116,6 +155,9 @@ GameLib.D3.World.prototype.toApiObject = function() { this.rigidBodies.map(function(body){ return GameLib.Utils.IdOrNull(body); }), + this.contactMaterials.map(function(contactMaterial){ + return GameLib.Utils.IdOrNull(contactMaterial); + }), GameLib.Utils.IdOrNull(this.parentEntity) ); @@ -123,21 +165,21 @@ GameLib.D3.World.prototype.toApiObject = function() { }; /** - * GameLib.D3.World from Object World + * GameLib.D3.PhysicsWorld from Object World * @param graphics * @param objectComponent - * @returns {GameLib.D3.World} + * @returns {GameLib.D3.PhysicsWorld} * @constructor */ -GameLib.D3.World.FromObject = function(graphics, objectComponent) { - var apiWorld = GameLib.D3.API.World.FromObject(objectComponent); - return new GameLib.D3.World( +GameLib.D3.PhysicsWorld.FromObject = function(graphics, objectComponent) { + var apiWorld = GameLib.D3.API.PhysicsWorld.FromObject(objectComponent); + return new GameLib.D3.PhysicsWorld( graphics, apiWorld ); }; -GameLib.D3.World.prototype.step = function(deltaTime) { +GameLib.D3.PhysicsWorld.prototype.step = function(deltaTime) { if (this.isCannon) { this.instance.step(deltaTime); @@ -150,14 +192,14 @@ GameLib.D3.World.prototype.step = function(deltaTime) { }; // -// GameLib.D3.World.prototype.step = function( +// GameLib.D3.PhysicsWorld.prototype.step = function( // fixedStep, // dtStep // ) { // // }; // -// GameLib.D3.World.prototype.generateWireframeViewTriangleMesh = function( +// GameLib.D3.PhysicsWorld.prototype.generateWireframeViewTriangleMesh = function( // graphics, // triangleMeshShape, // normalLength, @@ -264,7 +306,7 @@ GameLib.D3.World.prototype.step = function(deltaTime) { // * @returns {THREE.Mesh|this.meshes} // * @constructor // */ -// GameLib.D3.World.prototype.generateWireframeViewConvexPolyMesh = function( +// GameLib.D3.PhysicsWorld.prototype.generateWireframeViewConvexPolyMesh = function( // graphics, // convexPolyMeshShape, // normalLength, @@ -362,7 +404,7 @@ GameLib.D3.World.prototype.step = function(deltaTime) { // * @returns {Object} // * @constructor // */ -// GameLib.D3.World.prototype.generateTriangleMeshShapeDivided = function( +// GameLib.D3.PhysicsWorld.prototype.generateTriangleMeshShapeDivided = function( // graphics, // graphicsMesh, // mass, @@ -453,7 +495,7 @@ GameLib.D3.World.prototype.step = function(deltaTime) { // } // }; // -// GameLib.D3.World.prototype.generateConvexPolyShape = function( +// GameLib.D3.PhysicsWorld.prototype.generateConvexPolyShape = function( // graphics, // mesh // ) { @@ -521,7 +563,7 @@ GameLib.D3.World.prototype.step = function(deltaTime) { // * @returns {GameLib.D3.Shape} // * @constructor // */ -// GameLib.D3.World.prototype.generateTriangleMeshShape = function( +// GameLib.D3.PhysicsWorld.prototype.generateTriangleMeshShape = function( // graphics, // graphicsMesh // ) { @@ -608,7 +650,7 @@ GameLib.D3.World.prototype.step = function(deltaTime) { // * @returns {GameLib.D3.RigidBody} // * @constructor // */ -// GameLib.D3.World.prototype.fixupTriangleMeshShape = function( +// GameLib.D3.PhysicsWorld.prototype.fixupTriangleMeshShape = function( // triangleMeshBody, // triangleMeshShapes, // rayscale, diff --git a/src/game-lib-d3-raycast-vehicle.js b/src/game-lib-d3-raycast-vehicle.js index 0564167..4d2d9ef 100644 --- a/src/game-lib-d3-raycast-vehicle.js +++ b/src/game-lib-d3-raycast-vehicle.js @@ -26,6 +26,8 @@ GameLib.D3.RaycastVehicle = function ( apiRaycastVehicle.name, apiRaycastVehicle.chassis, apiRaycastVehicle.wheels, + apiRaycastVehicle.raycastWheels, + apiRaycastVehicle.parentWorld, apiRaycastVehicle.parentEntity ); @@ -37,8 +39,8 @@ GameLib.D3.RaycastVehicle = function ( } this.wheels = this.wheels.map(function(wheel){ - if (wheel instanceof GameLib.D3.API.RaycastWheel) { - return new GameLib.D3.RaycastWheel( + if (wheel instanceof GameLib.D3.API.RigidBody) { + return new GameLib.D3.RigidBody( this.physics, wheel ) @@ -47,12 +49,25 @@ GameLib.D3.RaycastVehicle = function ( } }.bind(this)); + this.raycastWheels = this.raycastWheels.map(function(raycastWheel){ + if (raycastWheel instanceof GameLib.D3.API.RaycastWheel) { + return new GameLib.D3.RaycastWheel( + this.physics, + raycastWheel + ) + } else { + return raycastWheel; + } + }.bind(this)); + GameLib.Component.call( this, GameLib.Component.COMPONENT_RAYCAST_VEHICLE, { - 'chassis' : GameLib.D3.RigidBody, - 'wheels' : [GameLib.D3.RaycastWheel] + 'chassis' : GameLib.D3.RigidBody, + 'wheels' : [GameLib.D3.RigidBody], + 'raycastWheels' : [GameLib.D3.RaycastWheel], + 'parentWorld' : GameLib.D3.PhysicsWorld } ); }; @@ -75,18 +90,27 @@ GameLib.D3.RaycastVehicle.prototype.createInstance = function() { var instance = false; if (this.chassis && this.chassis.instance) { - var instance = new CANNON.RaycastVehicle({ + + instance = new CANNON.RaycastVehicle({ chassisBody: this.chassis.instance }); + + this.raycastWheels.map(function(wheel){ + instance.addWheel(wheel.instance); + }); + + if (this.parentWorld && this.parentWorld.instance) { + instance.addToWorld(this.parentWorld.instance); + } } return instance; }; GameLib.D3.RaycastVehicle.prototype.updateInstance = function() { - this.instance.chassisBody = this.chassis.instance; + // this.instance.chassisBody = this.chassis.instance; //TODO: add / remove wheels? - console.log('TODO: add/remove wheels?'); + console.log('TODO: update raycast vehicle instance'); }; /** @@ -102,6 +126,10 @@ GameLib.D3.RaycastVehicle.prototype.toApiObject = function() { this.wheels.map(function(wheel){ return GameLib.Utils.IdOrNull(wheel); }), + this.raycastWheels.map(function(raycastWheel){ + return GameLib.Utils.IdOrNull(raycastWheel); + }), + GameLib.Utils.IdOrNull(this.parentWorld), GameLib.Utils.IdOrNull(this.parentEntity) ); diff --git a/src/game-lib-d3-rigid-body.js b/src/game-lib-d3-rigid-body.js index 1b9542e..2c44146 100644 --- a/src/game-lib-d3-rigid-body.js +++ b/src/game-lib-d3-rigid-body.js @@ -40,6 +40,7 @@ GameLib.D3.RigidBody = function ( apiRigidBody.fixedRotation, apiRigidBody.shapes, apiRigidBody.kinematic, + apiRigidBody.parentMesh, apiRigidBody.parentEntity ); @@ -71,7 +72,8 @@ GameLib.D3.RigidBody = function ( this, GameLib.Component.COMPONENT_RIGID_BODY, { - 'shapes' : [GameLib.D3.Shape] + 'shapes' : [GameLib.D3.Shape], + 'parentMesh' : GameLib.D3.Mesh } ); }; @@ -152,6 +154,30 @@ GameLib.D3.RigidBody.prototype.updateInstance = function() { this.instance.kinematic = this.kinematic; }; +GameLib.D3.RigidBody.prototype.setFromParentMesh = function() { + + if (!this.parentMesh || !this.parentMesh.instance) { + console.log('no parent mesh or instance'); + } + + this.instance.position.x = this.parentMesh.position.x; + this.instance.position.y = this.parentMesh.position.y; + this.instance.position.z = this.parentMesh.position.z; + + // this.parentMesh.quaternion.x = this.parentMesh.instance.quaternion.x; + // this.parentMesh.quaternion.y = this.parentMesh.instance.quaternion.y; + // this.parentMesh.quaternion.z = this.parentMesh.instance.quaternion.z; + // this.parentMesh.quaternion.w = this.parentMesh.instance.quaternion.w; + // + // this.quaternion.x = this.parentMesh.quaternion.x; + // this.quaternion.y = this.parentMesh.quaternion.y; + // this.quaternion.z = this.parentMesh.quaternion.z; + // this.quaternion.w = this.parentMesh.quaternion.w; + + this.updateInstance(); + +}; + /** * GameLib.D3.RigidBody to GameLib.D3.API.RigidBody * @returns {GameLib.D3.API.RigidBody} @@ -177,6 +203,7 @@ GameLib.D3.RigidBody.prototype.toApiObject = function() { this.fixedRotation, this.shapes.map(function(shape){return GameLib.Utils.IdOrNull(shape)}), this.kinematic, + GameLib.Utils.IdOrNull(this.parentMesh), GameLib.Utils.IdOrNull(this.parentEntity) ); diff --git a/src/game-lib-d3-shape-0.js b/src/game-lib-d3-shape-0.js index 56b55bc..58e0865 100644 --- a/src/game-lib-d3-shape-0.js +++ b/src/game-lib-d3-shape-0.js @@ -89,10 +89,6 @@ GameLib.D3.Shape.prototype.updateInstance = function() { throw new Error('Do not instantiate this class directly - use a child class instead'); }; -GameLib.D3.Shape.prototype.visualize = function() { - -}; - /** * Converts a GameLib.D3.Shape to a GameLib.D3.API.Shape * @returns {GameLib.D3.API.Shape} @@ -121,3 +117,21 @@ GameLib.D3.Shape.prototype.toApiObject = function() { GameLib.D3.Shape.FromObject = function(physics, objectShape) { throw ('not implemented'); }; + +GameLib.D3.Shape.prototype.stopVisualize = function() { + GameLib.Event.Emit( + GameLib.Event.STOP_VISUALIZE, + { + mesh : this.mesh + } + ) +}; + +GameLib.D3.Shape.prototype.visualize = function() { + GameLib.Event.Emit( + GameLib.Event.VISUALIZE, + { + shape : this + } + ) +}; \ No newline at end of file diff --git a/src/game-lib-d3-shape-height-map.js b/src/game-lib-d3-shape-height-map.js index e2dfa11..7c78c55 100644 --- a/src/game-lib-d3-shape-height-map.js +++ b/src/game-lib-d3-shape-height-map.js @@ -103,7 +103,35 @@ GameLib.D3.Shape.HeightMap.prototype.setFromMesh = function() { return; } - this.zValues = this.parentMesh.getHeightData(); + var dim1Array = Array.prototype.slice.call(this.parentMesh.getHeightData()); + + var w = 0; + + var h = 0; + + var width = this.parentMesh.widthSegments + 1; + + var height = this.parentMesh.heightSegments + 1; + + var dim2Array = dim1Array.reduce( + function(result, value) { + + result[h].push(value); + + w++; + + if (w === this.parentMesh.widthSegments) { + w = 0; + h++; + result[h] = []; + } + + return result; + }.bind(this), + [[]] + ); + + this.zValues = dim2Array; this.minValue = 0; this.maxValue = (this.parentMesh.widthSegments + 1) * (this.parentMesh.heightSegments + 1); diff --git a/src/game-lib-system-0.js b/src/game-lib-system-0.js index ab42598..296440e 100644 --- a/src/game-lib-system-0.js +++ b/src/game-lib-system-0.js @@ -34,16 +34,17 @@ GameLib.System = function( GameLib.System.prototype = Object.create(GameLib.API.System.prototype); GameLib.System.prototype.constructor = GameLib.System; -GameLib.System.SYSTEM_TYPE_NONE = 0x0; -GameLib.System.SYSTEM_TYPE_RENDER = 0x1; -GameLib.System.SYSTEM_TYPE_ANIMATION = 0x2; -GameLib.System.SYSTEM_TYPE_INPUT = 0x4; -GameLib.System.SYSTEM_TYPE_STORAGE = 0x8; -GameLib.System.SYSTEM_TYPE_GUI = 0x10; -GameLib.System.SYSTEM_TYPE_PHYSICS = 0x20; -GameLib.System.SYSTEM_TYPE_LINKING = 0x40; -GameLib.System.SYSTEM_TYPE_CUSTOM = 0x80; -GameLib.System.SYSTEM_TYPE_ALL = 0xFFFF; +GameLib.System.SYSTEM_TYPE_NONE = 0x0; +GameLib.System.SYSTEM_TYPE_RENDER = 0x1; +GameLib.System.SYSTEM_TYPE_ANIMATION = 0x2; +GameLib.System.SYSTEM_TYPE_INPUT = 0x4; +GameLib.System.SYSTEM_TYPE_STORAGE = 0x8; +GameLib.System.SYSTEM_TYPE_GUI = 0x10; +GameLib.System.SYSTEM_TYPE_PHYSICS = 0x20; +GameLib.System.SYSTEM_TYPE_LINKING = 0x40; +GameLib.System.SYSTEM_TYPE_CUSTOM = 0x80; +GameLib.System.SYSTEM_TYPE_VISUALIZATION = 0x100; +GameLib.System.SYSTEM_TYPE_ALL = 0xFFFF; GameLib.System.prototype.createInstance = function() { //console.log('GameLib.System.prototype.createInstance();'); diff --git a/src/game-lib-system-animation.js b/src/game-lib-system-animation.js new file mode 100644 index 0000000..9ca160f --- /dev/null +++ b/src/game-lib-system-animation.js @@ -0,0 +1,26 @@ +/** + * System takes care of updating all the entities (based on their component data) + * @param apiSystem GameLib.API.System + * @constructor + */ +GameLib.System.Animation = function( + apiSystem +) { + GameLib.System.call( + this, + apiSystem + ); +}; + +GameLib.System.Animation.prototype = Object.create(GameLib.System.prototype); +GameLib.System.Animation.prototype.constructor = GameLib.System.Animation; + +GameLib.System.Animation.prototype.start = function() { + console.log('todo: animation system start'); +}; + + +GameLib.System.Animation.prototype.stop = function() { + console.log('todo: animation system stop'); +}; + diff --git a/src/game-lib-system-gui.js b/src/game-lib-system-gui.js index b8516ba..b69dd49 100644 --- a/src/game-lib-system-gui.js +++ b/src/game-lib-system-gui.js @@ -75,7 +75,7 @@ GameLib.System.GUI.prototype.start = function() { return this.params.closed; }, set: function(v) { - console.log('override here too'); + // console.log('override here too'); this.params.closed = v; if (this.params.closed) { @@ -451,7 +451,17 @@ GameLib.System.GUI.prototype.buildArrayManagerControl = function( componentTemplate.affected.map(function (component) { if (component[property].indexOf(activeSelection.component) === -1) { component[property].push(activeSelection.component); - addArrayItem(activeSelection.component, component[property].length - 1); + + GameLib.Event.Emit( + GameLib.Event.ARRAY_ITEM_ADDED, + { + component : component, + property : property, + item : activeSelection.component + } + ); + + // addArrayItem(activeSelection.component, component[property].length - 1); } }); @@ -631,7 +641,18 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, } ) ); - } else if (property === 'meshType') { + } else if (property === 'solverType') { + controllers.push( + folder.add( + object, + property, + { + 'gs': GameLib.D3.Solver.GS_SOLVER, + 'split': GameLib.D3.Solver.SPLIT_SOLVER + } + ) + ); + } else if (property === 'meshType') { controllers.push( folder.add( object, @@ -641,7 +662,9 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, 'curve' : GameLib.D3.Mesh.MESH_TYPE_CURVE, 'skinned' : GameLib.D3.Mesh.MESH_TYPE_SKINNED, 'plane' : GameLib.D3.Mesh.MESH_TYPE_PLANE, - 'sphere' : GameLib.D3.Mesh.MESH_TYPE_SPHERE + 'sphere' : GameLib.D3.Mesh.MESH_TYPE_SPHERE, + 'box' : GameLib.D3.Mesh.MESH_TYPE_BOX, + 'cylinder' : GameLib.D3.Mesh.MESH_TYPE_CYLINDER } ) ); @@ -968,6 +991,7 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, controllers.push(folder.add(object, property, 0, 10, 0.001)); } else if ( property === 'widthSegments' || + property === 'radiusSegments' || property === 'heightSegments' ) { controllers.push(folder.add(object, property, 1, 1000, 1)); @@ -990,7 +1014,15 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, property === 'rotationFactor' ) { controllers.push(folder.add(object, property, -100, 100, 0.001)); - } else { + } else if ( + property === 'radius' + ) { + controllers.push(folder.add(object, property, 0, 1000, 0.01)); + } else if ( + property === 'thetaLength' + ) { + controllers.push(folder.add(object, property, -Math.PI * 2, Math.PI * 2, 0.01)); + } else { controllers.push(folder.add(object, property, -10000, 10000, grain)); } } diff --git a/src/game-lib-system-linking.js b/src/game-lib-system-linking.js index 08331fb..5b8367d 100644 --- a/src/game-lib-system-linking.js +++ b/src/game-lib-system-linking.js @@ -37,7 +37,8 @@ GameLib.System.Linking = function( this.meshDeletedSubscription = null; this.imageChangedSubscription = null; this.materialTypeChangedSubscription = null; - this.shapeInstanceCreatedSubscription = null; + this.arrayItemAddedSubscription = null; + this.instanceCreatedSubscription = null; }; GameLib.System.Linking.prototype = Object.create(GameLib.System.prototype); @@ -110,10 +111,15 @@ GameLib.System.Linking.prototype.start = function() { this.materialTypeChanged ); - this.shapeInstanceCreatedSubscription = this.subscribe( - GameLib.Event.SHAPE_INSTANCE_CREATED, - this.shapeInstanceCreated + this.instanceCreatedSubscription = this.subscribe( + GameLib.Event.INSTANCE_CREATED, + this.instanceCreated ); + + this.arrayItemAddedSubscription = this.subscribe( + GameLib.Event.ARRAY_ITEM_ADDED, + this.arrayItemAdded + ) }; GameLib.System.Linking.prototype.link = function(component, data) { @@ -242,7 +248,7 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { */ var index = parentComponent.dependencies.indexOf(component.id); if (index === -1) { - console.warn('dependency mismatch'); + // console.warn('dependency mismatch'); } else { parentComponent.dependencies.splice(index, 1); } @@ -366,7 +372,7 @@ GameLib.System.Linking.prototype.registerDependencies = function(component) { /** * Don't store duplicate dependencies */ - if (this.dependencies[id].indexOf(component === -1)) { + if (this.dependencies[id].indexOf(component) === -1) { this.dependencies[id].push(component); GameLib.Event.Emit( GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE, @@ -506,6 +512,15 @@ GameLib.System.Linking.prototype.imageChanged = function(data) { }; +GameLib.System.Linking.prototype.arrayItemAdded = function(data) { +}; + +GameLib.System.Linking.prototype.arrayItemRemoved = function(data) { +}; + +GameLib.System.Linking.prototype.instanceCreated = function(data) { +}; + GameLib.System.Linking.prototype.meshInstanceCreated = function(data) { this.resolveDependencies(data.mesh); @@ -559,46 +574,16 @@ GameLib.System.Linking.prototype.meshInstanceCreated = function(data) { wheel.parentMesh = data.mesh; } }); -}; - -GameLib.System.Linking.prototype.shapeInstanceCreated = function(data) { /** - * When a shape instance is created, just check if the parentMesh is loaded somewhere and set it. - * - * We also do the reverse, when a mesh instance is created, we check if its the parent of any shape. + * Link Parent Meshes for rigidbodies */ - var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh); - meshes.map( - function(mesh) { - if (data.shape.parentMesh === mesh.id) { - data.shape.parentMesh = mesh; - } + var rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody); + rigidBodies.map(function(rigidBody){ + if (rigidBody.parentMesh === data.mesh.id) { + rigidBody.parentMesh = data.mesh; } - ); - - /** - * We need to now, find the rigid bodies to which the shape belongs, and add it - also the reverse ? - * - * this is not ok - because we are not dealing with links to parent objects - these are dependencies which need - * to be resolved - an array of dependencies... eeek... - */ - // var rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody); - // rigidBodies.map(function(rigidBody){ - // - // rigidBody.shapes = rigidBody.shapes.reduce( - // function(result, shape) { - // if (shape === data.shape.id) { - // result.push(data.shape); - // } - // return result; - // }, - // [] - // ); - // - // }); - - + }); }; GameLib.System.Linking.prototype.lightInstanceCreated = function(data) { @@ -867,6 +852,7 @@ GameLib.System.Linking.prototype.stop = function() { this.meshDeletedSubscription.remove(); this.imageChangedSubscription.remove(); this.materialTypeChangedSubscription.remove(); - this.shapeInstanceCreatedSubscription.remove(); + this.instanceCreatedSubscription.remove(); + this.arrayItemAddedSubscription.remove(); }; diff --git a/src/game-lib-system-physics.js b/src/game-lib-system-physics.js index 935b52f..044d737 100644 --- a/src/game-lib-system-physics.js +++ b/src/game-lib-system-physics.js @@ -12,77 +12,227 @@ GameLib.System.Physics = function( apiSystem ); - this.worldSubscription = null; - this.rigidBodySubscription = null; + this.worlds = []; + this.rigidBodies = []; + this.wheels = []; + this.vehicles = []; + + this.worldSubscription = null; + this.rigidBodySubscription = null; + this.beforeRenderSubscription = null; + this.afterRenderSubscription = null; + + + this.shapeInstanceCreatedSubscription = this.subscribe( + GameLib.Event.SHAPE_INSTANCE_CREATED, + this.shapeInstanceCreated + ); + + this.solverInstanceCreatedSubscription = this.subscribe( + GameLib.Event.SOLVER_INSTANCE_CREATED, + this.solverInstanceCreated + ); + + this.physicsWorldInstanceCreatedSubscription = this.subscribe( + GameLib.Event.PHYSICS_WORLD_INSTANCE_CREATED, + this.physicsWorldInstanceCreated + ); + + this.instanceCreatedSubscription = this.subscribe( + GameLib.Event.INSTANCE_CREATED, + this.instanceCreated + ); + + 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.updateWorlds = function() { - this.worlds = GameLib.EntityManager.Instance.query( - [ - GameLib.D3.World - ] - ); -}; - -GameLib.System.Physics.prototype.updateRigidBodies = function() { - this.rigidBodyEntities = GameLib.EntityManager.Instance.query( - [ - GameLib.D3.RigidBody - ] - ); -}; - GameLib.System.Physics.prototype.start = function() { - this.worldSubscription = this.subscribe( - GameLib.Event.WORLD_INSTANCE_CREATED, - this.updateWorlds + 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) { + world.instance.addEventListener( + 'postStep', + function() { + + this.vehicles.map( + function(vehicle) { + vehicle.instance.wheelInfos.map( + function(wheelInfo, index) { + vehicle.instance.updateWheelTransform(index); + var t = wheelInfo.worldTransform; + // vehicle.wheels[index].instance.position.copy(t.position); + // vehicle.wheels[index].instance.quaternion.copy(t.quaternion); + + // vehicle.raycastWheels[index].parentMesh.localPosition.x = t.position.x; + // vehicle.raycastWheels[index].parentMesh.localPosition.y = t.position.y; + // vehicle.raycastWheels[index].parentMesh.localPosition.z = t.position.z; + + // vehicle.raycastWheels[index].parentMesh.updateInstance(); + } + ); + } + ); + + + }.bind(this) + ) + }.bind(this) ); - this.rigidBodySubscription = this.subscribe( - GameLib.Event.RIGID_BODY_INSTANCE_CREATED, - this.updateRigidBodies + this.beforeRenderSubscription = this.subscribe( + GameLib.Event.BEFORE_RENDER, + this.beforeRender ); - - this.updateWorlds(); - - this.updateRigidBodies(); - }; /** * Update script */ -GameLib.System.Physics.prototype.update = function() { +GameLib.System.Physics.prototype.beforeRender = function(data) { + + this.worlds.map( + function(world) { + world.instance.step(1 / 60.0); + + this.rigidBodies.map( + function(rigidBody){ + 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.updateInstance(); + } + ) + }.bind(this) + ); +}; + +GameLib.System.Physics.prototype.solverInstanceCreated = function(data) { +}; + +GameLib.System.Physics.prototype.arrayItemAdded = function(data) { +}; + +GameLib.System.Physics.prototype.instanceCreated = function(data) { + + if (data.component instanceof GameLib.D3.RaycastVehicle) { + + var worlds = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.PhysicsWorld); + + /** + * First ensure our parent world is linked + */ + worlds.map( + function(world) { + if (data.component.parentWorld === world.id) { + data.component.parentWorld = world; + } + } + ); + + if (!data.component.parentWorld) { + console.log('no parent world'); + } else { + data.component.instance.addToWorld(data.component.parentWorld.instance); + console.log('raycast vehicle instance added to its parent world'); + } + } + + if (data.component instanceof GameLib.D3.RigidBody) { + var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh); + + meshes.map( + function(mesh) { + if (data.component.parentMesh === mesh.id) { + data.component.parentMesh = mesh; + } + } + ) + + } +}; + +GameLib.System.Physics.prototype.physicsWorldInstanceCreated = function(data) { + + var raycastVehicles = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastVehicle); + + raycastVehicles.map( + function(vehicle) { + if (vehicle.parentWorld === data.world.id) { + vehicle.parentWorld = data.world; + // vehicle.instance.addToWorld(data.world.instance); + } + } + ) + + // var contactMaterials = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.FrictionContactMaterial); + // + // data.world.contactMaterials.map( + // function() { + // if () + // } + // ); + +}; + + +GameLib.System.Physics.prototype.shapeInstanceCreated = function(data) { /** - * TODO: progress the world according to delta time + * When a shape instance is created, just check if the parentMesh is loaded somewhere and set it. + * + * We also do the reverse, when a mesh instance is created, we check if its the parent of any shape. */ - this.worlds.map(function( - world - ){ - world.step(1 / 60.0); - }); + var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh); + meshes.map( + function(mesh) { + if (data.shape.parentMesh === mesh.id) { + data.shape.parentMesh = mesh; + } + } + ); - this.rigidBodyEntities.map( + /** + * We need to now, find the rigid bodies to which the shape belongs, and add it - also the reverse ? + * + * this is not ok - because we are not dealing with links to parent objects - these are dependencies which need + * to be resolved - an array of dependencies... eeek... + */ + // var rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody); + // rigidBodies.map(function(rigidBody){ + // + // rigidBody.shapes = rigidBody.shapes.reduce( + // function(result, shape) { + // if (shape === data.shape.id) { + // result.push(data.shape); + // } + // return result; + // }, + // [] + // ); + // + // }); - function (rigidBody) { - - /** - * TODO: update mesh position based on rigidbody position - */ - } - ); }; GameLib.System.Physics.prototype.stop = function() { - this.worlds = []; - this.rigidBodyEntities = []; + this.worlds = []; + this.rigidBodies = []; + this.wheels = []; + this.vehicles = []; if (this.worldSubscription) { this.worldSubscription.remove(); @@ -91,5 +241,20 @@ GameLib.System.Physics.prototype.stop = function() { if (this.rigidBodySubscription) { this.rigidBodySubscription.remove(); } + + if (this.beforeRenderSubscription) { + this.beforeRenderSubscription.remove(); + } + + if (this.afterRenderSubscription) { + this.afterRenderSubscription.remove(); + } + + this.shapeInstanceCreatedSubscription.remove(); + this.solverInstanceCreatedSubscription.remove(); + this.physicsWorldInstanceCreatedSubscription.remove(); + this.instanceCreatedSubscription.remove(); + this.arrayItemAddedSubscription.remove(); + }; diff --git a/src/game-lib-system-render.js b/src/game-lib-system-render.js index e58d9c9..30e6166 100644 --- a/src/game-lib-system-render.js +++ b/src/game-lib-system-render.js @@ -46,11 +46,22 @@ GameLib.System.Render.prototype.start = function() { * Render subscription script */ GameLib.System.Render.prototype.render = function(data) { - this.renderers.map( + + GameLib.Event.Emit( + GameLib.Event.BEFORE_RENDER, + data + ); + + this.renderers.map( function (renderer) { renderer.render(data.delta); } ); + + GameLib.Event.Emit( + GameLib.Event.AFTER_RENDER, + data + ); }; /** diff --git a/src/game-lib-system-storage.js b/src/game-lib-system-storage.js index 5040606..73a3ede 100644 --- a/src/game-lib-system-storage.js +++ b/src/game-lib-system-storage.js @@ -377,7 +377,7 @@ GameLib.System.Storage.prototype.loadComponent = function(toProcess, includeDepe } if (!runtimeComponent) { - throw new Error('Could not create a runtime component: ', component); + throw new Error('Could not create a runtime component: ' + component.name); } if (parentEntity !== null) { diff --git a/src/game-lib-system-visualization.js b/src/game-lib-system-visualization.js new file mode 100644 index 0000000..0c70feb --- /dev/null +++ b/src/game-lib-system-visualization.js @@ -0,0 +1,99 @@ +/** + * System takes care of updating all the entities (based on their component data) + * Visualization System takes care of visualizing all objects which are not meshes (like physics data) + * + * @param apiSystem GameLib.API.System + * @param graphics + * @param physics + * @constructor + */ +GameLib.System.Visualization = function( + apiSystem, + graphics, + physics +) { + + GameLib.System.call( + this, + apiSystem + ); + + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + this.physics = physics; + this.physics.isNotCannonThrow(); + + this.visualizationSubscription = null; + this.stopVisualizationSubscription = null; + +}; + +GameLib.System.Visualization.prototype = Object.create(GameLib.System.prototype); +GameLib.System.Visualization.prototype.constructor = GameLib.System.Visualization; + +GameLib.System.Visualization.prototype.start = function() { + + this.visualizationSubscription = this.subscribe( + GameLib.Event.VISUALIZE, + this.visualize + ); + + this.stopVisualizationSubscription = this.subscribe( + GameLib.Event.STOP_VISUALIZE, + this.stopVisualize + ) +}; + + +GameLib.System.Visualization.prototype.visualize = function(data) { + + var shape = this.instance; + + var geometry = new THREE.Geometry(); + + var v0 = new CANNON.Vec3(); + var v1 = new CANNON.Vec3(); + var v2 = new CANNON.Vec3(); + 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(); + mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial()); + + this.mesh = mesh; +}; + +GameLib.System.Visualization.prototype.stopVisualize = function(data) { +}; + +GameLib.System.Visualization.prototype.stop = function() { + + if (this.visualizationSubscription) { + this.visualizationSubscription.remove(); + } + + if (this.stopVisualizationSubscription) { + this.stopVisualizationSubscription.remove(); + } + +}; +