From a830c0502faf2eeb52d8113b21eafe83e77a700b Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 4 Nov 2016 10:58:48 +0100 Subject: [PATCH 01/14] vehicle controls. todo: + get REAL scaled radius of wheelMesh. + create input class. --- ...-lib-component-raycast-vehicle-controls.js | 86 ++++++++++++++++--- src/game-lib-entity.js | 14 +++ src/game-lib-raycast-vehicle.js | 21 ++++- 3 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/game-lib-component-raycast-vehicle-controls.js b/src/game-lib-component-raycast-vehicle-controls.js index 411adb6..84d0317 100644 --- a/src/game-lib-component-raycast-vehicle-controls.js +++ b/src/game-lib-component-raycast-vehicle-controls.js @@ -1,24 +1,90 @@ GameLib.D3.ComponentRaycastVehicleControls = function( - componentId + componentId, + frontLWheelIndex, + frontRWheelIndex, + backLWheelIndex, + backRWheelIndex, + maxForce, + steering ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; + // maybe we pass this in the constructor + this.raycastVehicleComponent = null; + this.frontLWheelIndex = frontLWheelIndex || 0; + this.frontRWheelIndex = frontRWheelIndex || 1; + this.backLWheelIndex = backLWheelIndex || 2; + this.backRWheelIndex = backRWheelIndex || 3; + + this.maxForce = maxForce || 400; + this.steering = steering || 0.5; + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. GameLib.D3.Utils.Extend(GameLib.D3.ComponentRaycastVehicleControls, GameLib.D3.ComponentInterface); }; ///////////////////////// Methods to override ////////////////////////// -GameLib.D3.ComponentRaycastVehicleControls.prototype.onUpdate = function( - deltaTime, +GameLib.D3.ComponentRaycastVehicleControls.prototype.onSetParentEntity = function( + parentScene, parentEntity ) { - this.parentEntity.mesh.material.color = new THREE.Color(Math.random(), Math.random(), Math.random()); -}; -GameLib.D3.ComponentRaycastVehicleControls.prototype.onRegistered = function( - parentScene -) { - // Hook in document.eventlisteners - // save values & in the update method we just apply them on the vehicle itself + console.log("Set parent!"); + + this.raycastVehicleComponent = parentEntity.getComponent(GameLib.D3.RaycastVehicle); + if(!this.raycastVehicleComponent) { + console.warn("NO RAYCAST VEHICLE FOUND!"); + } else { + + var component = this; + document.addEventListener('keydown', function(event) { + + if (event.keyCode == 73) { // Forward [i] + + component.raycastVehicleComponent.instance.applyEngineForce(-component.maxForce, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(-component.maxForce, component.backRWheelIndex); + + } else if (event.keyCode == 74) { // Left [j] + + component.raycastVehicleComponent.instance.setSteeringValue(component.steering, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(component.steering, component.frontRWheelIndex); + + } else if (event.keyCode == 75) { // Back [k] + + component.raycastVehicleComponent.instance.applyEngineForce(component.maxForce, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(component.maxForce, component.backRWheelIndex); + + } else if (event.keyCode == 76) { // Right [l] + component.raycastVehicleComponent.instance.setSteeringValue(-component.steering, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(-component.steering, component.frontRWheelIndex); + } + + }, false); + + document.addEventListener('keyup', function(event) { + + if (event.keyCode == 73) { // Forward [i] + + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backRWheelIndex); + + } else if (event.keyCode == 74) { // Left [j] + + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontRWheelIndex); + + } else if (event.keyCode == 75) { // Back [k] + + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backRWheelIndex); + + } else if (event.keyCode == 76) { // Right [l] + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontRWheelIndex); + } + + }, false); + + } }; \ No newline at end of file diff --git a/src/game-lib-entity.js b/src/game-lib-entity.js index 75fc2a4..60f745a 100644 --- a/src/game-lib-entity.js +++ b/src/game-lib-entity.js @@ -105,6 +105,20 @@ GameLib.D3.Entity.prototype.addComponent = function( }; +GameLib.D3.Entity.prototype.getComponent = function( + componentType +) { + for(var c in this.componentIds) { + var componentId = this.componentIds[c]; + var component = this.parentScene.componentIdToComponent[componentId]; + if (component instanceof componentType) { + return component; + } + } + + return null; +}; + ///////////////////////// Methods to override ////////////////////////// GameLib.D3.Entity.prototype.onUpdate = function( diff --git a/src/game-lib-raycast-vehicle.js b/src/game-lib-raycast-vehicle.js index bfbcf2c..f84ce77 100644 --- a/src/game-lib-raycast-vehicle.js +++ b/src/game-lib-raycast-vehicle.js @@ -8,7 +8,8 @@ GameLib.D3.RaycastVehicle = function( engine, chassisBody, - wheels + wheels, + wheelBodies ) { this.engine = engine; this.engine.isNotCannonThrow(); @@ -22,6 +23,11 @@ GameLib.D3.RaycastVehicle = function( } this.wheels = wheels; + if(GameLib.D3.Utils.UndefinedOrNull(wheelBodies)) { + wheelBodies = []; + } + this.wheelBodies = wheelBodies; + this.instance = this.createInstance(); GameLib.D3.Utils.Extend(GameLib.D3.RaycastVehicle, GameLib.D3.ComponentInterface); @@ -40,11 +46,14 @@ GameLib.D3.RaycastVehicle.prototype.createInstance = function() { /** * Adds a raycast wheel to this vehicle * @param wheel GameLib.D3.RaycastWheel + * @param wheelRigidBody GameLib.D3.RigidBody */ GameLib.D3.RaycastVehicle.prototype.addWheel = function ( - wheel + wheel, + wheelRigidBody ) { this.wheels.push(wheel); + this.wheelBodies.push(wheelRigidBody); wheel.wheelIndex = this.instance.addWheel(wheel.instance); }; @@ -64,9 +73,13 @@ GameLib.D3.RaycastVehicle.prototype.onUpdate = function( deltaTime, parentEntity ) { - /*for (var i = 0; i < this.getWheelInfo().length; i++) { + for (var i = 0; i < this.getWheelInfo().length; i++) { this.instance.updateWheelTransform(i); - }*/ + var t = this.getWheelInfo()[i].worldTransform; + var wheelBody = this.wheelBodies[i].instance; + wheelBody.position.copy(t.position); + wheelBody.quaternion.copy(t.quaternion); + } }; GameLib.D3.RaycastVehicle.prototype.onRegistered = function( From 12ca785b427e17a9fb8f3826350bcfb503208fee Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 4 Nov 2016 14:57:48 +0100 Subject: [PATCH 02/14] changes: - entities have position, quaternion & scale - components operate on those properties - entities apply those back to the three mesh - scene: renamed threeScene to instance - added camera component - added fly controls component - added scaleOffset to mesh permutation component --- src/game-lib-component-camera-follow.js | 18 ++ src/game-lib-component-camera.js | 31 ++++ src/game-lib-component-fly-controls.js | 201 +++++++++++++++++++++ src/game-lib-component-mesh-permutation.js | 12 +- src/game-lib-entity.js | 34 +++- src/game-lib-rigid-body.js | 12 +- src/game-lib-scene.js | 18 +- 7 files changed, 306 insertions(+), 20 deletions(-) create mode 100644 src/game-lib-component-camera-follow.js create mode 100644 src/game-lib-component-camera.js create mode 100644 src/game-lib-component-fly-controls.js diff --git a/src/game-lib-component-camera-follow.js b/src/game-lib-component-camera-follow.js new file mode 100644 index 0000000..15cd2d2 --- /dev/null +++ b/src/game-lib-component-camera-follow.js @@ -0,0 +1,18 @@ +GameLib.D3.ComponentCameraFollow = function( + componentId, + targetEntity +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentCameraFollow, GameLib.D3.ComponentInterface); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentCameraFollow.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + // +}; \ No newline at end of file diff --git a/src/game-lib-component-camera.js b/src/game-lib-component-camera.js new file mode 100644 index 0000000..6d52332 --- /dev/null +++ b/src/game-lib-component-camera.js @@ -0,0 +1,31 @@ +GameLib.D3.ComponentCamera = function( + componentId, + threeCamera +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentCamera, GameLib.D3.ComponentInterface); + + // Component fields + this.threeCamera = threeCamera; +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentCamera.prototype.onLateUpdate = function( + deltaTime, + parentEntity +) { + + var quat = new THREE.Quaternion( + parentEntity.quaternion.x, + parentEntity.quaternion.y, + parentEntity.quaternion.z, + parentEntity.quaternion.w + ); + + this.threeCamera.quaternion.copy(quat); + this.threeCamera.position.copy(parentEntity.position); + +}; \ No newline at end of file diff --git a/src/game-lib-component-fly-controls.js b/src/game-lib-component-fly-controls.js new file mode 100644 index 0000000..7c919c0 --- /dev/null +++ b/src/game-lib-component-fly-controls.js @@ -0,0 +1,201 @@ +GameLib.D3.ComponentFlyControls = function( + componentId +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentFlyControls, GameLib.D3.ComponentInterface); + + // Component fields + this.pitch = 0; + this.yaw = 0; + this.canRotate = false; + this.moveSpeed = 22.2; + this.moveForward = false; + this.moveBackward = false; + this.moveLeft = false; + this.moveRight = false; + this.moveUp = false; + this.moveDown = false; + +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentFlyControls.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + // Apply rotation + var rotation = new THREE.Euler( + this.pitch, + this.yaw, + 0, + "YXZ" + ); + + var quat = new THREE.Quaternion().setFromEuler( + rotation + ); + + parentEntity.quaternion.x = quat.x; + parentEntity.quaternion.y = quat.y; + parentEntity.quaternion.z = quat.z; + parentEntity.quaternion.w = quat.w; + + // Apply translation + var direction = new THREE.Vector3(0, 0, -1); + direction = direction.applyEuler(rotation).normalize(); + + if(this.moveForward) { + + parentEntity.position.x += direction.x * (deltaTime * this.moveSpeed); + parentEntity.position.y += direction.y * (deltaTime * this.moveSpeed); + parentEntity.position.z += direction.z * (deltaTime * this.moveSpeed); + + } else if(this.moveBackward) { + + parentEntity.position.x -= direction.x * (deltaTime * this.moveSpeed); + parentEntity.position.y -= direction.y * (deltaTime * this.moveSpeed); + parentEntity.position.z -= direction.z * (deltaTime * this.moveSpeed); + + } + + if(this.moveLeft) { + + var right = direction.cross(new THREE.Vector3(0, 1, 0)); + parentEntity.position.x -= right.x * (deltaTime * this.moveSpeed); + parentEntity.position.y -= right.y * (deltaTime * this.moveSpeed); + parentEntity.position.z -= right.z * (deltaTime * this.moveSpeed); + + } else if(this.moveRight) { + + var right = direction.cross(new THREE.Vector3(0, 1, 0)); + parentEntity.position.x += right.x * (deltaTime * this.moveSpeed); + parentEntity.position.y += right.y * (deltaTime * this.moveSpeed); + parentEntity.position.z += right.z * (deltaTime * this.moveSpeed); + + } + + // Absolute Y-Axis + if(this.moveUp) { + + parentEntity.position.y += (deltaTime * this.moveSpeed); + + } else if(this.moveDown) { + + parentEntity.position.y -= (deltaTime * this.moveSpeed); + + } +}; + +GameLib.D3.ComponentFlyControls.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + var component = this; + + // Lock cursor + var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document; + var element = document.body; + + document.addEventListener('click', function(event) { + if(havePointerLock) { + if(event.button == 0) { + component.canRotate = true; + element.requestPointerLock(); + } else if(event.button == 2) { + component.canRotate = false; + document.exitPointerLock(); + } + } + }); + + if(havePointerLock) { + element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock; + document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock; + } + + + // Mouse move + document.addEventListener('mousemove', function (event) { + if(component.canRotate) { + var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + + component.yaw -= movementX * 0.002; + component.pitch -= movementY * 0.002; + } + + // Save mouseCoords + sys.mouseCoords.set( + (event.clientX / window.innerWidth) * 2 - 1, + -(event.clientY / window.innerHeight) * 2 + 1 + ); + + }, false); + + + // Hook up keyboard controls + document.addEventListener('keydown', function (event) { + + switch (event.keyCode) { + case 87: // w + component.moveForward = true; + break; + + case 65: // a + component.moveLeft = true; + break; + + case 83: // s + component.moveBackward = true; + break; + + case 68: // d + component.moveRight = true; + break; + + case 32: // space + component.moveUp = true; + break; + + case 16: + component.moveDown = true; + break; + } + }, false); + + document.addEventListener('keyup', function (event) { + switch (event.keyCode) { + case 38: // up + case 87: // w + component.moveForward = false; + break; + + case 37: // left + case 65: // a + component.moveLeft = false; + break; + + case 40: // down + case 83: // s + component.moveBackward = false; + break; + + case 39: // right + case 68: // d + component.moveRight = false; + break; + + case 32: // space + component.moveUp = false; + break; + + case 16: + component.moveDown = false; + break; + } + }, false); + +}; \ No newline at end of file diff --git a/src/game-lib-component-mesh-permutation.js b/src/game-lib-component-mesh-permutation.js index a90c2af..0ad3c36 100644 --- a/src/game-lib-component-mesh-permutation.js +++ b/src/game-lib-component-mesh-permutation.js @@ -1,13 +1,15 @@ GameLib.D3.ComponentMeshPermutation = function( componentId, positionOffset, - quaternionOffset + quaternionOffset, + scaleOffset ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; this.positionOffset = positionOffset || new GameLib.D3.Vector3(0, 0, 0); this.quaternionOffset = quaternionOffset || new GameLib.D3.Quaternion(0, 0, 0, 1); + this.scaleOffset = scaleOffset || new GameLib.D3.Vector3(0, 0, 0); // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. GameLib.D3.Utils.Extend(GameLib.D3.ComponentMeshPermutation, GameLib.D3.ComponentInterface); @@ -36,7 +38,15 @@ GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( offsetPosition.copy(this.positionOffset); position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); + var scale = new THREE.Vector3(); + scale.copy(parentEntity.mesh.scale); + + var scaleOffset = new THREE.Vector3(); + scaleOffset.copy(this.scaleOffset); + scale = scale.add(scaleOffset); + parentEntity.mesh.position.copy(position); parentEntity.mesh.quaternion.copy(quaternion); + parentEntity.mesh.scale.copy(scale); } }; \ No newline at end of file diff --git a/src/game-lib-entity.js b/src/game-lib-entity.js index 60f745a..dc3c4b2 100644 --- a/src/game-lib-entity.js +++ b/src/game-lib-entity.js @@ -1,6 +1,9 @@ GameLib.D3.Entity = function( meshId, - componentIds + componentIds, + position, + quaternion, + scale ) { this.meshId = meshId; @@ -14,15 +17,20 @@ GameLib.D3.Entity = function( this.parentScene = null; this.mesh = null; - // todo: - // add position, rotation & scale properties to entity itself! + if(GameLib.D3.Utils.UndefinedOrNull(position)) { + position = new GameLib.D3.Vector3(0, 0, 0); + } + this.position = position; - this.permutate = { - offset : { - position : null, - quaternion : null - } - }; + if(GameLib.D3.Utils.UndefinedOrNull(quaternion)) { + quaternion = new GameLib.D3.Vector4(0, 0, 0, 1); + } + this.quaternion = quaternion; + + if(GameLib.D3.Utils.UndefinedOrNull(scale)) { + scale = new GameLib.D3.Vector3(1, 1, 1); + } + this.scale = scale; }; /** @@ -40,6 +48,12 @@ GameLib.D3.Entity.prototype.update = function( } } + if(this.mesh) { + this.mesh.position.set(this.position.x, this.position.y, this.position.z); + this.mesh.quaternion.set(this.quaternion.x, this.quaternion.y, this.quaternion.z, this.quaternion.w); + this.mesh.scale.set(this.scale.x, this.scale.y, this.scale.z); + } + this.onUpdate(deltaTime); }; @@ -71,7 +85,7 @@ GameLib.D3.Entity.prototype.register = function( this.parentScene = parentScene; if(this.meshId != null && parentScene.meshIdToMesh[this.meshId]) { - parentScene.threeScene.add(parentScene.meshIdToMesh[this.meshId]); + parentScene.instance.add(parentScene.meshIdToMesh[this.meshId]); this.mesh = parentScene.meshIdToMesh[this.meshId]; } diff --git a/src/game-lib-rigid-body.js b/src/game-lib-rigid-body.js index 7e750b9..4c94abf 100644 --- a/src/game-lib-rigid-body.js +++ b/src/game-lib-rigid-body.js @@ -149,14 +149,20 @@ GameLib.D3.RigidBody.prototype.onUpdate = function( deltaTime, parentEntity ) { - if(parentEntity.mesh) { + if(parentEntity) { var quaternion = new THREE.Quaternion(); quaternion.copy(this.instance.quaternion); var position = new THREE.Vector3(); position.copy(this.instance.position); - parentEntity.mesh.position.copy(position); - parentEntity.mesh.quaternion.copy(quaternion); + parentEntity.position.x = position.x; + parentEntity.position.y = position.y; + parentEntity.position.z = position.z; + + parentEntity.quaternion.x = quaternion.x; + parentEntity.quaternion.y = quaternion.y; + parentEntity.quaternion.z = quaternion.z; + parentEntity.quaternion.w = quaternion.w; } }; \ No newline at end of file diff --git a/src/game-lib-scene.js b/src/game-lib-scene.js index 25d4f4d..b8457e1 100644 --- a/src/game-lib-scene.js +++ b/src/game-lib-scene.js @@ -81,10 +81,7 @@ GameLib.D3.Scene = function( } this.entities = entities; - // todo: remove this from the scene class - // changes - this.threeScene = new THREE.Scene(); - this.threeScene.render = true; + this.instance = this.createInstance(); // assoc array this.meshIdToMesh = {}; @@ -93,6 +90,15 @@ GameLib.D3.Scene = function( this.componentIdToComponent = {}; }; + +GameLib.D3.Scene.prototype.createInstance = function ( + +) { + var scene = new THREE.Scene(); + scene.render = true; + return scene; +}; + /** * Loads a scene directly from the API * @param gameLibScene GameLib.D3.Scene @@ -599,7 +605,7 @@ GameLib.D3.Scene.prototype.render = function( renderer, camera ) { - renderer.render(this.threeScene, camera); + renderer.render(this.instance, camera); }; /** @@ -647,5 +653,5 @@ GameLib.D3.Scene.prototype.registerComponent = function( GameLib.D3.Scene.prototype.registerLight = function( light ) { - this.threeScene.add(light); + this.instance.add(light); }; \ No newline at end of file From a0a9d6e45df2e938c42f84328097aa7a8036e422 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 4 Nov 2016 15:02:53 +0100 Subject: [PATCH 03/14] changed one line. --- src/game-lib-component-camera.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/game-lib-component-camera.js b/src/game-lib-component-camera.js index 6d52332..a5d2bb3 100644 --- a/src/game-lib-component-camera.js +++ b/src/game-lib-component-camera.js @@ -17,15 +17,6 @@ GameLib.D3.ComponentCamera.prototype.onLateUpdate = function( deltaTime, parentEntity ) { - - var quat = new THREE.Quaternion( - parentEntity.quaternion.x, - parentEntity.quaternion.y, - parentEntity.quaternion.z, - parentEntity.quaternion.w - ); - - this.threeCamera.quaternion.copy(quat); + this.threeCamera.quaternion.copy(parentEntity.quaternion); this.threeCamera.position.copy(parentEntity.position); - }; \ No newline at end of file From 274ab21d3eda3cf6147c7b4fa9fba41efb267b53 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 4 Nov 2016 15:50:33 +0100 Subject: [PATCH 04/14] follow & look at components --- src/game-lib-component-camera-follow.js | 18 ---------- src/game-lib-component-follow.js | 26 ++++++++++++++ src/game-lib-component-look-at.js | 46 +++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 18 deletions(-) delete mode 100644 src/game-lib-component-camera-follow.js create mode 100644 src/game-lib-component-follow.js create mode 100644 src/game-lib-component-look-at.js diff --git a/src/game-lib-component-camera-follow.js b/src/game-lib-component-camera-follow.js deleted file mode 100644 index 15cd2d2..0000000 --- a/src/game-lib-component-camera-follow.js +++ /dev/null @@ -1,18 +0,0 @@ -GameLib.D3.ComponentCameraFollow = function( - componentId, - targetEntity -) { - this.componentId = componentId || GameLib.D3.Tools.RandomId(); - this.parentEntity = null; - - // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. - GameLib.D3.Utils.Extend(GameLib.D3.ComponentCameraFollow, GameLib.D3.ComponentInterface); -}; - -///////////////////////// Methods to override ////////////////////////// -GameLib.D3.ComponentCameraFollow.prototype.onUpdate = function( - deltaTime, - parentEntity -) { - // -}; \ No newline at end of file diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js new file mode 100644 index 0000000..9aeec20 --- /dev/null +++ b/src/game-lib-component-follow.js @@ -0,0 +1,26 @@ +GameLib.D3.ComponentFollow = function( + componentId, + targetEntity +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentFollow, GameLib.D3.ComponentInterface); + + // + this.targetEntity = targetEntity; + this.moveSpeed = 2.5; +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentFollow.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + if(this.targetEntity) { + var target = new THREE.Vector3().copy(this.targetEntity.position); + + parentEntity.position = parentEntity.position.lerp(target, this.moveSpeed * deltaTime); + } +}; \ No newline at end of file diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js new file mode 100644 index 0000000..6d1a4e2 --- /dev/null +++ b/src/game-lib-component-look-at.js @@ -0,0 +1,46 @@ +GameLib.D3.ComponentLookAt = function( + componentId, + targetEntity +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface); + + // + this.targetEntity = targetEntity; +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentLookAt.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + if(this.targetEntity) { + var target = this.targetEntity.position; + var lookAtMatrix = new THREE.Matrix4().lookAt( + new THREE.Vector3( + parentEntity.position.x, + parentEntity.position.y, + parentEntity.position.z + ), + new THREE.Vector3( + target.x, + target.y, + target.z + ), + new THREE.Vector3( + 0, + 1, + 0 + ) + ); + + var quaternion = new THREE.Quaternion().setFromRotationMatrix(lookAtMatrix); + this.parentEntity.quaternion.x = quaternion.x; + this.parentEntity.quaternion.y = quaternion.y; + this.parentEntity.quaternion.z = quaternion.z; + this.parentEntity.quaternion.w = quaternion.w; + } +}; \ No newline at end of file From 9208ea925791b690d66e87a6a7af1f415f4acd2b Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 4 Nov 2016 16:31:56 +0100 Subject: [PATCH 05/14] follow component target offset. todo: - look at: use target offset. - camera component sphere-rigidbody. --- build/game-lib-min.js | 6 +- build/game-lib.js | 686 ++++++++++++++++++++++++++---- src/game-lib-component-follow.js | 19 +- src/game-lib-component-look-at.js | 6 +- 4 files changed, 622 insertions(+), 95 deletions(-) diff --git a/build/game-lib-min.js b/build/game-lib-min.js index 9fde699..e7c8386 100644 --- a/build/game-lib-min.js +++ b/build/game-lib-min.js @@ -1,3 +1,3 @@ -function GameLib(){}if("undefined"==typeof GameLib.D3&&(GameLib.D3=function(){}),"undefined"==typeof Q){if("undefined"==typeof require)throw console.warn("You need the Q promise library for the GameLib.D3"),new Error("You need the Q promise library for the GameLib.D3");var Q=require("q")}GameLib.D3.BoneWeight=function(e,t){this.boneIndex=e,this.weight=t},GameLib.D3.Bone=function(e,t,i,n,s,o,a,r,h,c){this.id=e,this.name=i,this.boneId=t,"undefined"==typeof n&&(n=[]),this.childBoneIds=n,"undefined"==typeof s&&(s=null),this.parentBoneId=s,"undefined"==typeof o&&(o=new GameLib.D3.Vector4),this.quaternion=o,"undefined"==typeof a&&(a=new GameLib.D3.Vector3(0,0,0)),this.position=a,"undefined"==typeof r&&(r=new GameLib.D3.Vector3(0,0,0)),this.rotation=r,"undefined"==typeof h&&(h=new GameLib.D3.Vector3(1,1,1)),this.scale=h,"undefined"==typeof c&&(c=new GameLib.D3.Vector3(0,1,0)),this.up=c},GameLib.D3.Broadphase=function(e,t,i,n){this.id=e,"undefined"==typeof t&&(t="broadphase-"+i),this.name=t,"undefined"==typeof i&&(i=GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE),this.broadphaseType=i,this.engine=n,this.engine.isNotCannonThrow(),this.instance=this.createInstance()},GameLib.D3.Broadphase.prototype.createInstance=function(){var e=null;if(this.broadphaseType==GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE)e=new this.engine.instance.NaiveBroadphase;else if(this.broadphaseType==GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID)e=new this.engine.instance.GridBroadphase;else{if(this.broadphaseType!=GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP)throw console.warn("Unsupported broadphase type: "+this.broadphaseType),new Error("Unsupported broadphase type: "+this.broadphaseType);e=new this.engine.instance.SAPBroadphase}return e},GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE=1,GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID=2,GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP=3,GameLib.D3.Color=function(e,t,i,n){this.r=e,this.g=t,this.b=i,this.a=n},GameLib.D3.Engine=function(e,t){this.engineType=e,this.instance=t},GameLib.D3.Engine.prototype.isCannon=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_CANNON},GameLib.D3.Engine.prototype.isNotCannonThrow=function(){if(this.engineType!=GameLib.D3.Engine.ENGINE_TYPE_CANNON)throw console.warn("Only CANNON supported for this function"),new Error("Only CANNON supported for this function")},GameLib.D3.Engine.prototype.isAmmo=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_AMMO},GameLib.D3.Engine.prototype.isGoblin=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_GOBLIN},GameLib.D3.Engine.ENGINE_TYPE_CANNON=1,GameLib.D3.Engine.ENGINE_TYPE_AMMO=2,GameLib.D3.Engine.ENGINE_TYPE_GOBLIN=3,GameLib.D3.Entity=function(e,t){this.meshId=e,"undefined"==typeof t&&(t=[]),this.componentIds=t},GameLib.D3.FlyControls=function(e,t,i){this.flySpeed=100,this.canvas=i,this.THREE=t,this.yaw=0,this.pitch=0,this.canRotate=!1,this.moveForward=!1,this.moveBackward=!1,this.moveLeft=!1,this.moveRight=!1,this.moveUp=!1,this.moveDown=!1,this.mouseUpCallback=this.onMouseUp.bind(this),this.mouseDownCallback=this.onMouseDown.bind(this),this.mouseMoveCallback=this.onMouseMove.bind(this),this.mouseWheelCallback=this.onMouseWheel.bind(this),this.keyDownCallback=this.onKeyDown.bind(this),this.keyUpCallback=this.onKeyUp.bind(this),this.camera=e,this.canvas.addEventListener("keydown",this.keyDownCallback,!1),this.canvas.addEventListener("keyup",this.keyUpCallback,!1),this.canvas.addEventListener("mousedown",this.mouseDownCallback,!1),this.canvas.addEventListener("mouseup",this.mouseUpCallback,!1),this.canvas.addEventListener("mousewheel",this.mouseWheelCallback,!1),this.havePointerLock="pointerLockElement"in document||"mozPointerLockElement"in document||"webkitPointerLockElement"in document,this.element=document.body,this.havePointerLock&&(this.element.requestPointerLock=this.element.requestPointerLock||this.element.mozRequestPointerLock||this.element.webkitRequestPointerLock,document.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock)},GameLib.D3.FlyControls.prototype.onMouseWheel=function(e){this.moveForward=!0,this.applyTranslation(.001*e.wheelDelta),e.preventDefault(),this.moveForward=!1},GameLib.D3.FlyControls.prototype.onMouseDown=function(e){1==e.button&&(this.canRotate=!0,this.canvas.addEventListener("mousemove",this.mouseMoveCallback,!1))},GameLib.D3.FlyControls.prototype.onMouseUp=function(e){1==e.button&&(this.canRotate=!1,this.canvas.removeEventListener("mousemove",this.mouseMoveCallback))},GameLib.D3.FlyControls.prototype.applyRotation=function(){this.camera.rotation.set(this.pitch,this.yaw,0,"YXZ")},GameLib.D3.FlyControls.prototype.applyTranslation=function(e){var t=new this.THREE.Vector3(0,0,-1),i=new this.THREE.Euler(0,0,0,"YXZ");i.set(this.pitch,this.yaw,0,"YXZ"),t=t.applyEuler(i);var n=t.normalize(),s=n.cross(new this.THREE.Vector3(0,1,0));this.moveForward?(this.camera.position.x+=n.x*(e*this.flySpeed),this.camera.position.y+=n.y*(e*this.flySpeed),this.camera.position.z+=n.z*(e*this.flySpeed)):this.moveBackward&&(this.camera.position.x-=n.x*(e*this.flySpeed),this.camera.position.y-=n.y*(e*this.flySpeed),this.camera.position.z-=n.z*(e*this.flySpeed)),this.moveLeft?(this.camera.position.x-=s.x*(e*this.flySpeed),this.camera.position.y-=s.y*(e*this.flySpeed),this.camera.position.z-=s.z*(e*this.flySpeed)):this.moveRight&&(this.camera.position.x+=s.x*(e*this.flySpeed),this.camera.position.y+=s.y*(e*this.flySpeed),this.camera.position.z+=s.z*(e*this.flySpeed)),this.moveUp?this.camera.position.y+=e*this.flySpeed:this.moveDown&&(this.camera.position.y-=e*this.flySpeed)},GameLib.D3.FlyControls.prototype.update=function(e){this.applyRotation(),this.applyTranslation(e)},GameLib.D3.FlyControls.prototype.onMouseMove=function(e){if(this.canRotate){var t=e.movementX||e.mozMovementX||e.webkitMovementX||0,i=e.movementY||e.mozMovementY||e.webkitMovementY||0;this.yaw-=.002*t,this.pitch-=.002*i}},GameLib.D3.FlyControls.prototype.onKeyDown=function(e){switch(e.keyCode){case 87:this.moveForward=!0;break;case 65:this.moveLeft=!0;break;case 83:this.moveBackward=!0;break;case 68:this.moveRight=!0;break;case 104:this.moveUp=!0;break;case 98:this.moveDown=!0}},GameLib.D3.FlyControls.prototype.onKeyUp=function(e){switch(e.keyCode){case 38:case 87:this.moveForward=!1;break;case 37:case 65:this.moveLeft=!1;break;case 40:case 83:this.moveBackward=!1;break;case 39:case 68:this.moveRight=!1;break;case 104:this.moveUp=!1;break;case 98:this.moveDown=!1}},GameLib.D3.Game=function(){this.scenes={},this.physicsWorlds=[],this.sceneToPhysicsWorldsMap={}},GameLib.D3.Game.prototype.AddScene=function(e){this.scenes[e.name]=e},GameLib.D3.Game.prototype.AddPhysicsWorld=function(e){this.physicsWorlds.push(e)},GameLib.D3.Game.prototype.LinkPhysicsWorldToScene=function(e,t){this.sceneToPhysicsWorldsMap[t.name]=this.sceneToPhysicsWorldsMap[t.name]||[],this.sceneToPhysicsWorldsMap[t.name].push(e)},GameLib.D3.Game.prototype.GetPhysicsWorldsForScene=function(e){return this.sceneToPhysicsWorldsMap[e.name]},GameLib.D3.Game.prototype.ProcessPhysics=function(e){for(var t in this.sceneToPhysicsWorldsMap){var i=this.sceneToPhysicsWorldsMap[t],n=this.scenes[t];if(n&&i)for(var s=0,o=i.length;s0){var r=GameLib.D3.Texture.loadMaps(e,a,o,t,i,n);Q.all(r).then(function(){s.resolve(o)}).catch(function(e){console.log(e),s.reject(e)})}else s.resolve(o);return s.promise},GameLib.D3.Matrix3=function(e,t,i){this.identity(),e&&(this.rows[0]=e),t&&(this.rows[1]=t),i&&(this.rows[2]=i)},GameLib.D3.Matrix3.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0),new GameLib.D3.Vector4(0,1,0),new GameLib.D3.Vector4(0,0,1)]},GameLib.D3.Matrix4=function(e,t,i,n){this.identity(),e&&(this.rows[0]=e),t&&(this.rows[1]=t),i&&(this.rows[2]=i),n&&(this.rows[3]=n)},GameLib.D3.Matrix4.prototype.rotationMatrixX=function(e){return this.identity(),this.rows[1]=new GameLib.D3.Vector4(0,Math.cos(e),-1*Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(0,Math.sin(e),Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixY=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),0,Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(-1*Math.sin(e),0,Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixZ=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),-1*Math.sin(e),0,0),this.rows[1]=new GameLib.D3.Vector4(Math.sin(e),Math.cos(e),0,0),this},GameLib.D3.Matrix4.prototype.rotateX=function(e,t){return this.identity(),this.rotationMatrixX(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.rotateY=function(e,t){return this.identity(),this.rotationMatrixY(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.rotateZ=function(e,t){return this.identity(),this.rotationMatrixZ(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.multiply=function(e){return e instanceof GameLib.D3.Vector4?new GameLib.D3.Vector4(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z+this.rows[0].w*e.w,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z+this.rows[1].w*e.w,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z+this.rows[2].w*e.w,this.rows[3].x*e.x+this.rows[3].y*e.y+this.rows[3].z*e.z+this.rows[3].w*e.w):e instanceof GameLib.D3.Vector3?new GameLib.D3.Vector3(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z):void 0},GameLib.D3.Matrix4.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0,0),new GameLib.D3.Vector4(0,1,0,0),new GameLib.D3.Vector4(0,0,1,0),new GameLib.D3.Vector4(0,0,0,1)]},GameLib.D3.Matrix4.prototype.lookAt=function(e,t,i){var n=new GameLib.D3.Vector3(e.x,e.y,e.z),s=n.subtract(t).normalize();0===s.squared()&&(s.z=1);var o=i.cross(s).normalize();0===o.squared()&&(s.x+=1e-4,o=i.cross(s).normalize());var a=s.cross(o);return this.rows[0].x=o.x,this.rows[0].y=o.y,this.rows[0].z=o.z,this.rows[1].x=a.x,this.rows[1].y=a.y,this.rows[1].z=a.z,this.rows[2].x=s.x,this.rows[2].y=s.y,this.rows[2].z=s.z,this},GameLib.D3.Mesh=function(e,t,i,n,s,o,a,r,h,c,l,p,d,m,u,f,y,v,L){this.id=e,this.meshId=GameLib.D3.Tools.RandomId(),this.path=t,this.name=i,this.meshType=n,this.vertices=s,this.faces=o,"undefined"==typeof a&&(a=null),this.skeleton=a,"undefined"==typeof r&&(r=[]),this.faceVertexUvs=r,"undefined"==typeof h&&(h=[]),this.skinIndices=h,"undefined"==typeof c&&(c=[]),this.skinWeights=c,"undefined"==typeof l&&(l=[]),this.materials=l,"undefined"==typeof p&&(p=new GameLib.D3.Vector3(0,0,0)),this.position=p,"undefined"==typeof d&&new GameLib.D3.Vector4,this.quaternion=d,"undefined"==typeof m&&(m=new GameLib.D3.Vector3(0,0,0)),this.rotation=m,"undefined"==typeof u&&(u=new GameLib.D3.Vector3(1,1,1)),this.scale=u,"undefined"==typeof f&&(f=new GameLib.D3.Vector3(0,1,0)),this.up=f,this.physics=y,this.parentMeshId=v,this.parentSceneId=L},GameLib.D3.Mesh.TYPE_NORMAL=0,GameLib.D3.Mesh.TYPE_SKINNED=1,GameLib.D3.Mesh.createInstanceMesh=function(e,t,i,n){var s=null;if(e.meshType==GameLib.D3.Mesh.TYPE_NORMAL&&(s=new n.instance.Mesh(t,i)),e.meshType==GameLib.D3.Mesh.TYPE_SKINNED){for(var o=e.skeleton.bones,a=e.skinIndices,r=e.skinWeights,h=[],c=0;c0;){var a=s.pop();if(a.triangle.v0==a.edge.x&&a.triangle.v1==a.edge.y||a.triangle.v1==a.edge.x&&a.triangle.v2==a.edge.y||a.triangle.v2==a.edge.x&&a.triangle.v0==a.edge.y){var r=a.triangle.v1;a.triangle.v1=a.triangle.v2,a.triangle.v2=r;var h=a.triangle.v1uv;a.triangle.v1uv=a.triangle.v2uv,a.triangle.v2uv=h}o.push(a);for(var c=[new GameLib.D3.Vector2(a.triangle.v0,a.triangle.v1),new GameLib.D3.Vector2(a.triangle.v1,a.triangle.v2),new GameLib.D3.Vector2(a.triangle.v2,a.triangle.v0)],l=0;l9||console.log("The vertices are not in the right length : "+e.length);for(var i=[],n=new GameLib.D3.Vector4.Points,s=0;s0&&console.warn("Implement physics worlds code here");for(var h=[],c=0;c0},GameLib.D3.Vector3.normal=function(e,t,i){var n=t.copy(),s=i.copy();return n.subtract(e).cross(s.subtract(e))},GameLib.D3.Vector3.prototype.lookAt=function(e,t){var i=GameLib.D3.Matrix4.lookAt(this,e,t);this.multiply(i)},GameLib.D3.Vector3.prototype.translate=function(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this},GameLib.D3.Vector3.prototype.squared=function(){return this.x*this.x+this.y*this.y+this.z*this.z},GameLib.D3.Vector3.prototype.copy=function(){return new GameLib.D3.Vector3(this.x,this.y,this.z)},GameLib.D3.Vector3.prototype.multiply=function(e){if(e instanceof GameLib.D3.Vector3)this.x*=e.x,this.y*=e.y,this.z*=e.z;else{if(!(e instanceof GameLib.D3.Matrix4))throw console.log("functionality not implemented - please do this"),new Error("not implemented");var t=e.rows[0].x*this.x+e.rows[0].y*this.y+e.rows[0].z*this.z,i=e.rows[1].x*this.x+e.rows[1].y*this.y+e.rows[1].z*this.z,n=e.rows[2].x*this.x+e.rows[2].y*this.y+e.rows[2].z*this.z;this.x=t,this.y=i,this.z=n}return this},GameLib.D3.Vector3.prototype.dot=function(e){return this.x*e.x+this.y*e.y+this.z*e.z},GameLib.D3.Vector3.prototype.normalize=function(){var e=1e-6,t=this.squared();if(to&&(o=h.x,n=t*e)}this.vectors=s;for(var c=(new GameLib.D3.Matrix4).rotationMatrixY(n),l=0;lo&&(o=h.y,n=t*e)}this.vectors=s;for(var c=(new GameLib.D3.Matrix4).rotationMatrixX(n),l=0;ln&&(n=this.vectors[a].x),this.vectors[a].y>s&&(s=this.vectors[a].y),this.vectors[a].z>o&&(o=this.vectors[a].z);return new GameLib.D3.Vector3(Math.abs(n-e),Math.abs(s-t),Math.abs(s-i))},GameLib.D3.Vector4.Points.prototype.average=function(){for(var e=0,t=0,i=0,n=0;nthis.minDistance&&(t.position=t.position.lerp(i,this.moveSpeed*e))}},GameLib.D3.ComponentInterface=function(e){this.componentId=e||GameLib.D3.Tools.RandomId(),this.parentEntity=null},GameLib.D3.ComponentInterface.prototype.setParentEntity=function(e,t){this.parentEntity=t,this.onSetParentEntity(e,t)},GameLib.D3.ComponentInterface.prototype.update=function(e,t){this.onUpdate(e,t)},GameLib.D3.ComponentInterface.prototype.lateUpdate=function(e,t){this.onLateUpdate(e,t)},GameLib.D3.ComponentInterface.prototype.register=function(e){this.onRegistered(e)},GameLib.D3.ComponentInterface.prototype.onUpdate=function(e,t){},GameLib.D3.ComponentInterface.prototype.onLateUpdate=function(e,t){},GameLib.D3.ComponentInterface.prototype.onRegistered=function(e){},GameLib.D3.ComponentInterface.prototype.onSetParentEntity=function(e,t){},GameLib.D3.ComponentLookAt=function(e,t,i){this.componentId=e||GameLib.D3.Tools.RandomId(),this.parentEntity=null,GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt,GameLib.D3.ComponentInterface),this.targetEntity=t,this.targetOffset=i||new GameLib.D3.Vector3(0,0,0)},GameLib.D3.ComponentLookAt.prototype.onUpdate=function(e,t){if(this.targetEntity){var i=this.targetEntity.position,n=(new THREE.Matrix4).lookAt(new THREE.Vector3(t.position.x,t.position.y,t.position.z),new THREE.Vector3(i.x,i.y,i.z),new THREE.Vector3(0,1,0)),o=(new THREE.Quaternion).setFromRotationMatrix(n);this.parentEntity.quaternion.x=o.x,this.parentEntity.quaternion.y=o.y,this.parentEntity.quaternion.z=o.z,this.parentEntity.quaternion.w=o.w}},GameLib.D3.ComponentMeshPermutation=function(e,t,i,n){this.componentId=e||GameLib.D3.Tools.RandomId(),this.parentEntity=null,this.positionOffset=t||new GameLib.D3.Vector3(0,0,0),this.quaternionOffset=i||new GameLib.D3.Quaternion(0,0,0,1),this.scaleOffset=n||new GameLib.D3.Vector3(0,0,0),GameLib.D3.Utils.Extend(GameLib.D3.ComponentMeshPermutation,GameLib.D3.ComponentInterface)},GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate=function(e,t){if(t&&t.mesh){var i=new THREE.Quaternion;i.copy(t.mesh.quaternion);var n=i.clone(),o=new THREE.Vector3;o.copy(t.mesh.position);var s=new THREE.Quaternion;s.copy(this.quaternionOffset),i=i.multiply(s).normalize();var a=new THREE.Vector3;a.copy(this.positionOffset),o=o.add(a.applyQuaternion(n));var r=new THREE.Vector3;r.copy(t.mesh.scale);var h=new THREE.Vector3;h.copy(this.scaleOffset),r=r.add(h),t.mesh.position.copy(o),t.mesh.quaternion.copy(i),t.mesh.scale.copy(r)}},GameLib.D3.ComponentRaycastVehicleControls=function(e,t,i,n,o,s,a){this.componentId=e||GameLib.D3.Tools.RandomId(),this.parentEntity=null,this.raycastVehicleComponent=null,this.frontLWheelIndex=t||0,this.frontRWheelIndex=i||1,this.backLWheelIndex=n||2,this.backRWheelIndex=o||3,this.maxForce=s||400,this.steering=a||.5,GameLib.D3.Utils.Extend(GameLib.D3.ComponentRaycastVehicleControls,GameLib.D3.ComponentInterface)},GameLib.D3.ComponentRaycastVehicleControls.prototype.onSetParentEntity=function(e,t){if(console.log("Set parent!"),this.raycastVehicleComponent=t.getComponent(GameLib.D3.RaycastVehicle),this.raycastVehicleComponent){var i=this;document.addEventListener("keydown",function(e){73==e.keyCode?(i.raycastVehicleComponent.instance.applyEngineForce(-i.maxForce,i.backLWheelIndex),i.raycastVehicleComponent.instance.applyEngineForce(-i.maxForce,i.backRWheelIndex)):74==e.keyCode?(i.raycastVehicleComponent.instance.setSteeringValue(i.steering,i.frontLWheelIndex),i.raycastVehicleComponent.instance.setSteeringValue(i.steering,i.frontRWheelIndex)):75==e.keyCode?(i.raycastVehicleComponent.instance.applyEngineForce(i.maxForce,i.backLWheelIndex),i.raycastVehicleComponent.instance.applyEngineForce(i.maxForce,i.backRWheelIndex)):76==e.keyCode&&(i.raycastVehicleComponent.instance.setSteeringValue(-i.steering,i.frontLWheelIndex),i.raycastVehicleComponent.instance.setSteeringValue(-i.steering,i.frontRWheelIndex))},!1),document.addEventListener("keyup",function(e){73==e.keyCode?(i.raycastVehicleComponent.instance.applyEngineForce(0,i.backLWheelIndex),i.raycastVehicleComponent.instance.applyEngineForce(0,i.backRWheelIndex)):74==e.keyCode?(i.raycastVehicleComponent.instance.setSteeringValue(0,i.frontLWheelIndex),i.raycastVehicleComponent.instance.setSteeringValue(0,i.frontRWheelIndex)):75==e.keyCode?(i.raycastVehicleComponent.instance.applyEngineForce(0,i.backLWheelIndex),i.raycastVehicleComponent.instance.applyEngineForce(0,i.backRWheelIndex)):76==e.keyCode&&(i.raycastVehicleComponent.instance.setSteeringValue(0,i.frontLWheelIndex),i.raycastVehicleComponent.instance.setSteeringValue(0,i.frontRWheelIndex))},!1)}else console.warn("NO RAYCAST VEHICLE FOUND!")},GameLib.D3.Engine=function(e,t){this.engineType=e,this.instance=t},GameLib.D3.Engine.prototype.isCannon=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_CANNON},GameLib.D3.Engine.prototype.isNotCannonThrow=function(){if(this.engineType!=GameLib.D3.Engine.ENGINE_TYPE_CANNON)throw console.warn("Only CANNON supported for this function"),new Error("Only CANNON supported for this function")},GameLib.D3.Engine.prototype.isAmmo=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_AMMO},GameLib.D3.Engine.prototype.isGoblin=function(){return this.engineType==GameLib.D3.Engine.ENGINE_TYPE_GOBLIN},GameLib.D3.Engine.ENGINE_TYPE_CANNON=1,GameLib.D3.Engine.ENGINE_TYPE_AMMO=2,GameLib.D3.Engine.ENGINE_TYPE_GOBLIN=3,GameLib.D3.Entity=function(e,t,i,n,o){this.meshId=e,"undefined"==typeof t&&(t=[]),this.componentIds=t,this.parentScene=null,this.mesh=null,GameLib.D3.Utils.UndefinedOrNull(i)&&(i=new GameLib.D3.Vector3(0,0,0)),this.position=i,GameLib.D3.Utils.UndefinedOrNull(n)&&(n=new GameLib.D3.Vector4(0,0,0,1)),this.quaternion=n,GameLib.D3.Utils.UndefinedOrNull(o)&&(o=new GameLib.D3.Vector3(1,1,1)),this.scale=o},GameLib.D3.Entity.prototype.update=function(e){for(var t in this.componentIds){var i=this.componentIds[t],n=this.parentScene.componentIdToComponent[i];n&&n.onUpdate&&n.onUpdate(e,this)}this.mesh&&(this.mesh.position.set(this.position.x,this.position.y,this.position.z),this.mesh.quaternion.set(this.quaternion.x,this.quaternion.y,this.quaternion.z,this.quaternion.w),this.mesh.scale.set(this.scale.x,this.scale.y,this.scale.z)),this.onUpdate(e)},GameLib.D3.Entity.prototype.lateUpdate=function(e){for(var t in this.componentIds){var i=this.componentIds[t],n=this.parentScene.componentIdToComponent[i];n&&n.onLateUpdate&&n.onLateUpdate(e,this)}this.onLateUpdate(e)},GameLib.D3.Entity.prototype.register=function(e){this.parentScene=e,null!=this.meshId&&e.meshIdToMesh[this.meshId]&&(e.instance.add(e.meshIdToMesh[this.meshId]),this.mesh=e.meshIdToMesh[this.meshId]),this.onRegistered(e)},GameLib.D3.Entity.prototype.addComponentId=function(e){this.componentIds.push(e)},GameLib.D3.Entity.prototype.addComponent=function(e){this.parentScene.registerComponent(e),this.componentIds.push(e.componentId),e.setParentEntity&&"function"==typeof e.setParentEntity&&e.setParentEntity(this.parentScene,this)},GameLib.D3.Entity.prototype.getComponent=function(e){for(var t in this.componentIds){var i=this.componentIds[t],n=this.parentScene.componentIdToComponent[i];if(n instanceof e)return n}return null},GameLib.D3.Entity.prototype.onUpdate=function(e){},GameLib.D3.Entity.prototype.onLateUpdate=function(e){},GameLib.D3.Entity.prototype.onRegistered=function(e){},GameLib.D3.FlyControls=function(e,t,i){this.flySpeed=100,this.canvas=i,this.THREE=t,this.yaw=0,this.pitch=0,this.canRotate=!1,this.moveForward=!1,this.moveBackward=!1,this.moveLeft=!1,this.moveRight=!1,this.moveUp=!1,this.moveDown=!1,this.mouseUpCallback=this.onMouseUp.bind(this),this.mouseDownCallback=this.onMouseDown.bind(this),this.mouseMoveCallback=this.onMouseMove.bind(this),this.mouseWheelCallback=this.onMouseWheel.bind(this),this.keyDownCallback=this.onKeyDown.bind(this),this.keyUpCallback=this.onKeyUp.bind(this),this.camera=e,this.canvas.addEventListener("keydown",this.keyDownCallback,!1),this.canvas.addEventListener("keyup",this.keyUpCallback,!1),this.canvas.addEventListener("mousedown",this.mouseDownCallback,!1),this.canvas.addEventListener("mouseup",this.mouseUpCallback,!1),this.canvas.addEventListener("mousewheel",this.mouseWheelCallback,!1),this.havePointerLock="pointerLockElement"in document||"mozPointerLockElement"in document||"webkitPointerLockElement"in document,this.element=document.body,this.havePointerLock&&(this.element.requestPointerLock=this.element.requestPointerLock||this.element.mozRequestPointerLock||this.element.webkitRequestPointerLock,document.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock)},GameLib.D3.FlyControls.prototype.onMouseWheel=function(e){this.moveForward=!0,this.applyTranslation(.001*e.wheelDelta),e.preventDefault(),this.moveForward=!1},GameLib.D3.FlyControls.prototype.onMouseDown=function(e){1==e.button&&(this.canRotate=!0,this.canvas.addEventListener("mousemove",this.mouseMoveCallback,!1))},GameLib.D3.FlyControls.prototype.onMouseUp=function(e){1==e.button&&(this.canRotate=!1,this.canvas.removeEventListener("mousemove",this.mouseMoveCallback))},GameLib.D3.FlyControls.prototype.applyRotation=function(){this.camera.rotation.set(this.pitch,this.yaw,0,"YXZ")},GameLib.D3.FlyControls.prototype.applyTranslation=function(e){var t=new this.THREE.Vector3(0,0,-1),i=new this.THREE.Euler(0,0,0,"YXZ");i.set(this.pitch,this.yaw,0,"YXZ"),t=t.applyEuler(i);var n=t.normalize(),o=n.cross(new this.THREE.Vector3(0,1,0));this.moveForward?(this.camera.position.x+=n.x*(e*this.flySpeed),this.camera.position.y+=n.y*(e*this.flySpeed),this.camera.position.z+=n.z*(e*this.flySpeed)):this.moveBackward&&(this.camera.position.x-=n.x*(e*this.flySpeed),this.camera.position.y-=n.y*(e*this.flySpeed),this.camera.position.z-=n.z*(e*this.flySpeed)),this.moveLeft?(this.camera.position.x-=o.x*(e*this.flySpeed),this.camera.position.y-=o.y*(e*this.flySpeed),this.camera.position.z-=o.z*(e*this.flySpeed)):this.moveRight&&(this.camera.position.x+=o.x*(e*this.flySpeed),this.camera.position.y+=o.y*(e*this.flySpeed),this.camera.position.z+=o.z*(e*this.flySpeed)),this.moveUp?this.camera.position.y+=e*this.flySpeed:this.moveDown&&(this.camera.position.y-=e*this.flySpeed)},GameLib.D3.FlyControls.prototype.update=function(e){this.applyRotation(),this.applyTranslation(e)},GameLib.D3.FlyControls.prototype.onMouseMove=function(e){if(this.canRotate){var t=e.movementX||e.mozMovementX||e.webkitMovementX||0,i=e.movementY||e.mozMovementY||e.webkitMovementY||0;this.yaw-=.002*t,this.pitch-=.002*i}},GameLib.D3.FlyControls.prototype.onKeyDown=function(e){switch(e.keyCode){case 87:this.moveForward=!0;break;case 65:this.moveLeft=!0;break;case 83:this.moveBackward=!0;break;case 68:this.moveRight=!0;break;case 104:this.moveUp=!0;break;case 98:this.moveDown=!0}},GameLib.D3.FlyControls.prototype.onKeyUp=function(e){switch(e.keyCode){case 38:case 87:this.moveForward=!1;break;case 37:case 65:this.moveLeft=!1;break;case 40:case 83:this.moveBackward=!1;break;case 39:case 68:this.moveRight=!1;break;case 104:this.moveUp=!1;break;case 98:this.moveDown=!1}},GameLib.D3.Game=function(){this.scenes={}},GameLib.D3.Game.prototype.addScene=function(e,t){this.scenes[t]=e},GameLib.D3.Game.prototype.processPhysics=function(e){for(var t in this.scenes){var i=this.scenes[t];for(var n in i.worlds){var o=i.worlds[n];o.step(e)}}},GameLib.D3.Game.prototype.render=function(e,t,i){for(var n in this.scenes){var o=this.scenes[n];o.render(e,t,i)}},GameLib.D3.Game.prototype.update=function(e,t){for(var i in this.scenes){var n=this.scenes[i];for(var o in n.worlds){var s=n.worlds[o];s.step(t)}n.update(e),n.lateUpdate(e)}},GameLib.D3.Graphics=function(e,t){this.graphicsType=e,this.instance=t},GameLib.D3.Graphics.prototype.isThree=function(){return this.graphicsType==GameLib.D3.Graphics.GRAPHICS_TYPE_THREE},GameLib.D3.Graphics.prototype.isNotThreeThrow=function(){if(this.graphicsType!=GameLib.D3.Graphics.GRAPHICS_TYPE_THREE)throw console.warn("Only THREE supported for this function"),new Error("Only THREE supported for this function")},GameLib.D3.Graphics.GRAPHICS_TYPE_THREE=1,GameLib.D3.Heightmap=function(e,t,i,n,o){"undefined"==typeof e&&(e=0),this.sizeX=e,"undefined"==typeof t&&(t=0),this.sizeY=t,"undefined"==typeof i&&(i=[]),this.matrix=i,"undefined"==typeof n&&(n=10),this.elementSize=n,"undefined"==typeof o&&(o=15),this.elementSize=o},GameLib.D3.Heightmap.GenerateInstanceMesh=function(e,t,i){e.isNotThreeThrow(),i.isNotCannonThrow();for(var n=new e.instance.Geometry,o=new i.instance.Vec3,s=new i.instance.Vec3,a=new i.instance.Vec3,r=0;r0){var r=GameLib.D3.Texture.loadMaps(e,a,s,t,i,n);Q.all(r).then(function(){o.resolve(s)}).catch(function(e){console.log(e),o.reject(e)})}else o.resolve(s);return o.promise},GameLib.D3.Matrix3=function(e,t,i){this.identity(),e&&(this.rows[0]=e),t&&(this.rows[1]=t),i&&(this.rows[2]=i)},GameLib.D3.Matrix3.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0),new GameLib.D3.Vector4(0,1,0),new GameLib.D3.Vector4(0,0,1)]},GameLib.D3.Matrix4=function(e,t,i,n){this.identity(),e&&(this.rows[0]=e),t&&(this.rows[1]=t),i&&(this.rows[2]=i),n&&(this.rows[3]=n)},GameLib.D3.Matrix4.prototype.rotationMatrixX=function(e){return this.identity(),this.rows[1]=new GameLib.D3.Vector4(0,Math.cos(e),-1*Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(0,Math.sin(e),Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixY=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),0,Math.sin(e),0),this.rows[2]=new GameLib.D3.Vector4(-1*Math.sin(e),0,Math.cos(e),0),this},GameLib.D3.Matrix4.prototype.rotationMatrixZ=function(e){return this.identity(),this.rows[0]=new GameLib.D3.Vector4(Math.cos(e),-1*Math.sin(e),0,0),this.rows[1]=new GameLib.D3.Vector4(Math.sin(e),Math.cos(e),0,0),this},GameLib.D3.Matrix4.prototype.rotateX=function(e,t){return this.identity(),this.rotationMatrixX(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.rotateY=function(e,t){return this.identity(),this.rotationMatrixY(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.rotateZ=function(e,t){return this.identity(),this.rotationMatrixZ(e),this.multiply(t)},GameLib.D3.Matrix4.prototype.multiply=function(e){return e instanceof GameLib.D3.Vector4?new GameLib.D3.Vector4(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z+this.rows[0].w*e.w,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z+this.rows[1].w*e.w,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z+this.rows[2].w*e.w,this.rows[3].x*e.x+this.rows[3].y*e.y+this.rows[3].z*e.z+this.rows[3].w*e.w):e instanceof GameLib.D3.Vector3?new GameLib.D3.Vector3(this.rows[0].x*e.x+this.rows[0].y*e.y+this.rows[0].z*e.z,this.rows[1].x*e.x+this.rows[1].y*e.y+this.rows[1].z*e.z,this.rows[2].x*e.x+this.rows[2].y*e.y+this.rows[2].z*e.z):void 0; +},GameLib.D3.Matrix4.prototype.identity=function(){this.rows=[new GameLib.D3.Vector4(1,0,0,0),new GameLib.D3.Vector4(0,1,0,0),new GameLib.D3.Vector4(0,0,1,0),new GameLib.D3.Vector4(0,0,0,1)]},GameLib.D3.Matrix4.prototype.lookAt=function(e,t,i){var n=new GameLib.D3.Vector3(e.x,e.y,e.z),o=n.subtract(t).normalize();0===o.squared()&&(o.z=1);var s=i.cross(o).normalize();0===s.squared()&&(o.x+=1e-4,s=i.cross(o).normalize());var a=o.cross(s);return this.rows[0].x=s.x,this.rows[0].y=s.y,this.rows[0].z=s.z,this.rows[1].x=a.x,this.rows[1].y=a.y,this.rows[1].z=a.z,this.rows[2].x=o.x,this.rows[2].y=o.y,this.rows[2].z=o.z,this},GameLib.D3.Mesh=function(e,t,i,n,o,s,a,r,h,c,p,l,d,m,u,f,y,L,v){this.id=e,this.meshId=GameLib.D3.Tools.RandomId(),this.path=t,this.name=i,this.meshType=n,this.vertices=o,this.faces=s,"undefined"==typeof a&&(a=null),this.skeleton=a,"undefined"==typeof r&&(r=[]),this.faceVertexUvs=r,"undefined"==typeof h&&(h=[]),this.skinIndices=h,"undefined"==typeof c&&(c=[]),this.skinWeights=c,"undefined"==typeof p&&(p=[]),this.materials=p,"undefined"==typeof l&&(l=new GameLib.D3.Vector3(0,0,0)),this.position=l,"undefined"==typeof d&&new GameLib.D3.Vector4,this.quaternion=d,"undefined"==typeof m&&(m=new GameLib.D3.Vector3(0,0,0)),this.rotation=m,"undefined"==typeof u&&(u=new GameLib.D3.Vector3(1,1,1)),this.scale=u,"undefined"==typeof f&&(f=new GameLib.D3.Vector3(0,1,0)),this.up=f,this.physics=y,this.parentMeshId=L,this.parentSceneId=v},GameLib.D3.Mesh.TYPE_NORMAL=0,GameLib.D3.Mesh.TYPE_SKINNED=1,GameLib.D3.Mesh.createInstanceMesh=function(e,t,i,n){var o=null;if(e.meshType==GameLib.D3.Mesh.TYPE_NORMAL&&(o=new n.instance.Mesh(t,i)),e.meshType==GameLib.D3.Mesh.TYPE_SKINNED){for(var s=e.skeleton.bones,a=e.skinIndices,r=e.skinWeights,h=[],c=0;c0;){var a=o.pop();if(a.triangle.v0==a.edge.x&&a.triangle.v1==a.edge.y||a.triangle.v1==a.edge.x&&a.triangle.v2==a.edge.y||a.triangle.v2==a.edge.x&&a.triangle.v0==a.edge.y){var r=a.triangle.v1;a.triangle.v1=a.triangle.v2,a.triangle.v2=r;var h=a.triangle.v1uv;a.triangle.v1uv=a.triangle.v2uv,a.triangle.v2uv=h}s.push(a);for(var c=[new GameLib.D3.Vector2(a.triangle.v0,a.triangle.v1),new GameLib.D3.Vector2(a.triangle.v1,a.triangle.v2),new GameLib.D3.Vector2(a.triangle.v2,a.triangle.v0)],p=0;p9||console.log("The vertices are not in the right length : "+e.length);for(var i=[],n=new GameLib.D3.Vector4.Points,o=0;o0&&console.warn("Implement physics worlds code here");for(var h=[],c=0;c0},GameLib.D3.Vector3.normal=function(e,t,i){var n=t.copy(),o=i.copy();return n.subtract(e).cross(o.subtract(e))},GameLib.D3.Vector3.prototype.lookAt=function(e,t){var i=GameLib.D3.Matrix4.lookAt(this,e,t);this.multiply(i)},GameLib.D3.Vector3.prototype.translate=function(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this},GameLib.D3.Vector3.prototype.squared=function(){return this.x*this.x+this.y*this.y+this.z*this.z},GameLib.D3.Vector3.prototype.copy=function(){return new GameLib.D3.Vector3(this.x,this.y,this.z)},GameLib.D3.Vector3.prototype.multiply=function(e){if(e instanceof GameLib.D3.Vector3)this.x*=e.x,this.y*=e.y,this.z*=e.z;else{if(!(e instanceof GameLib.D3.Matrix4))throw console.log("functionality not implemented - please do this"),new Error("not implemented");var t=e.rows[0].x*this.x+e.rows[0].y*this.y+e.rows[0].z*this.z,i=e.rows[1].x*this.x+e.rows[1].y*this.y+e.rows[1].z*this.z,n=e.rows[2].x*this.x+e.rows[2].y*this.y+e.rows[2].z*this.z;this.x=t,this.y=i,this.z=n}return this},GameLib.D3.Vector3.prototype.dot=function(e){return this.x*e.x+this.y*e.y+this.z*e.z},GameLib.D3.Vector3.prototype.normalize=function(){var e=1e-6,t=this.squared();if(ts&&(s=h.x,n=t*e)}this.vectors=o;for(var c=(new GameLib.D3.Matrix4).rotationMatrixY(n),p=0;ps&&(s=h.y,n=t*e)}this.vectors=o;for(var c=(new GameLib.D3.Matrix4).rotationMatrixX(n),p=0;pn&&(n=this.vectors[a].x),this.vectors[a].y>o&&(o=this.vectors[a].y),this.vectors[a].z>s&&(s=this.vectors[a].z);return new GameLib.D3.Vector3(Math.abs(n-e),Math.abs(o-t),Math.abs(o-i))},GameLib.D3.Vector4.Points.prototype.average=function(){for(var e=0,t=0,i=0,n=0;n this.minDistance) { + parentEntity.position = parentEntity.position.lerp(target, this.moveSpeed * deltaTime); + } + } +}; GameLib.D3.ComponentInterface = function( componentId ) { @@ -257,6 +521,196 @@ GameLib.D3.ComponentInterface.prototype.onSetParentEntity = function( parentEntity ) { +}; +GameLib.D3.ComponentLookAt = function( + componentId, + targetEntity, + targetOffset +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface); + + // todo: USE TARGET OFFSET. + this.targetEntity = targetEntity; + this.targetOffset = targetOffset || new GameLib.D3.Vector3(0, 0, 0); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentLookAt.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + if(this.targetEntity) { + var target = this.targetEntity.position; + var lookAtMatrix = new THREE.Matrix4().lookAt( + new THREE.Vector3( + parentEntity.position.x, + parentEntity.position.y, + parentEntity.position.z + ), + new THREE.Vector3( + target.x, + target.y, + target.z + ), + new THREE.Vector3( + 0, + 1, + 0 + ) + ); + + var quaternion = new THREE.Quaternion().setFromRotationMatrix(lookAtMatrix); + this.parentEntity.quaternion.x = quaternion.x; + this.parentEntity.quaternion.y = quaternion.y; + this.parentEntity.quaternion.z = quaternion.z; + this.parentEntity.quaternion.w = quaternion.w; + } +}; +GameLib.D3.ComponentMeshPermutation = function( + componentId, + positionOffset, + quaternionOffset, + scaleOffset +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + this.positionOffset = positionOffset || new GameLib.D3.Vector3(0, 0, 0); + this.quaternionOffset = quaternionOffset || new GameLib.D3.Quaternion(0, 0, 0, 1); + this.scaleOffset = scaleOffset || new GameLib.D3.Vector3(0, 0, 0); + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentMeshPermutation, GameLib.D3.ComponentInterface); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( + deltaTime, + parentEntity +) { + + if(parentEntity && parentEntity.mesh) { + var quaternion = new THREE.Quaternion(); + quaternion.copy(parentEntity.mesh.quaternion); + + var quaternionCopy = quaternion.clone(); + + var position = new THREE.Vector3(); + position.copy(parentEntity.mesh.position); + + var offsetQuaternion = new THREE.Quaternion(); + offsetQuaternion.copy(this.quaternionOffset); + quaternion = quaternion.multiply(offsetQuaternion).normalize(); + + var offsetPosition = new THREE.Vector3(); + offsetPosition.copy(this.positionOffset); + position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); + + var scale = new THREE.Vector3(); + scale.copy(parentEntity.mesh.scale); + + var scaleOffset = new THREE.Vector3(); + scaleOffset.copy(this.scaleOffset); + scale = scale.add(scaleOffset); + + parentEntity.mesh.position.copy(position); + parentEntity.mesh.quaternion.copy(quaternion); + parentEntity.mesh.scale.copy(scale); + } +}; +GameLib.D3.ComponentRaycastVehicleControls = function( + componentId, + frontLWheelIndex, + frontRWheelIndex, + backLWheelIndex, + backRWheelIndex, + maxForce, + steering +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // maybe we pass this in the constructor + this.raycastVehicleComponent = null; + this.frontLWheelIndex = frontLWheelIndex || 0; + this.frontRWheelIndex = frontRWheelIndex || 1; + this.backLWheelIndex = backLWheelIndex || 2; + this.backRWheelIndex = backRWheelIndex || 3; + + this.maxForce = maxForce || 400; + this.steering = steering || 0.5; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentRaycastVehicleControls, GameLib.D3.ComponentInterface); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentRaycastVehicleControls.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + + console.log("Set parent!"); + + this.raycastVehicleComponent = parentEntity.getComponent(GameLib.D3.RaycastVehicle); + if(!this.raycastVehicleComponent) { + console.warn("NO RAYCAST VEHICLE FOUND!"); + } else { + + var component = this; + document.addEventListener('keydown', function(event) { + + if (event.keyCode == 73) { // Forward [i] + + component.raycastVehicleComponent.instance.applyEngineForce(-component.maxForce, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(-component.maxForce, component.backRWheelIndex); + + } else if (event.keyCode == 74) { // Left [j] + + component.raycastVehicleComponent.instance.setSteeringValue(component.steering, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(component.steering, component.frontRWheelIndex); + + } else if (event.keyCode == 75) { // Back [k] + + component.raycastVehicleComponent.instance.applyEngineForce(component.maxForce, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(component.maxForce, component.backRWheelIndex); + + } else if (event.keyCode == 76) { // Right [l] + component.raycastVehicleComponent.instance.setSteeringValue(-component.steering, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(-component.steering, component.frontRWheelIndex); + } + + }, false); + + document.addEventListener('keyup', function(event) { + + if (event.keyCode == 73) { // Forward [i] + + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backRWheelIndex); + + } else if (event.keyCode == 74) { // Left [j] + + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontRWheelIndex); + + } else if (event.keyCode == 75) { // Back [k] + + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backLWheelIndex); + component.raycastVehicleComponent.instance.applyEngineForce(0, component.backRWheelIndex); + + } else if (event.keyCode == 76) { // Right [l] + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontLWheelIndex); + component.raycastVehicleComponent.instance.setSteeringValue(0, component.frontRWheelIndex); + } + + }, false); + + } }; /** * Engine Superset @@ -315,7 +769,10 @@ GameLib.D3.Engine.ENGINE_TYPE_AMMO = 0x2; GameLib.D3.Engine.ENGINE_TYPE_GOBLIN = 0x3; GameLib.D3.Entity = function( meshId, - componentIds + componentIds, + position, + quaternion, + scale ) { this.meshId = meshId; @@ -325,8 +782,24 @@ GameLib.D3.Entity = function( this.componentIds = componentIds; + // constructed at runtime this.parentScene = null; this.mesh = null; + + if(GameLib.D3.Utils.UndefinedOrNull(position)) { + position = new GameLib.D3.Vector3(0, 0, 0); + } + this.position = position; + + if(GameLib.D3.Utils.UndefinedOrNull(quaternion)) { + quaternion = new GameLib.D3.Vector4(0, 0, 0, 1); + } + this.quaternion = quaternion; + + if(GameLib.D3.Utils.UndefinedOrNull(scale)) { + scale = new GameLib.D3.Vector3(1, 1, 1); + } + this.scale = scale; }; /** @@ -344,6 +817,12 @@ GameLib.D3.Entity.prototype.update = function( } } + if(this.mesh) { + this.mesh.position.set(this.position.x, this.position.y, this.position.z); + this.mesh.quaternion.set(this.quaternion.x, this.quaternion.y, this.quaternion.z, this.quaternion.w); + this.mesh.scale.set(this.scale.x, this.scale.y, this.scale.z); + } + this.onUpdate(deltaTime); }; @@ -375,7 +854,7 @@ GameLib.D3.Entity.prototype.register = function( this.parentScene = parentScene; if(this.meshId != null && parentScene.meshIdToMesh[this.meshId]) { - parentScene.threeScene.add(parentScene.meshIdToMesh[this.meshId]); + parentScene.instance.add(parentScene.meshIdToMesh[this.meshId]); this.mesh = parentScene.meshIdToMesh[this.meshId]; } @@ -409,6 +888,20 @@ GameLib.D3.Entity.prototype.addComponent = function( }; +GameLib.D3.Entity.prototype.getComponent = function( + componentType +) { + for(var c in this.componentIds) { + var componentId = this.componentIds[c]; + var component = this.parentScene.componentIdToComponent[componentId]; + if (component instanceof componentType) { + return component; + } + } + + return null; +}; + ///////////////////////// Methods to override ////////////////////////// GameLib.D3.Entity.prototype.onUpdate = function( @@ -679,14 +1172,14 @@ GameLib.D3.Game.prototype.addScene = function( }; GameLib.D3.Game.prototype.processPhysics = function ( - timestep + dt ) { for(var s in this.scenes) { var scene = this.scenes[s]; for(var w in scene.worlds) { var world = scene.worlds[w]; - world.step(timestep); + world.step(dt); } } }; @@ -703,14 +1196,15 @@ GameLib.D3.Game.prototype.render = function( }; GameLib.D3.Game.prototype.update = function( - dt + dt, + fixedDt ) { for(var s in this.scenes) { var scene = this.scenes[s]; for(var w in scene.worlds) { var world = scene.worlds[w]; - world.step(dt); + world.step(fixedDt); } scene.update(dt); @@ -2565,7 +3059,8 @@ GameLib.D3.PolyVertex.prototype.clone = function() { GameLib.D3.RaycastVehicle = function( engine, chassisBody, - wheels + wheels, + wheelBodies ) { this.engine = engine; this.engine.isNotCannonThrow(); @@ -2579,7 +3074,14 @@ GameLib.D3.RaycastVehicle = function( } this.wheels = wheels; + if(GameLib.D3.Utils.UndefinedOrNull(wheelBodies)) { + wheelBodies = []; + } + this.wheelBodies = wheelBodies; + this.instance = this.createInstance(); + + GameLib.D3.Utils.Extend(GameLib.D3.RaycastVehicle, GameLib.D3.ComponentInterface); }; /** @@ -2595,12 +3097,15 @@ GameLib.D3.RaycastVehicle.prototype.createInstance = function() { /** * Adds a raycast wheel to this vehicle * @param wheel GameLib.D3.RaycastWheel + * @param wheelRigidBody GameLib.D3.RigidBody */ GameLib.D3.RaycastVehicle.prototype.addWheel = function ( - wheel + wheel, + wheelRigidBody ) { this.wheels.push(wheel); - this.instance.addWheel(wheel.instance); + this.wheelBodies.push(wheelRigidBody); + wheel.wheelIndex = this.instance.addWheel(wheel.instance); }; /** @@ -2611,6 +3116,28 @@ GameLib.D3.RaycastVehicle.prototype.addWheel = function ( GameLib.D3.RaycastVehicle.prototype.getWheelInfo = function() { return this.instance.wheelInfos; }; + + + +// Override component methods // +GameLib.D3.RaycastVehicle.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + for (var i = 0; i < this.getWheelInfo().length; i++) { + this.instance.updateWheelTransform(i); + var t = this.getWheelInfo()[i].worldTransform; + var wheelBody = this.wheelBodies[i].instance; + wheelBody.position.copy(t.position); + wheelBody.quaternion.copy(t.quaternion); + } +}; + +GameLib.D3.RaycastVehicle.prototype.onRegistered = function( + parentScene +) { + +}; GameLib.D3.RaycastWheel = function( engine, chassisConnectionPointLocal, @@ -2631,7 +3158,6 @@ GameLib.D3.RaycastWheel = function( deltaRotation, rollInfluence, maxSuspensionForce, - isFrontWheel, clippedInvContactDotSuspension, suspensionRelativeVelocity, suspensionForce, @@ -2646,147 +3172,144 @@ GameLib.D3.RaycastWheel = function( this.componentId = GameLib.D3.Tools.RandomId(); - if(typeof chassisConnectionPointLocal == 'undefined') { + if(typeof chassisConnectionPointLocal == 'undefined' || chassisConnectionPointLocal == null) { chassisConnectionPointLocal = new this.engine.instance.Vec3(); } this.chassisConnectionPointLocal = chassisConnectionPointLocal; - if(typeof chassisConnectionPointWorld == 'undefined') { + if(typeof chassisConnectionPointWorld == 'undefined' || chassisConnectionPointWorld == null) { chassisConnectionPointWorld = new this.engine.instance.Vec3(); } this.chassisConnectionPointWorld = chassisConnectionPointWorld; - if(typeof directionLocal == 'undefined') { + if(typeof directionLocal == 'undefined' || directionLocal == null) { directionLocal = new this.engine.instance.Vec3(); } this.directionLocal = directionLocal; - if(typeof directionWorld == 'undefined') { + if(typeof directionWorld == 'undefined' || directionWorld == null) { directionWorld = new this.engine.instance.Vec3(); } this.directionWorld = directionWorld; - if(typeof axleLocal == 'undefined') { + if(typeof axleLocal == 'undefined' || axleLocal == null) { axleLocal = new this.engine.instance.Vec3(); } this.axleLocal = axleLocal; - if(typeof axleWorld == 'undefined') { + if(typeof axleWorld == 'undefined' || axleWorld == null) { axleWorld = new this.engine.instance.Vec3(); } this.axleWorld = axleWorld; - if(typeof suspensionRestLength == 'undefined') { + if(typeof suspensionRestLength == 'undefined' || suspensionRestLength == null) { suspensionRestLength = 1; } this.suspensionRestLength = suspensionRestLength; - if(typeof suspensionMaxLength == 'undefined') { + if(typeof suspensionMaxLength == 'undefined' || suspensionMaxLength == null) { suspensionMaxLength = 2; } this.suspensionMaxLength = suspensionMaxLength; - if(typeof radius == 'undefined') { + if(typeof radius == 'undefined' || radius == null) { radius = 1; } this.radius = radius; - if(typeof suspensionStiffness == 'undefined') { + if(typeof suspensionStiffness == 'undefined' || suspensionStiffness == null) { suspensionStiffness = 100; } this.suspensionStiffness = suspensionStiffness; - if(typeof dampingCompression == 'undefined') { + if(typeof dampingCompression == 'undefined' || dampingCompression == null) { dampingCompression = 10; } this.dampingCompression = dampingCompression; - if(typeof dampingRelaxation == 'undefined') { + if(typeof dampingRelaxation == 'undefined' || dampingRelaxation == null) { dampingRelaxation = 10; } this.dampingRelaxation = dampingRelaxation; - if(typeof frictionSlip == 'undefined') { + if(typeof frictionSlip == 'undefined' || frictionSlip == null) { frictionSlip = 10000; } this.frictionSlip = frictionSlip; - if(typeof steering == 'undefined') { + if(typeof steering == 'undefined' || steering == null) { steering = 0; } this.steering = steering; - if(typeof rotation == 'undefined') { + if(typeof rotation == 'undefined' || rotation == null) { rotation = 0; } this.rotation = rotation; - if(typeof deltaRotation == 'undefined') { + if(typeof deltaRotation == 'undefined' || deltaRotation == null) { deltaRotation = 0; } this.deltaRotation = deltaRotation; - if(typeof rollInfluence == 'undefined') { + if(typeof rollInfluence == 'undefined' || rollInfluence == null) { rollInfluence = 0.01; } this.rollInfluence = rollInfluence; - if(typeof maxSuspensionForce == 'undefined') { + if(typeof maxSuspensionForce == 'undefined' || maxSuspensionForce == null) { maxSuspensionForce = Number.MAX_VALUE; } this.maxSuspensionForce = maxSuspensionForce; - if(typeof isFrontWheel == 'undefined') { - isFrontWheel = true; - } - this.isFrontWheel = isFrontWheel; - - if(typeof clippedInvContactDotSuspension == 'undefined') { + if(typeof clippedInvContactDotSuspension == 'undefined' || clippedInvContactDotSuspension == null) { clippedInvContactDotSuspension = 1; } this.clippedInvContactDotSuspension = clippedInvContactDotSuspension; - if(typeof suspensionRelativeVelocity == 'undefined') { + if(typeof suspensionRelativeVelocity == 'undefined' || suspensionRelativeVelocity == null) { suspensionRelativeVelocity = 0; } this.suspensionRelativeVelocity = suspensionRelativeVelocity; - if(typeof suspensionForce == 'undefined') { + if(typeof suspensionForce == 'undefined' || suspensionForce == null) { suspensionForce = 0; } this.suspensionForce = suspensionForce; - if(typeof skidInfo == 'undefined') { + if(typeof skidInfo == 'undefined' || skidInfo == null) { skidInfo = 0; } this.skidInfo = skidInfo; - if(typeof suspensionLength == 'undefined') { + if(typeof suspensionLength == 'undefined' || suspensionLength == null) { suspensionLength = 0; } this.suspensionLength = suspensionLength; - if(typeof maxSuspensionTravel == 'undefined') { + if(typeof maxSuspensionTravel == 'undefined' || maxSuspensionTravel == null) { maxSuspensionTravel = 1; } this.maxSuspensionTravel = maxSuspensionTravel; - if(typeof useCustomSlidingRotationalSpeed == 'undefined') { + if(typeof useCustomSlidingRotationalSpeed == 'undefined' || useCustomSlidingRotationalSpeed == null) { useCustomSlidingRotationalSpeed = false; } this.useCustomSlidingRotationalSpeed = useCustomSlidingRotationalSpeed; - if(typeof customSlidingRotationalSpeed == 'undefined') { + if(typeof customSlidingRotationalSpeed == 'undefined' || customSlidingRotationalSpeed == null) { customSlidingRotationalSpeed = -0.1; } this.customSlidingRotationalSpeed = customSlidingRotationalSpeed; this.instance = this.createInstance(); + + // this gets assigned at runtime, when the wheel gets added to a vehicle + this.wheelIndex = -1; }; GameLib.D3.RaycastWheel.prototype.createInstance = function() { - - return new this.engine.instance.WheelInfo({ + return { chassisConnectionPointLocal : this.chassisConnectionPointLocal, chassisConnectionPointWorld : this.chassisConnectionPointWorld, directionLocal : this.directionLocal, @@ -2805,7 +3328,6 @@ GameLib.D3.RaycastWheel.prototype.createInstance = function() { deltaRotation : this.deltaRotation, rollInfluence : this.rollInfluence, maxSuspensionForce : this.maxSuspensionForce, - isFrontWheel : this.isFrontWheel, clippedInvContactDotSuspension : this.clippedInvContactDotSuspension, suspensionRelativeVelocity : this.suspensionRelativeVelocity, suspensionForce : this.suspensionForce, @@ -2814,7 +3336,7 @@ GameLib.D3.RaycastWheel.prototype.createInstance = function() { maxSuspensionTravel : this.maxSuspensionTravel, useCustomSlidingRotationalSpeed : this.useCustomSlidingRotationalSpeed, customSlidingRotationalSpeed : this.customSlidingRotationalSpeed - }); + }; }; @@ -3013,11 +3535,11 @@ GameLib.D3.RigidBody.prototype.addShape = function( offset, orientation ) { - if (!offset) { + if (!offset || typeof offset == 'undefined') { offset = new GameLib.D3.Vector3(0,0,0); } - if (!orientation) { + if (!orientation || typeof orientation == 'undefined') { orientation = new GameLib.D3.Vector4(0,0,0,1); } @@ -3038,50 +3560,26 @@ GameLib.D3.RigidBody.prototype.addShape = function( }; ///////////////////////// Methods to override ////////////////////////// -GameLib.D3.RigidBody.prototype.onLateUpdate = function( +GameLib.D3.RigidBody.prototype.onUpdate = function( deltaTime, parentEntity ) { - if(parentEntity.mesh) { + if(parentEntity) { var quaternion = new THREE.Quaternion(); quaternion.copy(this.instance.quaternion); - var quaternionCopy = quaternion.clone(); - var position = new THREE.Vector3(); position.copy(this.instance.position); - // todo: create mesh superset with permutate field - // permutate : { - // offset : { - // quaternion : new Quaternion(), - // position : new Vec3() - // } - // } + parentEntity.position.x = position.x; + parentEntity.position.y = position.y; + parentEntity.position.z = position.z; - /*if(mesh.permutate) { - if(mesh.permutate.offset) { - if(mesh.permutate.offset.quaternion) { - var offsetQuaternion = new THREE.Quaternion(); - offsetQuaternion.copy(mesh.permutate.offset.quaternion); - quaternion = quaternion.multiply(offsetQuaternion).normalize(); - } - - if(mesh.permutate.offset.position) { - var offsetPosition = new THREE.Vector3(); - offsetPosition.copy(mesh.permutate.offset.position); - //position = position.add(offsetPosition); - position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); - } - } - }*/ - - parentEntity.mesh.position.copy(position); - parentEntity.mesh.quaternion.copy(quaternion); + parentEntity.quaternion.x = quaternion.x; + parentEntity.quaternion.y = quaternion.y; + parentEntity.quaternion.z = quaternion.z; + parentEntity.quaternion.w = quaternion.w; } - - - }; /** * Rigid Wheel superset @@ -3187,16 +3685,22 @@ GameLib.D3.Scene = function( } this.entities = entities; - // todo: remove this from the scene class - // changes - //this.threeScene = new THREE.Scene(); - //this.threeScene.render = true; + this.instance = this.createInstance(); // assoc array - //this.meshIdToMesh = {}; + this.meshIdToMesh = {}; // assoc array - //this.componentIdToComponent = {}; + this.componentIdToComponent = {}; +}; + + +GameLib.D3.Scene.prototype.createInstance = function ( + +) { + var scene = new THREE.Scene(); + scene.render = true; + return scene; }; /** @@ -3705,7 +4209,7 @@ GameLib.D3.Scene.prototype.render = function( renderer, camera ) { - renderer.render(this.threeScene, camera); + renderer.render(this.instance, camera); }; /** @@ -3753,7 +4257,7 @@ GameLib.D3.Scene.prototype.registerComponent = function( GameLib.D3.Scene.prototype.registerLight = function( light ) { - this.threeScene.add(light); + this.instance.add(light); }; /** * Physics Shape Superset @@ -4715,6 +5219,12 @@ GameLib.D3.Utils.Extend = function( } }; +GameLib.D3.Utils.UndefinedOrNull = function ( + variable +) { + return typeof variable == 'undefined' || variable == null; +}; + GameLib.D3.Utils.Raycast = function ( from, to, diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js index 9aeec20..05df78e 100644 --- a/src/game-lib-component-follow.js +++ b/src/game-lib-component-follow.js @@ -1,6 +1,8 @@ GameLib.D3.ComponentFollow = function( componentId, - targetEntity + targetEntity, + targetOffset, + minDistance ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; @@ -11,6 +13,14 @@ GameLib.D3.ComponentFollow = function( // this.targetEntity = targetEntity; this.moveSpeed = 2.5; + + + if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) { + targetOffset = new GameLib.D3.Vector3(0, 0, 0); + } + + this.targetOffset = targetOffset; + this.minDistance = minDistance || 0; }; ///////////////////////// Methods to override ////////////////////////// @@ -20,7 +30,12 @@ GameLib.D3.ComponentFollow.prototype.onUpdate = function( ) { if(this.targetEntity) { var target = new THREE.Vector3().copy(this.targetEntity.position); + target.x += this.targetOffset.x; + target.y += this.targetOffset.y; + target.z += this.targetOffset.z; - parentEntity.position = parentEntity.position.lerp(target, this.moveSpeed * deltaTime); + if(target.distanceTo(parentEntity.position) > this.minDistance) { + parentEntity.position = parentEntity.position.lerp(target, this.moveSpeed * deltaTime); + } } }; \ No newline at end of file diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js index 6d1a4e2..a876cdb 100644 --- a/src/game-lib-component-look-at.js +++ b/src/game-lib-component-look-at.js @@ -1,6 +1,7 @@ GameLib.D3.ComponentLookAt = function( componentId, - targetEntity + targetEntity, + targetOffset ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; @@ -8,8 +9,9 @@ GameLib.D3.ComponentLookAt = function( // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface); - // + // todo: USE TARGET OFFSET. this.targetEntity = targetEntity; + this.targetOffset = targetOffset || new GameLib.D3.Vector3(0, 0, 0); }; ///////////////////////// Methods to override ////////////////////////// From 32afbd1abbab624ccd24f3b79399d8e7201a671d Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Tue, 8 Nov 2016 11:13:55 +0100 Subject: [PATCH 06/14] smooth follow components --- src/game-lib-component-follow.js | 44 ++++++++++++++---- src/game-lib-component-look-at.js | 76 ++++++++++++++++++++++--------- src/game-lib-game.js | 3 +- src/game-lib-scene.js | 1 + src/game-lib-shape.js | 7 ++- src/game-lib-vector-3.js | 8 ++++ src/game-lib-world.js | 68 ++++++++++++++++++++++++++- 7 files changed, 171 insertions(+), 36 deletions(-) diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js index 05df78e..162f9dc 100644 --- a/src/game-lib-component-follow.js +++ b/src/game-lib-component-follow.js @@ -12,7 +12,7 @@ GameLib.D3.ComponentFollow = function( // this.targetEntity = targetEntity; - this.moveSpeed = 2.5; + this.moveSpeed = 12.5; if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) { @@ -23,19 +23,45 @@ GameLib.D3.ComponentFollow = function( this.minDistance = minDistance || 0; }; +ComponentFollow_Target_Vec3 = new THREE.Vector3(); +ComponentFollow_TargetToParent_Vec3 = new THREE.Vector3(); + ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentFollow.prototype.onUpdate = function( deltaTime, parentEntity ) { - if(this.targetEntity) { - var target = new THREE.Vector3().copy(this.targetEntity.position); - target.x += this.targetOffset.x; - target.y += this.targetOffset.y; - target.z += this.targetOffset.z; - if(target.distanceTo(parentEntity.position) > this.minDistance) { - parentEntity.position = parentEntity.position.lerp(target, this.moveSpeed * deltaTime); - } + if(this.targetEntity) { + + ComponentFollow_Target_Vec3.set( + this.targetEntity.position.x + this.targetOffset.x, + this.targetEntity.position.y + this.targetOffset.y, + this.targetEntity.position.z + this.targetOffset.z + ); + + ComponentFollow_TargetToParent_Vec3.set( + parentEntity.position.x - this.targetEntity.position.x, + parentEntity.position.y - this.targetEntity.position.y, + parentEntity.position.z - this.targetEntity.position.z + ); + + ComponentFollow_TargetToParent_Vec3.normalize(); + + ComponentFollow_TargetToParent_Vec3.set( + ComponentFollow_TargetToParent_Vec3.x * this.minDistance, + ComponentFollow_TargetToParent_Vec3.y * this.minDistance, + ComponentFollow_TargetToParent_Vec3.z * this.minDistance + ); + + ComponentFollow_Target_Vec3.set( + ComponentFollow_Target_Vec3.x + ComponentFollow_TargetToParent_Vec3.x, + ComponentFollow_Target_Vec3.y + ComponentFollow_TargetToParent_Vec3.y, + ComponentFollow_Target_Vec3.z + ComponentFollow_TargetToParent_Vec3.z + ); + + var t = deltaTime * this.moveSpeed; + //t = t * t * t * (t * (6.0 * t - 15.0) + 10.0); + parentEntity.position = parentEntity.position.lerp(ComponentFollow_Target_Vec3, t); } }; \ No newline at end of file diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js index a876cdb..811ab40 100644 --- a/src/game-lib-component-look-at.js +++ b/src/game-lib-component-look-at.js @@ -11,9 +11,27 @@ GameLib.D3.ComponentLookAt = function( // todo: USE TARGET OFFSET. this.targetEntity = targetEntity; - this.targetOffset = targetOffset || new GameLib.D3.Vector3(0, 0, 0); + + if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) { + targetOffset = new GameLib.D3.Vector3(0, 0, 0); + } + this.targetOffset = targetOffset; + + this.lastTargetPosition = new GameLib.D3.Vector3(0, 0, 0); + this.lastTargetQuaternion = new GameLib.D3.Vector4(0, 0, 0, 1); + this.rotationSpeed = 22.0; }; + +ComponentLookAt_currentPos = new THREE.Vector3(); +ComponentLookAt_targetPos = new THREE.Vector3(); +ComponentLookAt_upVector = new THREE.Vector3(0, 1, 0); +ComponentLookAt_parentQuaternion = new THREE.Quaternion(0, 0, 0, 1); +ComponentLookAt_tmpQuaternion = new THREE.Quaternion(0, 0, 0, 1); +ComponentLookAt_newRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); +ComponentLookAt_lastRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); +ComponentLookAt_lookAtMatrix = new THREE.Matrix4(); + ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentLookAt.prototype.onUpdate = function( deltaTime, @@ -21,28 +39,42 @@ GameLib.D3.ComponentLookAt.prototype.onUpdate = function( ) { if(this.targetEntity) { var target = this.targetEntity.position; - var lookAtMatrix = new THREE.Matrix4().lookAt( - new THREE.Vector3( - parentEntity.position.x, - parentEntity.position.y, - parentEntity.position.z - ), - new THREE.Vector3( - target.x, - target.y, - target.z - ), - new THREE.Vector3( - 0, - 1, - 0 - ) + + ComponentLookAt_currentPos.set( + parentEntity.position.x, + parentEntity.position.y, + parentEntity.position.z ); - var quaternion = new THREE.Quaternion().setFromRotationMatrix(lookAtMatrix); - this.parentEntity.quaternion.x = quaternion.x; - this.parentEntity.quaternion.y = quaternion.y; - this.parentEntity.quaternion.z = quaternion.z; - this.parentEntity.quaternion.w = quaternion.w; + ComponentLookAt_lastRotationQuaternion.set( + this.lastTargetQuaternion.x, + this.lastTargetQuaternion.y, + this.lastTargetQuaternion.z, + this.lastTargetQuaternion.w + ); + + ComponentLookAt_targetPos.set( + target.x + this.targetOffset.x, + target.y + this.targetOffset.y, + target.z + this.targetOffset.z + ); + + ComponentLookAt_lookAtMatrix.lookAt( + ComponentLookAt_currentPos, + ComponentLookAt_targetPos, + ComponentLookAt_upVector + ); + + ComponentLookAt_tmpQuaternion.setFromRotationMatrix(ComponentLookAt_lookAtMatrix); + + var t = deltaTime * this.rotationSpeed; + t = t * t * t * (t * (6.0 * t - 15.0) + 10.0); + + THREE.Quaternion.slerp(ComponentLookAt_lastRotationQuaternion, ComponentLookAt_tmpQuaternion, ComponentLookAt_newRotationQuaternion, t); + + this.parentEntity.quaternion.x = this.lastTargetQuaternion.x = ComponentLookAt_newRotationQuaternion.x; + this.parentEntity.quaternion.y = this.lastTargetQuaternion.y = ComponentLookAt_newRotationQuaternion.y; + this.parentEntity.quaternion.z = this.lastTargetQuaternion.z = ComponentLookAt_newRotationQuaternion.z; + this.parentEntity.quaternion.w = this.lastTargetQuaternion.w = ComponentLookAt_newRotationQuaternion.w; } }; \ No newline at end of file diff --git a/src/game-lib-game.js b/src/game-lib-game.js index 1c8a19c..70cdadd 100644 --- a/src/game-lib-game.js +++ b/src/game-lib-game.js @@ -44,7 +44,8 @@ GameLib.D3.Game.prototype.update = function( for(var w in scene.worlds) { var world = scene.worlds[w]; - world.step(fixedDt); + // NOTE: We are calling the step function with a variable timestep! + world.step(dt); } scene.update(dt); diff --git a/src/game-lib-scene.js b/src/game-lib-scene.js index b8457e1..36919e7 100644 --- a/src/game-lib-scene.js +++ b/src/game-lib-scene.js @@ -97,6 +97,7 @@ GameLib.D3.Scene.prototype.createInstance = function ( var scene = new THREE.Scene(); scene.render = true; return scene; + //return {}; }; /** diff --git a/src/game-lib-shape.js b/src/game-lib-shape.js index 3ae8381..7494c3b 100644 --- a/src/game-lib-shape.js +++ b/src/game-lib-shape.js @@ -139,8 +139,11 @@ GameLib.D3.Shape.prototype.createInstance = function() { } ); } else if (this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL) { - console.warn('Shape type not implemented: ' + this.shapeType); - throw new Error('Shape type not implemented: ' + this.shapeType); + + instance = new this.engine.instance.ConvexPolyhedron( + this.vertices, this.indices + ); + } else { console.warn('Shape type not implemented: ' + this.shapeType); throw new Error('Shape type not implemented: ' + this.shapeType); diff --git a/src/game-lib-vector-3.js b/src/game-lib-vector-3.js index fee45c1..8ca7cfe 100644 --- a/src/game-lib-vector-3.js +++ b/src/game-lib-vector-3.js @@ -90,6 +90,14 @@ GameLib.D3.Vector3.prototype.copy = function () { ); }; +GameLib.D3.Vector3.prototype.lerp = function ( v, alpha ) { + return new GameLib.D3.Vector3( + this.x + ( v.x - this.x ) * alpha, + this.y + ( v.y - this.y ) * alpha, + this.z + ( v.z - this.z ) * alpha + ); +}; + GameLib.D3.Vector3.prototype.multiply = function (s) { if (s instanceof GameLib.D3.Vector3) { this.x *= s.x; diff --git a/src/game-lib-world.js b/src/game-lib-world.js index 1ea9861..1052503 100644 --- a/src/game-lib-world.js +++ b/src/game-lib-world.js @@ -106,10 +106,12 @@ GameLib.D3.World.prototype.step = function( timeStep ) { // todo: figure out, why this call to internal step is more stable for trimesh collisions..... - //this.worldObject.internalStep(timeStep); + //this.instance.internalStep(timeStep); //return; + //console.log("this should not be called."); - var now = performance.now() / 1000; + //var now = Date.now() / 1000; + var now = null; if(!this.lastCallTime){ // last call time not saved, cant guess elapsed time. Take a simple step. this.instance.step(timeStep); @@ -448,6 +450,68 @@ GameLib.D3.World.prototype.generateTriangleMeshShapeDivided = function( } }; +GameLib.D3.World.prototype.generateConvexPolyShape = function( + graphics, + mesh +) { + var processedFaces = 0; + var facesPerSubSection = 2; // *2 -> SUBDIVISION MESH + var subMeshesToMerge = 4; // *2 -> SUBDIVISION MESH + var facesToProcess = subMeshesToMerge * facesPerSubSection; + + var vertices = []; + var indicies = []; + + for(var i = 0; i <= mesh.geometry.faces.length; i++) { + if(processedFaces == facesToProcess || i == mesh.geometry.faces.length) { + + // try and create convex poly........... + var convexIndices = []; + for(var index = 0; index < indicies.length / 3; index++) { + convexIndices.push([ indicies[index * 3], indicies[index * 3 + 1], indicies[index * 3 + 2] ]); + } + + var convexVertices = []; + for(var vert = 0; vert < vertices.length / 3; vert++) { + convexVertices[vert] = new CANNON.Vec3(vertices[vert * 3] * mesh.scale.x, vertices[vert * 3 + 1] * mesh.scale.y, vertices[vert * 3 + 2] * mesh.scale.z); + } + + var meshShape = new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL, {x:1,y:1,z:1},convexVertices, convexIndices); + + var body = new GameLib.D3.RigidBody(this.engine, 0, 1); + body.addShape(meshShape); + + this.addRigidBody(body); + + vertices = []; + indicies = []; + processedFaces = 0; + + console.log("SPLIT MESH TO CONVEX POLY"); + + if(i == mesh.geometry.faces.length) { + break; + } + } + + var face = mesh.geometry.faces[i]; + indicies.push(indicies.length); + indicies.push(indicies.length); + indicies.push(indicies.length); + + var v0 = mesh.geometry.vertices[face.a]; + var v1 = mesh.geometry.vertices[face.b]; + var v2 = mesh.geometry.vertices[face.c]; + + vertices.push(v0.x, v0.y, v0.z); + vertices.push(v1.x, v1.y, v1.z); + vertices.push(v2.x, v2.y, v2.z); + + processedFaces++; + } + +}; + /** * @param graphics GameLib.D3.Graphics * @param graphicsMesh THREE.Mesh From de5961456fbefacd687ae6df2401cc66af495664 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Tue, 8 Nov 2016 11:26:08 +0100 Subject: [PATCH 07/14] reusing vars inside mesh permutation component --- src/game-lib-component-mesh-permutation.js | 43 +++++++++++----------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/game-lib-component-mesh-permutation.js b/src/game-lib-component-mesh-permutation.js index 0ad3c36..e0ded90 100644 --- a/src/game-lib-component-mesh-permutation.js +++ b/src/game-lib-component-mesh-permutation.js @@ -15,6 +15,15 @@ GameLib.D3.ComponentMeshPermutation = function( GameLib.D3.Utils.Extend(GameLib.D3.ComponentMeshPermutation, GameLib.D3.ComponentInterface); }; +ComponentMeshPermutation_quaternion = new THREE.Quaternion(); +ComponentMeshPermutation_quaternionCopy = new THREE.Quaternion(); +ComponentMeshPermutation_position = new THREE.Vector3(); +ComponentMeshPermutation_scale = new THREE.Vector3(); + +ComponentMeshPermutation_offsetQuaternion = new THREE.Quaternion(); +ComponentMeshPermutation_offsetPosition = new THREE.Vector3(); +ComponentMeshPermutation_offsetScale = new THREE.Vector3(); + ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( deltaTime, @@ -22,31 +31,23 @@ GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( ) { if(parentEntity && parentEntity.mesh) { - var quaternion = new THREE.Quaternion(); - quaternion.copy(parentEntity.mesh.quaternion); + ComponentMeshPermutation_quaternion.copy(parentEntity.mesh.quaternion); + ComponentMeshPermutation_quaternionCopy.copy(ComponentMeshPermutation_quaternion); + ComponentMeshPermutation_position.copy(parentEntity.mesh.position); - var quaternionCopy = quaternion.clone(); + ComponentMeshPermutation_offsetQuaternion.copy(this.quaternionOffset); + ComponentMeshPermutation_quaternion = ComponentMeshPermutation_quaternion.multiply(ComponentMeshPermutation_offsetQuaternion).normalize(); - var position = new THREE.Vector3(); - position.copy(parentEntity.mesh.position); + ComponentMeshPermutation_offsetPosition.copy(this.positionOffset); + ComponentMeshPermutation_position = ComponentMeshPermutation_position.add(ComponentMeshPermutation_offsetPosition.applyQuaternion(ComponentMeshPermutation_quaternionCopy)); - var offsetQuaternion = new THREE.Quaternion(); - offsetQuaternion.copy(this.quaternionOffset); - quaternion = quaternion.multiply(offsetQuaternion).normalize(); + ComponentMeshPermutation_scale.copy(parentEntity.mesh.scale); - var offsetPosition = new THREE.Vector3(); - offsetPosition.copy(this.positionOffset); - position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); + ComponentMeshPermutation_offsetScale.copy(this.scaleOffset); + ComponentMeshPermutation_scale = ComponentMeshPermutation_scale.add(ComponentMeshPermutation_offsetScale); - var scale = new THREE.Vector3(); - scale.copy(parentEntity.mesh.scale); - - var scaleOffset = new THREE.Vector3(); - scaleOffset.copy(this.scaleOffset); - scale = scale.add(scaleOffset); - - parentEntity.mesh.position.copy(position); - parentEntity.mesh.quaternion.copy(quaternion); - parentEntity.mesh.scale.copy(scale); + parentEntity.mesh.position.copy(ComponentMeshPermutation_position); + parentEntity.mesh.quaternion.copy(ComponentMeshPermutation_quaternion); + parentEntity.mesh.scale.copy(ComponentMeshPermutation_scale); } }; \ No newline at end of file From 8ddba38561e88e695ff93a276fea437207a08fa6 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Tue, 8 Nov 2016 12:04:42 +0100 Subject: [PATCH 08/14] added more settings for follow & look at components --- src/game-lib-component-follow.js | 31 ++++++++++++++++++++++++++----- src/game-lib-component-look-at.js | 6 +++--- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js index 162f9dc..d1f8a87 100644 --- a/src/game-lib-component-follow.js +++ b/src/game-lib-component-follow.js @@ -2,7 +2,8 @@ GameLib.D3.ComponentFollow = function( componentId, targetEntity, targetOffset, - minDistance + minDistance, + moveSpeed ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; @@ -12,7 +13,7 @@ GameLib.D3.ComponentFollow = function( // this.targetEntity = targetEntity; - this.moveSpeed = 12.5; + this.moveSpeed = moveSpeed || 12.5; if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) { @@ -25,6 +26,8 @@ GameLib.D3.ComponentFollow = function( ComponentFollow_Target_Vec3 = new THREE.Vector3(); ComponentFollow_TargetToParent_Vec3 = new THREE.Vector3(); +ComponentFollow_rotatedTargetOffset_Vec3 = new THREE.Vector3(); +ComponentFollow_tempQuaternion = new THREE.Quaternion(); ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentFollow.prototype.onUpdate = function( @@ -34,10 +37,28 @@ GameLib.D3.ComponentFollow.prototype.onUpdate = function( if(this.targetEntity) { + ComponentFollow_tempQuaternion.set( + this.targetEntity.quaternion.x, + this.targetEntity.quaternion.y, + this.targetEntity.quaternion.z, + this.targetEntity.quaternion.w + ); + + ComponentFollow_rotatedTargetOffset_Vec3.set( + this.targetOffset.x, + this.targetOffset.y, + this.targetOffset.z + ); + + ComponentFollow_rotatedTargetOffset_Vec3 = + ComponentFollow_rotatedTargetOffset_Vec3.applyQuaternion( + ComponentFollow_tempQuaternion + ); + ComponentFollow_Target_Vec3.set( - this.targetEntity.position.x + this.targetOffset.x, - this.targetEntity.position.y + this.targetOffset.y, - this.targetEntity.position.z + this.targetOffset.z + this.targetEntity.position.x + ComponentFollow_rotatedTargetOffset_Vec3.x, + this.targetEntity.position.y + ComponentFollow_rotatedTargetOffset_Vec3.y, + this.targetEntity.position.z + ComponentFollow_rotatedTargetOffset_Vec3.z ); ComponentFollow_TargetToParent_Vec3.set( diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js index 811ab40..a2944e7 100644 --- a/src/game-lib-component-look-at.js +++ b/src/game-lib-component-look-at.js @@ -1,7 +1,8 @@ GameLib.D3.ComponentLookAt = function( componentId, targetEntity, - targetOffset + targetOffset, + rotationSpeed ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; @@ -17,9 +18,8 @@ GameLib.D3.ComponentLookAt = function( } this.targetOffset = targetOffset; - this.lastTargetPosition = new GameLib.D3.Vector3(0, 0, 0); this.lastTargetQuaternion = new GameLib.D3.Vector4(0, 0, 0, 1); - this.rotationSpeed = 22.0; + this.rotationSpeed = rotationSpeed || 22.0; }; From cf57556a0b1ed457b8eccf90f3c3fc0705f47728 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Tue, 8 Nov 2016 12:12:56 +0100 Subject: [PATCH 09/14] look at components rotates the offset towards the targets rotation --- src/game-lib-component-look-at.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js index a2944e7..a26793c 100644 --- a/src/game-lib-component-look-at.js +++ b/src/game-lib-component-look-at.js @@ -23,10 +23,11 @@ GameLib.D3.ComponentLookAt = function( }; +ComponentLookAt_rotatedTargetOffset = new THREE.Vector3(); ComponentLookAt_currentPos = new THREE.Vector3(); ComponentLookAt_targetPos = new THREE.Vector3(); ComponentLookAt_upVector = new THREE.Vector3(0, 1, 0); -ComponentLookAt_parentQuaternion = new THREE.Quaternion(0, 0, 0, 1); +ComponentLookAt_targetQuaternion = new THREE.Quaternion(0, 0, 0, 1); ComponentLookAt_tmpQuaternion = new THREE.Quaternion(0, 0, 0, 1); ComponentLookAt_newRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); ComponentLookAt_lastRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); @@ -53,10 +54,28 @@ GameLib.D3.ComponentLookAt.prototype.onUpdate = function( this.lastTargetQuaternion.w ); + ComponentLookAt_rotatedTargetOffset.set( + this.targetOffset.x, + this.targetOffset.y, + this.targetOffset.z + ); + + ComponentLookAt_targetQuaternion.set( + this.targetEntity.quaternion.x, + this.targetEntity.quaternion.y, + this.targetEntity.quaternion.z, + this.targetEntity.quaternion.w + ); + + ComponentLookAt_rotatedTargetOffset = + ComponentLookAt_rotatedTargetOffset.applyQuaternion( + ComponentLookAt_targetQuaternion + ); + ComponentLookAt_targetPos.set( - target.x + this.targetOffset.x, - target.y + this.targetOffset.y, - target.z + this.targetOffset.z + target.x + ComponentLookAt_rotatedTargetOffset.x, + target.y + ComponentLookAt_rotatedTargetOffset.y, + target.z + ComponentLookAt_rotatedTargetOffset.z ); ComponentLookAt_lookAtMatrix.lookAt( From ac820f70badccd0a57a386aea532de372d715e97 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Wed, 9 Nov 2016 12:37:46 +0100 Subject: [PATCH 10/14] if-guards for 3d-editor --- src/game-lib-component-follow.js | 10 ++++++---- src/game-lib-component-look-at.js | 21 +++++++++++---------- src/game-lib-component-mesh-permutation.js | 17 +++++++++-------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js index d1f8a87..8acfd0d 100644 --- a/src/game-lib-component-follow.js +++ b/src/game-lib-component-follow.js @@ -24,10 +24,12 @@ GameLib.D3.ComponentFollow = function( this.minDistance = minDistance || 0; }; -ComponentFollow_Target_Vec3 = new THREE.Vector3(); -ComponentFollow_TargetToParent_Vec3 = new THREE.Vector3(); -ComponentFollow_rotatedTargetOffset_Vec3 = new THREE.Vector3(); -ComponentFollow_tempQuaternion = new THREE.Quaternion(); +if(typeof THREE != "undefined") { + ComponentFollow_Target_Vec3 = new THREE.Vector3(); + ComponentFollow_TargetToParent_Vec3 = new THREE.Vector3(); + ComponentFollow_rotatedTargetOffset_Vec3 = new THREE.Vector3(); + ComponentFollow_tempQuaternion = new THREE.Quaternion(); +} ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentFollow.prototype.onUpdate = function( diff --git a/src/game-lib-component-look-at.js b/src/game-lib-component-look-at.js index a26793c..f64dc7e 100644 --- a/src/game-lib-component-look-at.js +++ b/src/game-lib-component-look-at.js @@ -22,16 +22,17 @@ GameLib.D3.ComponentLookAt = function( this.rotationSpeed = rotationSpeed || 22.0; }; - -ComponentLookAt_rotatedTargetOffset = new THREE.Vector3(); -ComponentLookAt_currentPos = new THREE.Vector3(); -ComponentLookAt_targetPos = new THREE.Vector3(); -ComponentLookAt_upVector = new THREE.Vector3(0, 1, 0); -ComponentLookAt_targetQuaternion = new THREE.Quaternion(0, 0, 0, 1); -ComponentLookAt_tmpQuaternion = new THREE.Quaternion(0, 0, 0, 1); -ComponentLookAt_newRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); -ComponentLookAt_lastRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); -ComponentLookAt_lookAtMatrix = new THREE.Matrix4(); +if(typeof THREE != "undefined") { + ComponentLookAt_rotatedTargetOffset = new THREE.Vector3(); + ComponentLookAt_currentPos = new THREE.Vector3(); + ComponentLookAt_targetPos = new THREE.Vector3(); + ComponentLookAt_upVector = new THREE.Vector3(0, 1, 0); + ComponentLookAt_targetQuaternion = new THREE.Quaternion(0, 0, 0, 1); + ComponentLookAt_tmpQuaternion = new THREE.Quaternion(0, 0, 0, 1); + ComponentLookAt_newRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); + ComponentLookAt_lastRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1); + ComponentLookAt_lookAtMatrix = new THREE.Matrix4(); +} ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentLookAt.prototype.onUpdate = function( diff --git a/src/game-lib-component-mesh-permutation.js b/src/game-lib-component-mesh-permutation.js index e0ded90..c614578 100644 --- a/src/game-lib-component-mesh-permutation.js +++ b/src/game-lib-component-mesh-permutation.js @@ -15,14 +15,15 @@ GameLib.D3.ComponentMeshPermutation = function( GameLib.D3.Utils.Extend(GameLib.D3.ComponentMeshPermutation, GameLib.D3.ComponentInterface); }; -ComponentMeshPermutation_quaternion = new THREE.Quaternion(); -ComponentMeshPermutation_quaternionCopy = new THREE.Quaternion(); -ComponentMeshPermutation_position = new THREE.Vector3(); -ComponentMeshPermutation_scale = new THREE.Vector3(); - -ComponentMeshPermutation_offsetQuaternion = new THREE.Quaternion(); -ComponentMeshPermutation_offsetPosition = new THREE.Vector3(); -ComponentMeshPermutation_offsetScale = new THREE.Vector3(); +if(typeof THREE != "undefined") { + ComponentMeshPermutation_quaternion = new THREE.Quaternion(); + ComponentMeshPermutation_quaternionCopy = new THREE.Quaternion(); + ComponentMeshPermutation_position = new THREE.Vector3(); + ComponentMeshPermutation_scale = new THREE.Vector3(); + ComponentMeshPermutation_offsetQuaternion = new THREE.Quaternion(); + ComponentMeshPermutation_offsetPosition = new THREE.Vector3(); + ComponentMeshPermutation_offsetScale = new THREE.Vector3(); +} ///////////////////////// Methods to override ////////////////////////// GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( From a3f552b941c9e6bf99b1323aec1aaf826ac4d4f7 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Wed, 9 Nov 2016 14:17:13 +0100 Subject: [PATCH 11/14] trigger sphere --- ...ame-lib-component-trigger-sphere-sphere.js | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/game-lib-component-trigger-sphere-sphere.js diff --git a/src/game-lib-component-trigger-sphere-sphere.js b/src/game-lib-component-trigger-sphere-sphere.js new file mode 100644 index 0000000..f6419db --- /dev/null +++ b/src/game-lib-component-trigger-sphere-sphere.js @@ -0,0 +1,71 @@ +// +// uses the entity position + mesh bounding sphere to check if intersections +// +GameLib.D3.ComponentTriggerSphereSphere = function( + componentId, + sphereRadius, + entitiesToCheck, + callback +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentTriggerSphereSphere, GameLib.D3.ComponentInterface); + + this.entitiesToCheck = entitiesToCheck || []; + this.sphereRadius = sphereRadius || 1.0; + this.callback = callback || null; +}; + +if(typeof THREE != "undefined") { + ComponentTriggerSphereSphere_spherePosition_Vector3 = new THREE.Vector3(); + ComponentTriggerSphereSphere_targetBoundingSpherePosition_Vector3 = new THREE.Vector3(); + ComponentTriggerSphereSphere_targetBoundingSphereRadius = 0.0; + ComponentTriggerSphereSphere_sphereToSphere_Vector3 = new THREE.Vector3(); +} + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentTriggerSphereSphere.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + + ComponentTriggerSphereSphere_spherePosition_Vector3.set( + parentEntity.position.x, + parentEntity.position.y, + parentEntity.position.z + ); + + for(var e in this.entitiesToCheck) { + var entityToCheck = this.entitiesToCheck[e]; + + ComponentTriggerSphereSphere_targetBoundingSpherePosition_Vector3.set( + entityToCheck.position.x, + entityToCheck.position.y, + entityToCheck.position.z + ); + + if(entityToCheck.mesh && entityToCheck.mesh.geometry.boundingSphere) { + ComponentTriggerSphereSphere_targetBoundingSphereRadius = entityToCheck.mesh.geometry.boundingSphere.radius; + } else { + ComponentTriggerSphereSphere_targetBoundingSphereRadius = 0.0; + } + + // do sphere sphere collision + + ComponentTriggerSphereSphere_sphereToSphere_Vector3.set( + ComponentTriggerSphereSphere_targetBoundingSpherePosition_Vector3.x - ComponentTriggerSphereSphere_spherePosition_Vector3.x, + ComponentTriggerSphereSphere_targetBoundingSpherePosition_Vector3.y - ComponentTriggerSphereSphere_spherePosition_Vector3.y, + ComponentTriggerSphereSphere_targetBoundingSpherePosition_Vector3.z - ComponentTriggerSphereSphere_spherePosition_Vector3.z + ); + + var length = ComponentTriggerSphereSphere_sphereToSphere_Vector3.length(); + + if((length - (ComponentTriggerSphereSphere_targetBoundingSphereRadius + this.sphereRadius)) < 0) { + if(this.callback) { + this.callback(parentEntity, entityToCheck); + } + } + } +}; \ No newline at end of file From 66c8e76983330f60d2e9c0e87db6d964dd6f6e50 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Wed, 9 Nov 2016 16:18:43 +0100 Subject: [PATCH 12/14] box-sphere trigger area component --- src/game-lib-component-trigger-box-sphere.js | 89 ++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/game-lib-component-trigger-box-sphere.js diff --git a/src/game-lib-component-trigger-box-sphere.js b/src/game-lib-component-trigger-box-sphere.js new file mode 100644 index 0000000..8ac3d7f --- /dev/null +++ b/src/game-lib-component-trigger-box-sphere.js @@ -0,0 +1,89 @@ +// +// this component operates on it's parent entity's bounding box. +// so, you can't use this component with a null-mesh. +// +GameLib.D3.ComponentTriggerBoxSphere = function( + componentId, + entitiesToCheck, + callback +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentTriggerBoxSphere, GameLib.D3.ComponentInterface); + + this.entitiesToCheck = entitiesToCheck || []; + this.callback = callback || null; +}; + +if(typeof THREE != "undefined") { + ComponentTriggerBoxSphere_BoxInverseTransform = new THREE.Matrix4(); + ComponentTriggerBoxSphere_TargetPosition_Vec3 = new THREE.Vector3(); + ComponentTriggerBoxSphere_TargetRadius = 0.0; +} + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentTriggerBoxSphere.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + + if(parentEntity.mesh) { + // Calculate the current transform here, using the position, orientation and scale of the entity. + + if(!parentEntity.mesh.geometry.boundingBox) { + parentEntity.mesh.geometry.computeBoundingBox(); + } + + ComponentTriggerBoxSphere_BoxInverseTransform.getInverse(parentEntity.mesh.matrix); + + for(var e in this.entitiesToCheck) { + var entityToCheck = this.entitiesToCheck[e]; + + if(entityToCheck.mesh) { + + if (!entityToCheck.mesh.geometry.boundingSphere) { + entityToCheck.mesh.geometry.computeBoundingSphere(); + } + + var spherePosition = new THREE.Vector3( + entityToCheck.position.x, + entityToCheck.position.y, + entityToCheck.position.z + ); + + spherePosition.applyMatrix4(ComponentTriggerBoxSphere_BoxInverseTransform); + + var sphere = new THREE.Sphere( + spherePosition, + entityToCheck.mesh.geometry.boundingSphere.radius + ); + + if(this.callback && parentEntity.mesh.geometry.boundingBox.intersectsSphere(sphere)) { + this.callback(parentEntity, entityToCheck); + } + + } else { // no target mesh geometry. + + var spherePosition = new THREE.Vector3( + entityToCheck.position.x, + entityToCheck.position.y, + entityToCheck.position.z + ); + + spherePosition.applyMatrix4(ComponentTriggerBoxSphere_BoxInverseTransform); + + var sphere = new THREE.Sphere( + spherePosition, + 1 + ); + + if(this.callback && parentEntity.mesh.geometry.boundingBox.intersectsSphere(sphere)) { + this.callback(parentEntity, entityToCheck); + } + + } + } + } +}; \ No newline at end of file From c159a4e1aac4569843367e8e5e67058411f80146 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Thu, 10 Nov 2016 11:09:55 +0100 Subject: [PATCH 13/14] - added a modified version of cannon.js - convex|trimesh collisions work - modified shape.js (added type_plane) --- src/game-lib-shape.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game-lib-shape.js b/src/game-lib-shape.js index 7494c3b..1734411 100644 --- a/src/game-lib-shape.js +++ b/src/game-lib-shape.js @@ -99,6 +99,7 @@ GameLib.D3.Shape.SHAPE_TYPE_TRIMESH = 3; GameLib.D3.Shape.SHAPE_TYPE_CYLINDER = 4; GameLib.D3.Shape.SHAPE_TYPE_HEIGHT_MAP = 5; GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL = 6; +GameLib.D3.Shape.SHAPE_TYPE_PLANE = 7; /** * @@ -144,6 +145,8 @@ GameLib.D3.Shape.prototype.createInstance = function() { this.vertices, this.indices ); + } else if(this.shapeType == GameLib.D3.Shape.SHAPE_TYPE_PLANE) { + instance = new this.engine.instance.Plane(); } else { console.warn('Shape type not implemented: ' + this.shapeType); throw new Error('Shape type not implemented: ' + this.shapeType); From e2973d8ec6f67dfbe672fe496c237e02ca8caac5 Mon Sep 17 00:00:00 2001 From: "Theunis J. Botha" Date: Thu, 10 Nov 2016 13:47:40 +0100 Subject: [PATCH 14/14] comments --- src/game-lib-component-camera.js | 6 ++++++ src/game-lib-component-follow.js | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/game-lib-component-camera.js b/src/game-lib-component-camera.js index a5d2bb3..24ab32d 100644 --- a/src/game-lib-component-camera.js +++ b/src/game-lib-component-camera.js @@ -1,3 +1,9 @@ +/** + * + * @param componentId + * @param threeCamera + * @constructor + */ GameLib.D3.ComponentCamera = function( componentId, threeCamera diff --git a/src/game-lib-component-follow.js b/src/game-lib-component-follow.js index 8acfd0d..38a40a6 100644 --- a/src/game-lib-component-follow.js +++ b/src/game-lib-component-follow.js @@ -1,3 +1,12 @@ +/** + * + * @param componentId + * @param targetEntity GameLib.D3.Entity + * @param targetOffset GameLib.D3.Vector3 + * @param minDistance + * @param moveSpeed + * @constructor + */ GameLib.D3.ComponentFollow = function( componentId, targetEntity,