From af41443981690566acfbf25b54e61ed068bd1e94 Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Fri, 9 Mar 2018 03:38:45 +0100 Subject: [PATCH] orbit controls, first person, mesh clones --- src/game-lib-a-component-a.js | 24 +- src/game-lib-api-controls-0.js | 80 +++-- src/game-lib-api-controls-d3-first-person.js | 136 ++++++++ src/game-lib-api-controls-d3-orbit.js | 147 ++++++++ src/game-lib-controls-0.js | 26 +- src/game-lib-controls-d3-editor.js | 2 +- src/game-lib-controls-d3-first-person.js | 220 ++++++++++++ src/game-lib-controls-d3-orbit.js | 235 +++++++++++++ src/game-lib-d3-api-face.js | 38 +-- src/game-lib-d3-api-mesh-0.js | 25 +- src/game-lib-d3-camera-perspective.js | 7 + src/game-lib-d3-face.js | 19 +- src/game-lib-d3-geometry-buffer-a.js | 235 +++++++------ src/game-lib-d3-geometry-normal-a.js | 3 + src/game-lib-d3-helper.js | 19 +- src/game-lib-d3-mesh-0.js | 112 +++++- src/game-lib-d3-pass-render.js | 10 + src/game-lib-d3-scene.js | 8 +- src/game-lib-render-configuration.js | 7 + src/game-lib-system-gui.js | 8 +- src/game-lib-system-input.js | 339 +++++++++++++------ src/game-lib-system-linking.js | 87 ++--- 22 files changed, 1426 insertions(+), 361 deletions(-) create mode 100644 src/game-lib-api-controls-d3-first-person.js create mode 100644 src/game-lib-api-controls-d3-orbit.js create mode 100644 src/game-lib-controls-d3-first-person.js create mode 100644 src/game-lib-controls-d3-orbit.js diff --git a/src/game-lib-a-component-a.js b/src/game-lib-a-component-a.js index d05e889..aedaafc 100644 --- a/src/game-lib-a-component-a.js +++ b/src/game-lib-a-component-a.js @@ -300,7 +300,7 @@ GameLib.Component.FONT = 0x3c; GameLib.Component.CANVAS = 0x3d; GameLib.Component.BONE = 0x3e; GameLib.Component.GRAPHICS_IMPACT = 0x3f; -//GameLib.Component.MESH_CYLINDER = 0x40; +GameLib.Component.CONTROLS_FIRST_PERSON = 0x40; GameLib.Component.SYSTEM_ANIMATION = 0x41; GameLib.Component.SYSTEM_CUSTOM_CODE = 0x42; GameLib.Component.SYSTEM_GUI = 0x43; @@ -317,7 +317,7 @@ GameLib.Component.LIGHT_POINT = 0x4d; GameLib.Component.LIGHT_RECT_AREA = 0x4e; GameLib.Component.LIGHT_SPOT = 0x4f; GameLib.Component.FOG = 0x50; -//GameLib.Component.MESH_LINE = 0x51; +GameLib.Component.CONTROLS_ORBIT = 0x51; GameLib.Component.PARTICLE_ENGINE = 0x52; GameLib.Component.SYSTEM_PARTICLE = 0x53; GameLib.Component.PARTICLE = 0x54; @@ -806,12 +806,12 @@ GameLib.Component.GetComponentInfo = function(number) { constructor : GameLib.GraphicsRuntime.Impact, apiConstructor : GameLib.API.GraphicsRuntime.Impact }; - case 0x40 : return null;/*{ - name : 'GameLib.D3.Mesh.Cylinder', + case 0x40 : return { + name : 'GameLib.Controls.D3.FirstPerson', runtime : GameLib.Component.GRAPHICS_RUNTIME, - constructor : GameLib.D3.Mesh.Cylinder, - apiConstructor : GameLib.D3.API.Mesh - };*/ + constructor : GameLib.Controls.D3.FirstPerson, + apiConstructor : GameLib.API.Controls.D3.FirstPerson + }; case 0x41 : return { name : 'GameLib.System.Animation', runtime : GameLib.Component.DEFAULT_RUNTIME, @@ -908,12 +908,12 @@ GameLib.Component.GetComponentInfo = function(number) { constructor : GameLib.D3.Fog, apiConstructor : GameLib.D3.API.Fog }; - case 0x51 : return null;/*{ - name : 'GameLib.D3.Mesh.Line', + case 0x51 : return { + name : 'GameLib.Controls.D3.Orbit', runtime : GameLib.Component.GRAPHICS_RUNTIME, - constructor : GameLib.D3.Mesh.Line, - apiConstructor : GameLib.D3.API.Mesh - };*/ + constructor : GameLib.Controls.D3.Orbit, + apiConstructor : GameLib.API.Controls.D3.Orbit + }; case 0x52 : return { name : 'GameLib.D3.ParticleEngine', runtime : GameLib.Component.GRAPHICS_RUNTIME, diff --git a/src/game-lib-api-controls-0.js b/src/game-lib-api-controls-0.js index f034e53..522a35d 100644 --- a/src/game-lib-api-controls-0.js +++ b/src/game-lib-api-controls-0.js @@ -27,20 +27,27 @@ GameLib.API.Controls = function( if (GameLib.Utils.UndefinedOrNull(name)) { - if (this.controlsType === GameLib.API.Controls.CONTROLS_TYPE_EDITOR) { - name = 'Editing Controls'; - } + name = 'Controls'; - if (this.controlsType === GameLib.API.Controls.CONTROLS_TYPE_TOUCH) { - name = 'Touch Controls'; - } - - if (this.controlsType === GameLib.API.Controls.CONTROLS_TYPE_KEYBOARD) { - name = 'Keyboard Controls'; - } - - if (this.controlsType === GameLib.API.Controls.CONTROLS_TYPE_MOUSE) { - name = 'Mouse Controls'; + switch (this.controlsType) { + case GameLib.API.Controls.CONTROLS_TYPE_TOUCH : + name = 'Controls Editor'; + break; + case GameLib.API.Controls.CONTROLS_TYPE_KEYBOARD : + name = 'Controls Keyboard'; + break; + case GameLib.API.Controls.CONTROLS_TYPE_MOUSE : + name = 'Controls Mouse'; + break; + case GameLib.API.Controls.CONTROLS_TYPE_EDITOR : + name = 'Controls Editor'; + break; + case GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON : + name = 'Controls First Person'; + break; + case GameLib.API.Controls.CONTROLS_TYPE_ORBIT : + name = 'Controls Orbit'; + break; } name += ' (' + this.id + ')'; @@ -52,11 +59,23 @@ GameLib.API.Controls = function( } this.canvas = canvas; + GameLib.API.Component.call( + this, + GameLib.API.Controls.GetComponentType(this.controlsType), + parentEntity + ); +}; + +GameLib.API.Controls.prototype = Object.create(GameLib.API.Component.prototype); +GameLib.API.Controls.prototype.constructor = GameLib.API.Controls; + +GameLib.API.Controls.GetComponentType = function(controlsType) { + var componentType = null; - switch (this.controlsType) { - case GameLib.API.Controls.CONTROLS_TYPE_EDITOR : - componentType = GameLib.Component.CONTROLS_EDITOR; + switch (controlsType) { + case GameLib.API.Controls.CONTROLS_TYPE_NONE : + componentType = GameLib.Component.CONTROLS; break; case GameLib.API.Controls.CONTROLS_TYPE_TOUCH : componentType = GameLib.Component.CONTROLS_TOUCH; @@ -67,29 +86,30 @@ GameLib.API.Controls = function( case GameLib.API.Controls.CONTROLS_TYPE_MOUSE : componentType = GameLib.Component.CONTROLS_MOUSE; break; + case GameLib.API.Controls.CONTROLS_TYPE_EDITOR : + componentType = GameLib.Component.CONTROLS_EDITOR; + break; + case GameLib.API.Controls.CONTROLS_TYPE_ORBIT : + componentType = GameLib.Component.CONTROLS_ORBIT; + break; default : - throw new Error('unhandled controls type: ' + this.controlsType); + throw new Error('unhandled controls type: ' + controlsType); break; } - GameLib.API.Component.call( - this, - componentType, - parentEntity - ); + return componentType; }; -GameLib.API.Controls.prototype = Object.create(GameLib.API.Component.prototype); -GameLib.API.Controls.prototype.constructor = GameLib.API.Controls; - GameLib.API.Controls.D3 = function() {}; /** * Controls Type * @type {number} */ -GameLib.API.Controls.CONTROLS_TYPE_NONE = 0xf; -GameLib.API.Controls.CONTROLS_TYPE_EDITOR = 0x0; -GameLib.API.Controls.CONTROLS_TYPE_TOUCH = 0x1; -GameLib.API.Controls.CONTROLS_TYPE_KEYBOARD = 0x2; -GameLib.API.Controls.CONTROLS_TYPE_MOUSE = 0x3; +GameLib.API.Controls.CONTROLS_TYPE_NONE = 0x0; +GameLib.API.Controls.CONTROLS_TYPE_TOUCH = 0x1; +GameLib.API.Controls.CONTROLS_TYPE_KEYBOARD = 0x2; +GameLib.API.Controls.CONTROLS_TYPE_MOUSE = 0x3; +GameLib.API.Controls.CONTROLS_TYPE_EDITOR = 0x4; +GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON = 0x5; +GameLib.API.Controls.CONTROLS_TYPE_ORBIT = 0x6; diff --git a/src/game-lib-api-controls-d3-first-person.js b/src/game-lib-api-controls-d3-first-person.js new file mode 100644 index 0000000..6771d17 --- /dev/null +++ b/src/game-lib-api-controls-d3-first-person.js @@ -0,0 +1,136 @@ +/** + * GameLib.API.Controls.D3.FirstPerson + * @param apiControls + * @param camera + * @param enabled + * @param movementSpeed + * @param lookSpeed + * @param lookVertical + * @param autoForward + * @param activeLook + * @param heightSpeed + * @param heightCoef + * @param heightMin + * @param heightMax + * @param constrainVertical + * @param verticalMin + * @param verticalMax + * @param autoSpeedFactor + * @constructor + */ +GameLib.API.Controls.D3.FirstPerson = function( + apiControls, + camera, + enabled, + movementSpeed, + lookSpeed, + lookVertical, + autoForward, + activeLook, + heightSpeed, + heightCoef, + heightMin, + heightMax, + constrainVertical, + verticalMin, + verticalMax, + autoSpeedFactor +) { + + if (GameLib.Utils.UndefinedOrNull(apiControls)) { + apiControls = { + controlsType : GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON + }; + } + + if (GameLib.Utils.UndefinedOrNull(apiControls.controlsType)) { + apiControls.controlsType = GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON; + } + + if (GameLib.Utils.UndefinedOrNull(camera)) { + camera = null; + } + this.camera = camera; + + if (GameLib.Utils.UndefinedOrNull(enabled)) { + enabled = true; + } + this.enabled = enabled; + + if (GameLib.Utils.UndefinedOrNull(movementSpeed)) { + movementSpeed = 1.0; + } + this.movementSpeed = movementSpeed; + + if (GameLib.Utils.UndefinedOrNull(lookSpeed)) { + lookSpeed = 0.005; + } + this.lookSpeed = lookSpeed; + + if (GameLib.Utils.UndefinedOrNull(lookVertical)) { + lookVertical = true; + } + this.lookVertical = lookVertical; + + if (GameLib.Utils.UndefinedOrNull(autoForward)) { + autoForward = false; + } + this.autoForward = autoForward; + + if (GameLib.Utils.UndefinedOrNull(activeLook)) { + activeLook = false; + } + this.activeLook = activeLook; + + if (GameLib.Utils.UndefinedOrNull(heightSpeed)) { + heightSpeed = false; + } + this.heightSpeed = heightSpeed; + + if (GameLib.Utils.UndefinedOrNull(heightCoef)) { + heightCoef = 1.0; + } + this.heightCoef = heightCoef; + + if (GameLib.Utils.UndefinedOrNull(heightMin)) { + heightMin = 0.0; + } + this.heightMin = heightMin; + + if (GameLib.Utils.UndefinedOrNull(heightMax)) { + heightMax = 1.0; + } + this.heightMax = heightMax; + + if (GameLib.Utils.UndefinedOrNull(constrainVertical)) { + constrainVertical = false; + } + this.constrainVertical = constrainVertical; + + if (GameLib.Utils.UndefinedOrNull(verticalMin)) { + verticalMin = 0; + } + this.verticalMin = verticalMin; + + if (GameLib.Utils.UndefinedOrNull(verticalMax)) { + verticalMax = Math.PI; + } + this.verticalMax = verticalMax; + + if (GameLib.Utils.UndefinedOrNull(autoSpeedFactor)) { + autoSpeedFactor = 0; + } + this.autoSpeedFactor = autoSpeedFactor; + + GameLib.API.Controls.call( + this, + apiControls.id, + apiControls.name, + apiControls.controlsType, + apiControls.canvas, + apiControls.parentEntity + ); +}; + +GameLib.API.Controls.D3.FirstPerson.prototype = Object.create(GameLib.API.Controls.prototype); +GameLib.API.Controls.D3.FirstPerson.prototype.constructor = GameLib.API.Controls.D3.FirstPerson; diff --git a/src/game-lib-api-controls-d3-orbit.js b/src/game-lib-api-controls-d3-orbit.js new file mode 100644 index 0000000..d9da8a8 --- /dev/null +++ b/src/game-lib-api-controls-d3-orbit.js @@ -0,0 +1,147 @@ +/** + * GameLib.API.Controls.D3.Orbit + * @param apiControls + * @param camera + * @param target + * @param enabled + * @param minDistance + * @param maxDistance + * @param minZoom + * @param maxZoom + * @param minPolarAngle + * @param maxPolarAngle + * @param enableDamping + * @param dampingFactor + * @param enableZoom + * @param zoomSpeed + * @param enableRotate + * @param rotateSpeed + * @param enablePan + * @param keyPanSpeed + * @param autoRotate + * @param autoRotateSpeed + * @param enableKeys + * @constructor + */ +GameLib.API.Controls.D3.Orbit = function( + apiControls, + camera, + target, + enabled, + minPolarAngle, + maxPolarAngle, + enableDamping, + dampingFactor, + enableZoom, + zoomSpeed, + enableRotate, + rotateSpeed, + enablePan, + keyPanSpeed, + autoRotate, + autoRotateSpeed, + enableKeys +) { + + if (GameLib.Utils.UndefinedOrNull(apiControls)) { + apiControls = { + controlsType : GameLib.API.Controls.CONTROLS_TYPE_ORBIT + }; + } + + if (GameLib.Utils.UndefinedOrNull(apiControls.controlsType)) { + apiControls.controlsType = GameLib.API.Controls.CONTROLS_TYPE_ORBIT; + } + + if (GameLib.Utils.UndefinedOrNull(camera)) { + camera = null; + } + this.camera = camera; + + if (GameLib.Utils.UndefinedOrNull(target)) { + target = null; + } + this.target = target; + + if (GameLib.Utils.UndefinedOrNull(enabled)) { + enabled = true; + } + this.enabled = enabled; + + if (GameLib.Utils.UndefinedOrNull(minPolarAngle)) { + minPolarAngle = 0; + } + this.minPolarAngle = minPolarAngle; + + if (GameLib.Utils.UndefinedOrNull(maxPolarAngle)) { + maxPolarAngle = Math.PI; + } + this.maxPolarAngle = maxPolarAngle; + + if (GameLib.Utils.UndefinedOrNull(enableDamping)) { + enableDamping = false; + } + this.enableDamping = enableDamping; + + if (GameLib.Utils.UndefinedOrNull(dampingFactor)) { + dampingFactor = 0.25; + } + this.dampingFactor = dampingFactor; + + if (GameLib.Utils.UndefinedOrNull(enableZoom)) { + enableZoom = true; + } + this.enableZoom = enableZoom; + + if (GameLib.Utils.UndefinedOrNull(zoomSpeed)) { + zoomSpeed = 1.0; + } + this.zoomSpeed = zoomSpeed; + + if (GameLib.Utils.UndefinedOrNull(enableRotate)) { + enableRotate = true; + } + this.enableRotate = enableRotate; + + if (GameLib.Utils.UndefinedOrNull(rotateSpeed)) { + rotateSpeed = 1.0; + } + this.rotateSpeed = rotateSpeed; + + if (GameLib.Utils.UndefinedOrNull(enablePan)) { + enablePan = true; + } + this.enablePan = enablePan; + + if (GameLib.Utils.UndefinedOrNull(keyPanSpeed)) { + keyPanSpeed = 7.0; + } + this.keyPanSpeed = keyPanSpeed; + + if (GameLib.Utils.UndefinedOrNull(autoRotate)) { + autoRotate = false; + } + this.autoRotate = autoRotate; + + if (GameLib.Utils.UndefinedOrNull(autoRotateSpeed)) { + autoRotateSpeed = 2.0; + } + this.autoRotateSpeed = autoRotateSpeed; + + if (GameLib.Utils.UndefinedOrNull(enableKeys)) { + enableKeys = false; + } + this.enableKeys = enableKeys; + + GameLib.API.Controls.call( + this, + apiControls.id, + apiControls.name, + apiControls.controlsType, + apiControls.canvas, + apiControls.parentEntity + ); +}; + +GameLib.API.Controls.D3.Orbit.prototype = Object.create(GameLib.API.Controls.prototype); +GameLib.API.Controls.D3.Orbit.prototype.constructor = GameLib.API.Controls.D3.Orbit; diff --git a/src/game-lib-controls-0.js b/src/game-lib-controls-0.js index 6481a38..036ee0e 100644 --- a/src/game-lib-controls-0.js +++ b/src/game-lib-controls-0.js @@ -1,6 +1,7 @@ /** - * Controls Superset - The apiControls properties get moved into the Controls object itself, and then the instance is created - * @param apiControls GameLib.API.Controls + * GameLib.Controls + * @param apiControls + * @property controlsType * @constructor */ GameLib.Controls = function ( @@ -26,12 +27,19 @@ GameLib.Controls = function ( var delayed = false; - if (apiControls.controlsType === GameLib.API.Controls.CONTROLS_TYPE_EDITOR) { - - linkedObjects.raycaster = GameLib.D3.Raycaster; - linkedObjects.camera = GameLib.D3.Camera; - - delayed = true; + switch (this.controlsType) { + case (GameLib.API.Controls.CONTROLS_TYPE_EDITOR) : + linkedObjects.raycaster = GameLib.D3.Raycaster; + linkedObjects.camera = GameLib.D3.Camera; + delayed = true; + break; + case (GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON) : + linkedObjects.camera = GameLib.D3.Camera; + break; + case (GameLib.API.Controls.CONTROLS_TYPE_ORBIT) : + linkedObjects.camera = GameLib.D3.Camera; + linkedObjects.target = GameLib.Component; + break; } GameLib.Component.call( @@ -45,6 +53,8 @@ GameLib.Controls.prototype = Object.create(GameLib.Component.prototype); GameLib.Controls.prototype.constructor = GameLib.Controls; GameLib.Controls.D3 = function() {}; +GameLib.Controls.D3.prototype = Object.create(GameLib.Controls.prototype); +GameLib.Controls.D3.prototype.constructor = GameLib.Controls.D3; /** * Creates a mesh instance or updates it diff --git a/src/game-lib-controls-d3-editor.js b/src/game-lib-controls-d3-editor.js index 5cec59f..d1ac676 100644 --- a/src/game-lib-controls-d3-editor.js +++ b/src/game-lib-controls-d3-editor.js @@ -47,7 +47,7 @@ GameLib.Controls.D3.Editor = function ( * Inheritance * @type {GameLib.Controls} */ -GameLib.Controls.D3.Editor.prototype = Object.create(GameLib.Controls.prototype); +GameLib.Controls.D3.Editor.prototype = Object.create(GameLib.Controls.D3.prototype); GameLib.Controls.D3.Editor.prototype.constructor = GameLib.Controls.D3.Editor; /** diff --git a/src/game-lib-controls-d3-first-person.js b/src/game-lib-controls-d3-first-person.js new file mode 100644 index 0000000..364d74a --- /dev/null +++ b/src/game-lib-controls-d3-first-person.js @@ -0,0 +1,220 @@ +/** + * Controls Superset - The apiControls properties get moved into the Controls object itself, and then the instance is created + * @param graphics GameLib.GraphicsRuntime + * @param apiFirstPersonControls + * @constructor + */ +GameLib.Controls.D3.FirstPerson = function ( + graphics, + apiFirstPersonControls +) { + + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (GameLib.Utils.UndefinedOrNull(apiFirstPersonControls)) { + apiFirstPersonControls = { + controlsType : GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON + }; + } + + if (GameLib.Utils.UndefinedOrNull()) { + apiFirstPersonControls.controlsType = GameLib.API.Controls.CONTROLS_TYPE_FIRST_PERSON; + } + + GameLib.API.Controls.D3.FirstPerson.call( + this, + apiFirstPersonControls, + apiFirstPersonControls.camera, + apiFirstPersonControls.enabled, + apiFirstPersonControls.movementSpeed, + apiFirstPersonControls.lookSpeed, + apiFirstPersonControls.lookVertical, + apiFirstPersonControls.autoForward, + apiFirstPersonControls.activeLook, + apiFirstPersonControls.heightSpeed, + apiFirstPersonControls.heightCoef, + apiFirstPersonControls.heightMin, + apiFirstPersonControls.heightMax, + apiFirstPersonControls.constrainVertical, + apiFirstPersonControls.verticalMin, + apiFirstPersonControls.verticalMax, + apiFirstPersonControls.autoSpeedFactor + ); + + GameLib.Controls.call( + this, + apiFirstPersonControls + ); + +}; + +/** + * Inheritance + * @type {GameLib.Controls} + */ +GameLib.Controls.D3.FirstPerson.prototype = Object.create(GameLib.Controls.D3.prototype); +GameLib.Controls.D3.FirstPerson.prototype.constructor = GameLib.Controls.D3.FirstPerson; + +/** + * Create Instance + */ +GameLib.Controls.D3.FirstPerson.prototype.createInstance = function() { + + if ( + GameLib.Utils.UndefinedOrNull(this.camera) || + GameLib.Utils.UndefinedOrNull(this.camera.instance) + ) { + console.warn('no camera at time of editor-controls create instance'); + return; + } + + if ( + GameLib.Utils.UndefinedOrNull(this.canvas) || + GameLib.Utils.UndefinedOrNull(this.canvas.instance) + ) { + console.warn('no canvas at time of editor-controls create instance'); + return; + } + + this.instance = new THREE.FirstPersonControls( + this.camera.instance, + this.canvas.instance + ); + + this.instance.enabled = this.enabled; + this.instance.movementSpeed = this.movementSpeed; + this.instance.lookSpeed = this.lookSpeed; + this.instance.lookVertical = this.lookVertical; + this.instance.autoForward = this.autoForward; + this.instance.activeLook = this.activeLook; + this.instance.heightSpeed = this.heightSpeed; + this.instance.heightCoef = this.heightCoef; + this.instance.heightMin = this.heightMin; + this.instance.heightMax = this.heightMax; + this.instance.constrainVertical = this.constrainVertical; + this.instance.verticalMin = this.verticalMin; + this.instance.verticalMax = this.verticalMax; + this.instance.autoSpeedFactor = this.autoSpeedFactor; + + GameLib.Controls.prototype.createInstance.call(this); +}; + +/** + * Update Instance + */ +GameLib.Controls.D3.FirstPerson.prototype.updateInstance = function(property) { + + if ( + property === 'canvas' || + property === 'camera' + ) { + if (GameLib.Utils.UndefinedOrNull(this.instance)) { + this.createInstance(); + } else { + this.instance.dispose(); + this.createInstance(); + } + } + + if (property === 'enabled') { + this.instance.enabled = this.enabled; + return; + } + + if (property === 'movementSpeed') { + this.instance.movementSpeed = this.movementSpeed; + return; + } + + if (property === 'lookSpeed') { + this.instance.lookSpeed = this.lookSpeed; + return; + } + + if (property === 'lookVertical') { + this.instance.lookVertical = this.lookVertical; + return; + } + + if (property === 'autoForward') { + this.instance.autoForward = this.autoForward; + return; + } + + if (property === 'activeLook') { + this.instance.activeLook = this.activeLook; + return; + } + + if (property === 'heightSpeed') { + this.instance.heightSpeed = this.heightSpeed; + return; + } + + if (property === 'heightCoef') { + this.instance.heightCoef = this.heightCoef; + return; + } + + if (property === 'heightMin') { + this.instance.heightMin = this.heightMin; + return; + } + + if (property === 'heightMax') { + this.instance.heightMax = this.heightMax; + return; + } + + if (property === 'constrainVertical') { + this.instance.constrainVertical = this.constrainVertical; + return; + } + + if (property === 'verticalMin') { + this.instance.verticalMin = this.verticalMin; + return; + } + + if (property === 'verticalMax') { + this.instance.verticalMax = this.verticalMax; + return; + } + + if (property === 'autoSpeedFactor') { + this.instance.autoSpeedFactor = this.autoSpeedFactor; + return; + } + + + GameLib.Controls.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a GameLib.Controls.D3.FirstPerson to a GameLib.D3.API.Mesh + * @returns {GameLib.API.Controls} + */ +GameLib.Controls.D3.FirstPerson.prototype.toApiObject = function() { + + var apiControls = GameLib.Controls.prototype.toApiObject.call(this); + + return new GameLib.API.Controls.D3.FirstPerson( + apiControls, + GameLib.Utils.IdOrNull(this.camera), + this.enabled, + this.movementSpeed, + this.lookSpeed, + this.lookVertical, + this.autoForward, + this.activeLook, + this.heightSpeed, + this.heightCoef, + this.heightMin, + this.heightMax, + this.constrainVertical, + this.verticalMin, + this.verticalMax, + this.autoSpeedFactor + ); +}; diff --git a/src/game-lib-controls-d3-orbit.js b/src/game-lib-controls-d3-orbit.js new file mode 100644 index 0000000..b194726 --- /dev/null +++ b/src/game-lib-controls-d3-orbit.js @@ -0,0 +1,235 @@ +/** + * Controls Superset - The apiControls properties get moved into the Controls object itself, and then the instance is created + * @param graphics GameLib.GraphicsRuntime + * @param apiOrbitControls + * @constructor + */ +GameLib.Controls.D3.Orbit = function ( + graphics, + apiOrbitControls +) { + + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (GameLib.Utils.UndefinedOrNull(apiOrbitControls)) { + apiOrbitControls = { + controlsType : GameLib.API.Controls.CONTROLS_TYPE_ORBIT + }; + } + + if (GameLib.Utils.UndefinedOrNull()) { + apiOrbitControls.controlsType = GameLib.API.Controls.CONTROLS_TYPE_ORBIT; + } + + GameLib.API.Controls.D3.Orbit.call( + this, + apiOrbitControls, + apiOrbitControls.camera, + apiOrbitControls.target, + apiOrbitControls.enabled, + apiOrbitControls.minPolarAngle, + apiOrbitControls.maxPolarAngle, + apiOrbitControls.enableDamping, + apiOrbitControls.dampingFactor, + apiOrbitControls.enableZoom, + apiOrbitControls.zoomSpeed, + apiOrbitControls.enableRotate, + apiOrbitControls.rotateSpeed, + apiOrbitControls.enablePan, + apiOrbitControls.keyPanSpeed, + apiOrbitControls.autoRotate, + apiOrbitControls.autoRotateSpeed, + apiOrbitControls.enableKeys + ); + + GameLib.Controls.call( + this, + apiOrbitControls + ); + +}; + +/** + * Inheritance + * @type {GameLib.Controls} + */ +GameLib.Controls.D3.Orbit.prototype = Object.create(GameLib.Controls.D3.prototype); +GameLib.Controls.D3.Orbit.prototype.constructor = GameLib.Controls.D3.Orbit; + +/** + * Create Instance + */ +GameLib.Controls.D3.Orbit.prototype.createInstance = function() { + + if ( + GameLib.Utils.UndefinedOrNull(this.camera) || + GameLib.Utils.UndefinedOrNull(this.camera.instance) + ) { + console.warn('no camera at time of editor-controls create instance'); + return; + } + + if ( + GameLib.Utils.UndefinedOrNull(this.canvas) || + GameLib.Utils.UndefinedOrNull(this.canvas.instance) + ) { + console.warn('no canvas at time of editor-controls create instance'); + return; + } + + this.instance = new THREE.OrbitControls( + this.camera.instance, + this.canvas.instance + ); + + if (this.target && this.target.instance) { + this.instance.target = this.target.instance.position; + } + + this.instance.enabled = this.enabled; + this.instance.minPolarAngle = this.minPolarAngle; + this.instance.maxPolarAngle = this.maxPolarAngle; + this.instance.enableDamping = this.enableDamping; + this.instance.dampingFactor = this.dampingFactor; + this.instance.enableZoom = this.enableZoom; + this.instance.zoomSpeed = this.zoomSpeed; + this.instance.enableRotate = this.enableRotate; + this.instance.rotateSpeed = this.rotateSpeed; + this.instance.enablePan = this.enablePan; + this.instance.keyPanSpeed = this.keyPanSpeed; + this.instance.autoRotate = this.autoRotate; + this.instance.autoRotateSpeed = this.autoRotateSpeed; + this.instance.enableKeys = this.enableKeys; + + GameLib.Controls.prototype.createInstance.call(this); +}; + +/** + * Update Instance + */ +GameLib.Controls.D3.Orbit.prototype.updateInstance = function(property) { + + if ( + property === 'canvas' || + property === 'camera' + ) { + if (GameLib.Utils.UndefinedOrNull(this.instance)) { + this.createInstance(); + } else { + this.instance.dispose(); + this.createInstance(); + } + } + + if (property === 'target') { + + if (this.target && this.target.instance) { + this.instance.target = this.target.instance.position; + } else { + this.instance.target = new THREE.Vector3(); + } + return; + } + + if (property === 'enabled') { + this.instance.enabled = this.enabled; + return; + } + + if (property === 'minPolarAngle') { + this.instance.minPolarAngle = this.minPolarAngle; + return; + } + + if (property === 'maxPolarAngle') { + this.instance.maxPolarAngle = this.maxPolarAngle; + return; + } + + if (property === 'enableDamping') { + this.instance.enableDamping = this.enableDamping; + return; + } + + if (property === 'dampingFactor') { + this.instance.dampingFactor = this.dampingFactor; + return; + } + + if (property === 'enableZoom') { + this.instance.enableZoom = this.enableZoom; + return; + } + + if (property === 'zoomSpeed') { + this.instance.zoomSpeed = this.zoomSpeed; + return; + } + + if (property === 'enableRotate') { + this.instance.enableRotate = this.enableRotate; + return; + } + + if (property === 'rotateSpeed') { + this.instance.rotateSpeed = this.rotateSpeed; + return; + } + + if (property === 'enablePan') { + this.instance.enablePan = this.enablePan; + return; + } + + if (property === 'keyPanSpeed') { + this.instance.keyPanSpeed = this.keyPanSpeed; + return; + } + + if (property === 'autoRotate') { + this.instance.autoRotate = this.autoRotate; + return; + } + + if (property === 'autoRotateSpeed') { + this.instance.autoRotateSpeed = this.autoRotateSpeed; + return; + } + + if (property === 'enableKeys') { + this.instance.enableKeys = this.enableKeys; + return; + } + + GameLib.Controls.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a GameLib.Controls.D3.Orbit to a GameLib.D3.API.Mesh + * @returns {GameLib.API.Controls} + */ +GameLib.Controls.D3.Orbit.prototype.toApiObject = function() { + + var apiControls = GameLib.Controls.prototype.toApiObject.call(this); + + return new GameLib.API.Controls.D3.Orbit( + apiControls, + GameLib.Utils.IdOrNull(this.camera), + GameLib.Utils.IdOrNull(this.target), + this.enabled, + this.minPolarAngle, + this.maxPolarAngle, + this.enableDamping, + this.dampingFactor, + this.enableZoom, + this.zoomSpeed, + this.enableRotate, + this.rotateSpeed, + this.enablePan, + this.keyPanSpeed, + this.autoRotate, + this.autoRotateSpeed, + this.enableKeys + ); +}; diff --git a/src/game-lib-d3-api-face.js b/src/game-lib-d3-api-face.js index 66fa843..681a2a3 100644 --- a/src/game-lib-d3-api-face.js +++ b/src/game-lib-d3-api-face.js @@ -177,25 +177,25 @@ GameLib.D3.API.Face.prototype.constructor = GameLib.D3.API.Face; // ); // }; // -// /** -// * Clone a Face -// * @returns {GameLib.D3.API.Face} -// */ -// GameLib.D3.API.Face.prototype.clone = function(){ -// return new GameLib.D3.API.Face( -// this.id, -// this.name, -// this.v0index, -// this.v1index, -// this.v2index, -// this.materialIndex, -// this.uvs, -// this.color, -// this.vertexColors, -// this.vertexNormals, -// this.normal -// ); -// }; +/** + * Clone a Face + * @returns {GameLib.D3.API.Face} + */ +GameLib.D3.API.Face.prototype.clone = function(){ + return new GameLib.D3.API.Face( + this.id, + this.name, + this.v0index, + this.v1index, + this.v2index, + this.materialIndex, + this.uvs, + this.color, + this.vertexColors, + this.vertexNormals, + this.normal + ); +}; /** * Returns true if two triangles are equal (their vertex indices match in some order) diff --git a/src/game-lib-d3-api-mesh-0.js b/src/game-lib-d3-api-mesh-0.js index cbcbdaf..72fae06 100644 --- a/src/game-lib-d3-api-mesh-0.js +++ b/src/game-lib-d3-api-mesh-0.js @@ -14,6 +14,7 @@ * @param drawMode * @param morphTargetInfluences * @param morphTargetDictionary + * @param cloneDirection * @constructor */ GameLib.D3.API.Mesh = function( @@ -30,7 +31,8 @@ GameLib.D3.API.Mesh = function( receiveShadow, drawMode, morphTargetInfluences, - morphTargetDictionary + morphTargetDictionary, + cloneDirection ) { if (GameLib.Utils.UndefinedOrNull(apiD3Object)) { apiD3Object = { @@ -48,14 +50,14 @@ GameLib.D3.API.Mesh = function( /** * Backwards compatibility */ - // if (apiD3Object.faces && apiD3Object.vertices) { - // geometry = new GameLib.D3.API.Geometry.Normal( - // { - // faces : apiD3Object.faces, - // vertices : apiD3Object.vertices - // } - // ); - // } + if (apiD3Object.faces && apiD3Object.vertices) { + geometry = new GameLib.D3.API.Geometry.Normal( + { + faces : apiD3Object.faces, + vertices : apiD3Object.vertices + } + ); + } } this.geometry = geometry; @@ -122,6 +124,11 @@ GameLib.D3.API.Mesh = function( } this.morphTargetDictionary = morphTargetDictionary; + if (GameLib.Utils.UndefinedOrNull(cloneDirection)) { + cloneDirection = new GameLib.API.Vector3(-1,0,0); + } + this.cloneDirection = cloneDirection; + GameLib.D3.API.Object.call( this, apiD3Object.id, diff --git a/src/game-lib-d3-camera-perspective.js b/src/game-lib-d3-camera-perspective.js index 5115f98..5b92b92 100644 --- a/src/game-lib-d3-camera-perspective.js +++ b/src/game-lib-d3-camera-perspective.js @@ -69,36 +69,43 @@ GameLib.D3.Camera.Perspective.prototype.updateInstance = function(property) { if (property === 'near') { this.instance.near = this.near; + this.instance.updateProjectionMatrix(); return; } if (property === 'far') { this.instance.far = this.far; + this.instance.updateProjectionMatrix(); return; } if (property === 'fov') { this.instance.fov = this.fov; + this.instance.updateProjectionMatrix(); return; } if (property === 'filmGauge') { this.instance.filmGauge = this.filmGauge; + this.instance.updateProjectionMatrix(); return; } if (property === 'filmOffset') { this.instance.filmOffset = this.filmOffset; + this.instance.updateProjectionMatrix(); return; } if (property === 'focus') { this.instance.focus = this.focus; + this.instance.updateProjectionMatrix(); return; } if (property === 'zoom') { this.instance.zoom = this.zoom; + this.instance.updateProjectionMatrix(); return; } diff --git a/src/game-lib-d3-face.js b/src/game-lib-d3-face.js index 2c8da43..a3b209f 100644 --- a/src/game-lib-d3-face.js +++ b/src/game-lib-d3-face.js @@ -1,10 +1,10 @@ /** - * Face + * GameLib.D3.Face * @constructor * @param implementation * @param apiFace */ -GameLib.D3.Face = function Face( +GameLib.D3.Face = function( implementation, apiFace ) { @@ -51,19 +51,22 @@ GameLib.D3.Face = function Face( ); this.vertexColors = this.vertexColors.map(function(vertexColor){ + + return new GameLib.Color( + this.implementation, + vertexColor, + this + ); + /* if (vertexColor instanceof GameLib.Color) { return vertexColor; } if (vertexColor instanceof GameLib.API.Color) { - return new GameLib.Color( - this.implementation, - vertexColor, - this - ) + } - console.warn('unknown vertex color type', vertexColor); + console.warn('unknown vertex color type', vertexColor);*/ }.bind(this)); } diff --git a/src/game-lib-d3-geometry-buffer-a.js b/src/game-lib-d3-geometry-buffer-a.js index b6ec4dc..033f20c 100644 --- a/src/game-lib-d3-geometry-buffer-a.js +++ b/src/game-lib-d3-geometry-buffer-a.js @@ -122,24 +122,29 @@ GameLib.D3.Geometry.Buffer.prototype.createInstance = function() { var colors = new Float32Array( this.faces.reduce( function(result, face){ - result.push( - face.vertexColors[0].r, - face.vertexColors[0].g, - face.vertexColors[0].b, - face.vertexColors[1].r, - face.vertexColors[1].g, - face.vertexColors[1].b, - face.vertexColors[2].r, - face.vertexColors[2].g, - face.vertexColors[2].b - ); + if (face.vertexColors.length === 3) { + result.push( + face.vertexColors[0].r, + face.vertexColors[0].g, + face.vertexColors[0].b, + face.vertexColors[1].r, + face.vertexColors[1].g, + face.vertexColors[1].b, + face.vertexColors[2].r, + face.vertexColors[2].g, + face.vertexColors[2].b + ); + } return result; }.bind(this), [] ) ); - this.instance.addAttribute('color', new THREE.BufferAttribute(colors, 3, true)); - + + if (colors.length > 0) { + this.instance.addAttribute('color', new THREE.BufferAttribute(colors, 3, true)); + } + /** * Setup face UVs */ @@ -192,8 +197,8 @@ GameLib.D3.Geometry.Buffer.prototype.createInstance = function() { this.instance.addAttribute('normal', new THREE.BufferAttribute(normals, 3 )); //TODO: check below i don't do this - i used to but i don't think i should - //this.instance.normalizeNormals(); - //this.instance.computeVertexNormals(); + this.instance.normalizeNormals(); + this.instance.computeVertexNormals(); /** * Do faces setup @@ -253,12 +258,16 @@ GameLib.D3.Geometry.Buffer.prototype.updateInstance = function(property) { } if (property === 'faces') { - console.warn('todo: faces setup'); + console.warn('todo: faces setup - just re-creating the instance for now'); + this.instance = null; + this.createInstance(); return; } if (property === 'vertices') { - console.warn('todo: vertices setup'); + console.warn('todo: vertices setup - just re-creating the instance for now'); + this.instance = null; + this.createInstance(); return; } @@ -346,90 +355,122 @@ GameLib.D3.Geometry.Buffer.prototype.toApiObject = function() { */ GameLib.D3.Geometry.Buffer.prototype.updateFromInstance = function() { - var vertices = this.instance.getAttribute('position').array; + this.faces = []; + this.vertices = []; - var uvs = this.instance.getAttribute('uv').array; + var normalGeometry = new GameLib.D3.Geometry.Normal(this.graphics); + normalGeometry.instance.fromBufferGeometry(this.instance); + normalGeometry.updateFromInstance(); - this.instance.groups.map(function(group){ - - var materialIndex = group.materialIndex; - - var start = group.start; - - var count = group.count; - - var faceIndexes = []; - - var indexedUvs = []; - - for (var i = start; i < count; i ++) { - - var vertex = new GameLib.D3.Vertex( - this.graphics, - new GameLib.D3.API.Vertex( - new GameLib.Vector3( - this.graphics, - new GameLib.API.Vector3( - vertices[i*3], - vertices[i*3 + 1], - vertices[i*3 + 2] - ) - ) - ) - ); - - var uv = new GameLib.Vector2( - this.graphics, - new GameLib.API.Vector2( - uvs[i*2], - uvs[i*2 + 1] - ) - ); - - indexedUvs.push(uv); - - var vertexIndex = this.vertices.reduce( - function(result, indexedVertex, currentIndex){ - if (indexedVertex.position.equals(vertex.position)) { - result = currentIndex; - } - return result; - }, - -1 - ); - - var faceIndex = vertexIndex; - - if (vertexIndex === -1) { - this.vertices.push(vertex); - faceIndex = this.vertices.length - 1; - } - - faceIndexes.push(faceIndex); - - if (faceIndexes.length === 3) { - - this.faces.push( - new GameLib.D3.Face( - this.graphics, - new GameLib.D3.API.Face( - null, - null, - faceIndexes[0], - faceIndexes[1], - faceIndexes[2], - materialIndex, - [[indexedUvs[0], indexedUvs[1], indexedUvs[2]]] - ) - ) - ); - - indexedUvs = []; - faceIndexes = []; - } + this.faces = normalGeometry.faces.map( + function(face) { + return face; } + ); - }.bind(this)); + this.vertices = normalGeometry.vertices.map( + function(vertex) { + return vertex; + } + ); + + /** + * Now - we have to ensure our geometry is 'downgraded' to a normal buffer geometry + */ + this.geometryType = GameLib.D3.API.Geometry.GEOMETRY_TYPE_BUFFER; + + var componentType = GameLib.D3.API.Geometry.GetComponentType(GameLib.D3.API.Geometry.GEOMETRY_TYPE_BUFFER); + + this.replace(componentType); + + normalGeometry.remove(); + + // TODO: ok - after some testing - this code below doesn't work + // + // var vertices = this.instance.getAttribute('position').array; + // + // var uvs = this.instance.getAttribute('uv').array; + // + // this.instance.groups.map(function(group){ + // + // var materialIndex = group.materialIndex; + // + // var start = group.start; + // + // var count = group.count; + // + // var faceIndexes = []; + // + // var indexedUvs = []; + // + // for (var i = start; i < count; i ++) { + // + // var vertex = new GameLib.D3.Vertex( + // this.graphics, + // new GameLib.D3.API.Vertex( + // new GameLib.Vector3( + // this.graphics, + // new GameLib.API.Vector3( + // vertices[i*3], + // vertices[i*3 + 1], + // vertices[i*3 + 2] + // ) + // ) + // ) + // ); + // + // var uv = new GameLib.Vector2( + // this.graphics, + // new GameLib.API.Vector2( + // uvs[i*2], + // uvs[i*2 + 1] + // ) + // ); + // + // indexedUvs.push(uv); + // + // var vertexIndex = this.vertices.reduce( + // function(result, indexedVertex, currentIndex){ + // if (indexedVertex.position.equals(vertex.position)) { + // result = currentIndex; + // } + // return result; + // }, + // -1 + // ); + // + // var faceIndex = vertexIndex; + // + // if (vertexIndex === -1) { + // this.vertices.push(vertex); + // faceIndex = this.vertices.length - 1; + // } + // + // faceIndexes.push(faceIndex); + // + // if (faceIndexes.length === 3) { + // + // this.faces.push( + // new GameLib.D3.Face( + // this.graphics, + // new GameLib.D3.API.Face( + // null, + // null, + // faceIndexes[0], + // faceIndexes[1], + // faceIndexes[2], + // materialIndex, + // [[indexedUvs[0], indexedUvs[1], indexedUvs[2]]] + // ) + // ) + // ); + // + // indexedUvs = []; + // faceIndexes = []; + // } + // } + // + // }.bind(this)); }; diff --git a/src/game-lib-d3-geometry-normal-a.js b/src/game-lib-d3-geometry-normal-a.js index 0b9c699..7152ae7 100644 --- a/src/game-lib-d3-geometry-normal-a.js +++ b/src/game-lib-d3-geometry-normal-a.js @@ -309,6 +309,9 @@ GameLib.D3.Geometry.Normal.prototype.updateFromInstance = function() { var processed = 0; + this.faces = []; + this.vertices = []; + this.instance.faces.map(function(face, faceIndex){ processed++; diff --git a/src/game-lib-d3-helper.js b/src/game-lib-d3-helper.js index 4fb642a..6ad21af 100644 --- a/src/game-lib-d3-helper.js +++ b/src/game-lib-d3-helper.js @@ -112,7 +112,9 @@ GameLib.D3.Helper.prototype.createInstance = function() { linewidth:2 } ) - ) + ); + + this.updateInstance(); } if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_DIRECTIONAL_LIGHT) { @@ -141,12 +143,17 @@ GameLib.D3.Helper.prototype.createInstance = function() { * Updates the instance with the current state */ GameLib.D3.Helper.prototype.updateInstance = function() { + this.instance.position.copy(this.object.instance.position); + this.instance.scale.copy(this.object.instance.scale); + this.instance.quaternion.copy(this.object.instance.quaternion); - if (this.object.instance.parentMesh && this.object.instance.parentMesh.instance) { - this.instance.position.add(this.object.instance.parentMesh.instance.position); + if (this.object.parentMesh && this.object.parentMesh.instance) { + this.object.parentMesh.instance.add(this.instance); + + this.instance.applyMatrix(this.object.instance.matrix); + this.instance.updateMatrix(); + + this.instance.updateMatrixWorld(); } - - this.instance.scale.copy(this.object.instance.scale); - this.instance.quaternion.copy(this.object.instance.quaternion); }; diff --git a/src/game-lib-d3-mesh-0.js b/src/game-lib-d3-mesh-0.js index 18c3f1a..4f4c88d 100644 --- a/src/game-lib-d3-mesh-0.js +++ b/src/game-lib-d3-mesh-0.js @@ -33,7 +33,8 @@ GameLib.D3.Mesh = function ( apiD3ObjectMesh.receiveShadow, apiD3ObjectMesh.drawMode, apiD3ObjectMesh.morphTargetInfluences, - apiD3ObjectMesh.morphTargetDictionary + apiD3ObjectMesh.morphTargetDictionary, + apiD3ObjectMesh.cloneDirection ); if ( @@ -62,6 +63,12 @@ GameLib.D3.Mesh = function ( ); } + this.cloneDirection = new GameLib.Vector3( + this.graphics, + this.cloneDirection, + this + ); + /** * Runtime meshes have helpers too * @type {null} @@ -311,10 +318,13 @@ GameLib.D3.Mesh.prototype.updateInstance = function(property) { } else { - /** - * Add this as a child to the parent - */ - this.parentMesh.instance.add(this.instance); + if (this.parentMesh.instance) { + + /** + * Add this as a child to the parent + */ + this.parentMesh.instance.add(this.instance); + } } if (this.parentMesh && this.parentMesh.instance) { @@ -404,14 +414,75 @@ GameLib.D3.Mesh.prototype.toApiObject = function() { this.visible, this.castShadow, this.receiveShadow, - this.drawMode - //morphTargetInfluences, - //morphTargetDictionary + this.drawMode, + null,//morphTargetInfluences, + null,//morphTargetDictionary + this.cloneDirection.toApiObject() ); return apiMesh; }; +GameLib.D3.Mesh.prototype.clone = function() { + + var name = this.name + '(' + this.cloneNumber + ')'; + + if (this.cloneNumber > 0) { + name = this.name.replace('(' + this.cloneNumber + ')', '(' + (this.cloneNumber + 1) + ')'); + } + + this.cloneNumber += 1; + + var x = this.position.x; + var y = this.position.y; + var z = this.position.z; + + if (this.cloneDirection.x < 0) { + x += this.geometry.boundingBox.min.x * 2; + } + + if (this.cloneDirection.x > 0) { + x += this.geometry.boundingBox.max.x * 2; + } + + if (this.cloneDirection.y < 0) { + y += this.geometry.boundingBox.min.y * 2; + } + + if (this.cloneDirection.y > 0) { + y += this.geometry.boundingBox.max.y * 2; + } + + if (this.cloneDirection.z < 0) { + z += this.geometry.boundingBox.min.z * 2; + } + + if (this.cloneDirection.z > 0) { + z += this.geometry.boundingBox.max.z * 2; + } + + var mesh = new GameLib.D3.Mesh( + this.graphics, + { + name : name, + materials : this.materials, + geometry : this.geometry, + position: new GameLib.API.Vector3(x, y, z), + scale: this.scale.toApiObject(), + rotation: this.rotation.toApiObject(), + quaternion: this.quaternion.toApiObject(), + useQuaternion: this.useQuaternion, + castShadow : this.castShadow, + receiveShadow : this.receiveShadow, + visible : this.visible + } + ); + + this.parentScene.addClone(mesh); + + return mesh; +}; + /** * Centers the mesh around origin */ @@ -443,10 +514,20 @@ GameLib.D3.Mesh.prototype.centerAroundOrigin = function() { */ GameLib.D3.Mesh.prototype.applyPositionRotationScale = function() { + /** + * Ensure our instance matrix is up to date + */ this.instance.updateMatrix(); + /** + * Apply our instance matrix to the geometry + */ this.instance.geometry.applyMatrix(this.instance.matrix); - this.geometry.instance.updateFromInstance(); + + /** + * Update our geometry from the instance + */ + this.geometry.updateFromInstance(); /** * Reset position @@ -455,7 +536,7 @@ GameLib.D3.Mesh.prototype.applyPositionRotationScale = function() { this.position.x = 0; this.position.y = 0; this.position.z = 0; - this.updateInstancePosition(); + this.updateInstance('position'); /** * Reset scale @@ -464,7 +545,7 @@ GameLib.D3.Mesh.prototype.applyPositionRotationScale = function() { this.scale.x = 1; this.scale.y = 1; this.scale.z = 1; - this.instance.scale.set(1,1,1); + this.updateInstance('scale'); /** * Reset rotation @@ -483,12 +564,7 @@ GameLib.D3.Mesh.prototype.applyPositionRotationScale = function() { this.rotation.y = 0; this.rotation.z = 0; - this.updateInstanceRotation(); - - /** - * Update our instance matrix - */ - this.instance.updateMatrix(); + this.updateInstance('rotation'); }; /** @@ -551,7 +627,7 @@ GameLib.D3.Mesh.prototype.createHelper = function() { GameLib.D3.Helper.HELPER_TYPE_EDGES ); - this.helper.updateInstance(); + //this.helper.updateInstance(); /** * Backup the polygonOffset value, then set it to 'true' - helps for clear nice outlines diff --git a/src/game-lib-d3-pass-render.js b/src/game-lib-d3-pass-render.js index eecb251..3a4c93d 100644 --- a/src/game-lib-d3-pass-render.js +++ b/src/game-lib-d3-pass-render.js @@ -88,6 +88,11 @@ GameLib.D3.Pass.Render.prototype.updateInstance = function(property) { if (GameLib.Utils.UndefinedOrNull(this.instance)) { this.createInstance(); } + + if (this.instance && this.scene.instance) { + this.instance.scene = this.scene.instance; + } + return; } @@ -95,6 +100,11 @@ GameLib.D3.Pass.Render.prototype.updateInstance = function(property) { if (GameLib.Utils.UndefinedOrNull(this.instance)) { this.createInstance(); } + + if (this.instance && this.camera.instance) { + this.instance.camera = this.camera.instance; + } + return; } diff --git a/src/game-lib-d3-scene.js b/src/game-lib-d3-scene.js index 5d1465d..4039644 100644 --- a/src/game-lib-d3-scene.js +++ b/src/game-lib-d3-scene.js @@ -359,11 +359,15 @@ GameLib.D3.Scene.prototype.toApiObject = function() { GameLib.D3.Scene.prototype.addObject = function(object) { if (object instanceof GameLib.D3.Mesh) { - GameLib.Utils.PushUnique(this.meshes, object); + if (this.meshes.indexOf(object.id) === -1) { + GameLib.Utils.PushUnique(this.meshes, object); + } } if (object instanceof GameLib.D3.Light) { - GameLib.Utils.PushUnique(this.lights, object); + if (this.lights.indexOf(object.id) === -1) { + GameLib.Utils.PushUnique(this.lights, object); + } } object.parentScene = this; diff --git a/src/game-lib-render-configuration.js b/src/game-lib-render-configuration.js index 79914d7..f821b4a 100644 --- a/src/game-lib-render-configuration.js +++ b/src/game-lib-render-configuration.js @@ -124,6 +124,13 @@ GameLib.RenderConfiguration.prototype.updateInstance = function(property) { * Update the aspect ratio for the active camera */ this.updateInstance('aspectRatio'); + + GameLib.EntityManager.Instance.queryComponents(GameLib.Component.PASS_RENDER).map( + function(renderPass) { + renderPass.camera = this.activeCamera; + renderPass.updateInstance('camera'); + }.bind(this) + ) } } diff --git a/src/game-lib-system-gui.js b/src/game-lib-system-gui.js index 191224b..571b40b 100644 --- a/src/game-lib-system-gui.js +++ b/src/game-lib-system-gui.js @@ -331,9 +331,9 @@ GameLib.System.GUI.prototype.controller = function(folder, object, property, sub property === 'repeat' || property === 'position' ) { - min = -1000; - max = 1000; - step = 0.01; + min = -100; + max = 100; + step = 0.0001; } if ( @@ -1637,7 +1637,7 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, property === 'bumpScale' || property === 'speed' ) { - controllers.push(folder.add(object, property, 0, 20, 0.001)); + controllers.push(folder.add(object, property, 0, 100, 0.01)); } else if ( property === 'heightOffset' || property === 'rotationFactor' diff --git a/src/game-lib-system-input.js b/src/game-lib-system-input.js index 9dea43e..bde98ab 100644 --- a/src/game-lib-system-input.js +++ b/src/game-lib-system-input.js @@ -4,6 +4,7 @@ * @constructor */ GameLib.System.Input = function( + graphics, apiSystem ) { GameLib.System.call( @@ -13,14 +14,18 @@ GameLib.System.Input = function( this.selectAll = false; + this.editMode = false; + this.controlLeft = false; this.sensitivityCounter = 0; - this.editorControls = []; - this.touchControls = []; - this.keyboardControls = []; - this.mouseControls = []; + this.editorControls = []; + this.orbitControls = []; + this.firstPersonControls = []; + this.touchControls = []; + this.keyboardControls = []; + this.mouseControls = []; /** * Touch Controls @@ -47,13 +52,12 @@ GameLib.System.Input = function( this.mouseWheel = this.onMouseWheel.bind(this); this.mouseUp = this.onMouseUp.bind(this); - /** * Editor Controls * @type {null} */ - this.keyDown = this.onKeyDown.bind(this); - this.keyUp = this.onKeyUp.bind(this); + this.keyDownEdit = this.onKeyDownEdit.bind(this); + this.keyUpEdit = this.onKeyUpEdit.bind(this); this.mouseDownEdit = this.onMouseDownEdit.bind(this); this.mouseMoveEdit = this.onMouseMoveEdit.bind(this); this.mouseWheelEdit = this.onMouseWheelEdit.bind(this); @@ -68,6 +72,7 @@ GameLib.System.Input = function( this.selectionMode = GameLib.System.Input.SELECTION_MODE_DEFAULT; this.mouse = new GameLib.Mouse(); + this.raycaster = new GameLib.D3.Raycaster(graphics); }; GameLib.System.Input.prototype = Object.create(GameLib.System.prototype); @@ -104,19 +109,28 @@ GameLib.System.Input.prototype.start = function() { this.canvasChange.bind(this) ); + this.beforeRenderSubscription = GameLib.Event.Subscribe( + GameLib.Event.BEFORE_RENDER, + this.beforeRender.bind(this) + ); + this.selectionModeChangeSubscription = GameLib.Event.Subscribe( GameLib.Event.SELECTION_MODE_CHANGE, this.selectionModeChange.bind(this) ); - this.editorControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_EDITOR); - this.touchControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_TOUCH); this.keyboardControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_KEYBOARD); this.mouseControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_MOUSE); + this.editorControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_EDITOR); + + this.orbitControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_ORBIT); + + this.firstPersonControls = GameLib.EntityManager.Instance.queryComponents(GameLib.Component.CONTROLS_FIRST_PERSON); + /** * If we have touch controls - inject them first so we can override editor controls if necessary */ @@ -138,11 +152,9 @@ GameLib.System.Input.prototype.start = function() { }.bind(this) ); - this.editorControls.map( - function(editorControl){ - this.registerEditorControls(editorControl); - }.bind(this) - ); + if (this.editMode) { + this.registerEditorControls(); + } }; @@ -163,6 +175,8 @@ GameLib.System.Input.prototype.stop = function() { this.selectionModeChangeSubscription.remove(); + this.beforeRenderSubscription.remove(); + this.touchControls.map( function(touchControl){ this.deRegisterTouchControls(touchControl); @@ -181,14 +195,16 @@ GameLib.System.Input.prototype.stop = function() { }.bind(this) ); - this.editorControls.map( - function(editorControl){ - this.deRegisterEditorControls(editorControl); - }.bind(this) - ); - + if (this.editMode) { + this.deRegisterEditorControls(); + } + this.editorControls = []; + this.firstPersonControls = []; + + this.orbitControls = []; + this.touchControls = []; this.keyboardControls = []; @@ -215,6 +231,22 @@ GameLib.System.Input.prototype.selectionModeChange = function(data) { this.selectionMode = data.selectionMode; }; + +GameLib.System.Input.prototype.beforeRender = function(data) { + this.firstPersonControls.map( + function(controls) { + controls.instance.update(data.delta); + } + ); + + this.orbitControls.map( + function(controls) { + controls.instance.update(data.delta); + } + ); +}; + + /** * From now on we want to track everything about a component, only from the systems that are active * @param data @@ -254,6 +286,34 @@ GameLib.System.Input.prototype.instanceCreated = function(data) { this.registerMouseControls(data.component); } + if (data.component instanceof GameLib.Controls.D3.FirstPerson) { + + if (this.firstPersonControls.indexOf(data.component) !== -1) { + console.warn('First Person Controls already registered'); + return; + } + + this.firstPersonControls.push(data.component); + + if (this.editMode) { + this.registerEditorControls(); + } + } + + if (data.component instanceof GameLib.Controls.D3.Orbit) { + + if (this.orbitControls.indexOf(data.component) !== -1) { + console.warn('Orbit Controls already registered'); + return; + } + + this.orbitControls.push(data.component); + + if (this.editMode) { + this.registerEditorControls(); + } + } + }; /** @@ -264,22 +324,6 @@ GameLib.System.Input.prototype.removeComponent = function(data) { var index; - if (data.component instanceof GameLib.Controls.D3.Editor) { - - index = this.editorControls.indexOf(data.component); - - if (index === -1) { - console.warn('Failed to find the editor controls in the system - probably it was ignored - ' + data.component.name); - return; - } - - console.log('removing editor controls from system'); - - this.deRegisterEditorControls(data.component); - - this.editorControls.splice(index, 1); - } - if (data.component instanceof GameLib.Controls.Touch) { index = this.touchControls.indexOf(data.component); @@ -328,6 +372,50 @@ GameLib.System.Input.prototype.removeComponent = function(data) { this.mouseControls.splice(index, 1); } + if (data.component instanceof GameLib.Controls.D3.Editor) { + + index = this.editorControls.indexOf(data.component); + + if (index === -1) { + console.warn('Failed to find the editor controls in the system - probably it was ignored - ' + data.component.name); + return; + } + + console.log('removing editor controls from system'); + + this.deRegisterEditorControls(data.component); + + this.editorControls.splice(index, 1); + } + + if (data.component instanceof GameLib.Controls.D3.FirstPerson) { + + index = this.firstPersonControls.indexOf(data.component); + + if (index === -1) { + console.warn('Failed to find the first person controls in the system - probably it was ignored - ' + data.component.name); + return; + } + + console.log('removing first person controls from system'); + + this.firstPersonControls.splice(index, 1); + } + + if (data.component instanceof GameLib.Controls.D3.Orbit) { + + index = this.orbitControls.indexOf(data.component); + + if (index === -1) { + console.warn('Failed to find the orbit controls in the system - probably it was ignored - ' + data.component.name); + return; + } + + console.log('removing orbit controls from system'); + + this.orbitControls.splice(index, 1); + } + }; /** @@ -345,7 +433,9 @@ GameLib.System.Input.prototype.delayedInstanceEncountered = function(data) { this.editorControls.push(data.component); - this.registerEditorControls(data.component); + if (this.editMode) { + this.registerEditorControls(); + } } }; @@ -437,7 +527,7 @@ GameLib.System.Input.prototype.registerMouseControls = function(mouseControl) { * TODO: keyboard / mouse /touch controls are in effect * @param editorControl */ -GameLib.System.Input.prototype.registerEditorControls = function(editorControl) { +GameLib.System.Input.prototype.registerEditorControls = function() { /** * In the 'Flammentraum' example, we need the mouse controls @@ -450,62 +540,72 @@ GameLib.System.Input.prototype.registerEditorControls = function(editorControl) // }.bind(this) // ); - /** - * If we already have keyboard controls, we don't want to add another event listener onto the DOM - */ - this.keyboardControls.map( - function(keyboardControl) { - if (keyboardControl.canvas.instance === editorControl.canvas.instance) { - this.deRegisterKeyboardControls(keyboardControl); + GameLib.EntityManager.Instance.queryComponentsByConstructor(GameLib.Controls).map( + function(control) { + /** + * If we already have keyboard controls, we don't want to add another event listener onto the DOM + */ + this.keyboardControls.map( + function(keyboardControl) { + if (keyboardControl.canvas.instance === control.canvas.instance) { + this.deRegisterKeyboardControls(keyboardControl); + } + }.bind(this) + ); + + if (!control.canvas || !control.canvas.instance) { + console.warn('no canvas at time of registration of editor controls - are you sure you know what you are doing?'); + return; } + + control.canvas.instance.addEventListener( + 'mousedown', + this.mouseDownEdit, + true + ); + + control.canvas.instance.addEventListener( + 'mousemove', + this.mouseMoveEdit, + true + ); + + control.canvas.instance.addEventListener( + 'keydown', + this.keyDownEdit, + true + ); + + control.canvas.instance.addEventListener( + 'keyup', + this.keyUpEdit, + true + ); + + /** + * The order of creation is important here - it changes the way the DOM reacts to events + */ + this.editorControls.map( + function(editorControl) { + editorControl.createInstance(); + } + ); + + control.canvas.instance.addEventListener( + 'wheel', + this.mouseWheelEdit, + true + ); + + control.canvas.instance.addEventListener( + 'mouseup', + this.mouseUpEdit, + true + ); }.bind(this) ); - if (!editorControl.canvas || !editorControl.canvas.instance) { - console.warn('no canvas at time of registration of editor controls - are you sure you know what you are doing?'); - return; - } - editorControl.canvas.instance.addEventListener( - 'mousedown', - this.mouseDownEdit, - true - ); - - editorControl.canvas.instance.addEventListener( - 'mousemove', - this.mouseMoveEdit, - true - ); - - editorControl.canvas.instance.addEventListener( - 'keydown', - this.keyDown, - true - ); - - editorControl.canvas.instance.addEventListener( - 'keyup', - this.keyUp, - true - ); - - /** - * The order of creation is important here - it changes the way the DOM reacts to events - */ - editorControl.createInstance(); - - editorControl.canvas.instance.addEventListener( - 'wheel', - this.mouseWheelEdit, - true - ); - - editorControl.canvas.instance.addEventListener( - 'mouseup', - this.mouseUpEdit, - true - ); }; GameLib.System.Input.prototype.deRegisterEditorControls = function(editorControl) { @@ -524,18 +624,22 @@ GameLib.System.Input.prototype.deRegisterEditorControls = function(editorControl editorControl.canvas.instance.removeEventListener( 'keydown', - this.keyDown, + this.keyDownEdit, true ); editorControl.canvas.instance.removeEventListener( 'keyup', - this.keyUp, + this.keyUpEdit, true ); - - editorControl.instance.dispose(); - + + this.editorControls.map( + function(editorControl) { + editorControl.instance.dispose(); + } + ); + editorControl.canvas.instance.removeEventListener( 'wheel', this.mouseWheelEdit, @@ -830,7 +934,7 @@ GameLib.System.Input.prototype.onTouchEnd = function(event) { } }; -GameLib.System.Input.prototype.onKeyDown = function(event) { +GameLib.System.Input.prototype.onKeyDownEdit = function(event) { console.log('input system emitted keypress ' + event.code); @@ -908,7 +1012,7 @@ GameLib.System.Input.prototype.onKeyDown = function(event) { } }; -GameLib.System.Input.prototype.onKeyUp = function(event) { +GameLib.System.Input.prototype.onKeyUpEdit = function(event) { GameLib.Event.Emit( GameLib.Event.KEY_UP, @@ -966,9 +1070,9 @@ GameLib.System.Input.prototype.onMouseDownEdit = function(event) { if (event.button === 2) { - this.editorControls.map( + GameLib.EntityManager.Instance.queryComponentsByConstructor(GameLib.Controls.D3).map( - function(editorControl) { + function(control) { if (this.controlLeft) { return; @@ -990,16 +1094,22 @@ GameLib.System.Input.prototype.onMouseDownEdit = function(event) { function (result, scene) { - editorControl.raycaster.setFromCamera( + this.raycaster.setFromCamera( this.mouse, camera ); - intersects = editorControl.raycaster.getIntersectedObjects(scene.meshes); + this.raycaster.getIntersectedObjects(scene.meshes).map( + function (intersect) { + result.push(intersect); + } + ); - intersects.map(function (intersect) { - result.push(intersect); - }); + this.raycaster.getIntersectedObjects(scene.clones).map( + function (intersect) { + result.push(intersect); + } + ); return result; }.bind(this), @@ -1095,10 +1205,11 @@ GameLib.System.Input.prototype.onMouseMoveEdit = function(event) { // editorControl.camera.quaternion.z = editorControl.camera.instance.quaternion.z; // editorControl.camera.quaternion.w = editorControl.camera.instance.quaternion.w; - editorControl.camera.lookAt.x = editorControl.instance.center.x; - editorControl.camera.lookAt.y = editorControl.instance.center.y; - editorControl.camera.lookAt.z = editorControl.instance.center.z; - editorControl.camera.lookAt.instance.copy(editorControl.instance.center); + //TODO: do this below???!? + //editorControl.camera.lookAt.x = editorControl.instance.center.x; + //editorControl.camera.lookAt.y = editorControl.instance.center.y; + //editorControl.camera.lookAt.z = editorControl.instance.center.z; + //editorControl.camera.lookAt.instance.copy(editorControl.instance.center); } ); }; @@ -1170,6 +1281,13 @@ GameLib.System.Input.prototype.selectMesh = function(mesh) { mesh.createHelper(); + this.orbitControls.map( + function(controls){ + controls.target = mesh; + controls.updateInstance('target'); + } + ); + GameLib.Event.Emit( GameLib.Event.MESH_SELECTED, { @@ -1199,6 +1317,13 @@ GameLib.System.Input.prototype.deselectMesh = function(mesh) { mesh.removeHelper(); + this.orbitControls.map( + function(controls){ + controls.target = null; + controls.updateInstance('target'); + } + ); + GameLib.Event.Emit( GameLib.Event.MESH_DESELECTED, { diff --git a/src/game-lib-system-linking.js b/src/game-lib-system-linking.js index e50f04b..4c265f0 100644 --- a/src/game-lib-system-linking.js +++ b/src/game-lib-system-linking.js @@ -32,7 +32,7 @@ GameLib.System.Linking = function( this.registerDependenciesSubscription = null; this.componentRemoveSubscription = null; this.resolveDependenciesSubscription = null; - // this.replaceComponentSubscription = null; //render system does this + this.replaceComponentSubscription = null; //render system does this /** * Parents @@ -103,10 +103,10 @@ GameLib.System.Linking.prototype.start = function() { this.resolveDependencies ); - // this.replaceComponentSubscription = this.subscribe( - // GameLib.Event.REPLACE_COMPONENT, - // this.replaceComponent - // ); + this.replaceComponentSubscription = this.subscribe( + GameLib.Event.REPLACE_COMPONENT, + this.replaceComponent + ); /** * Parents @@ -497,28 +497,45 @@ GameLib.System.Linking.prototype.registerDependenciesDirect = function(data) { this.registerDependencies(data.component); }; -// Render system does this -// GameLib.System.Linking.prototype.replaceComponent = function(data) { -// -// /** -// * Link canvases -// */ -// if ( -// data.current instanceof GameLib.Renderer && -// data.replacement instanceof GameLib.Renderer -// ) { -// /** -// * Link the canvas to the replacement -// */ -// data.replacement.canvas = data.current.canvas; -// -// /** -// * Unlink the current canvas so it doesn't get removed -// */ -// data.current.canvas = null; -// } -// -// }; +GameLib.System.Linking.prototype.replaceComponent = function(data) { + + /** + * Link canvases + */ + if ( + data.current instanceof GameLib.D3.Geometry.Buffer && + data.replacement instanceof GameLib.D3.Geometry.Buffer + ) { + data.replacement.faces = data.current.faces.map( + function(face) { + return face; + } + ); + + data.replacement.vertices = data.current.vertices.map( + function(vertex) { + return vertex; + } + ); + + data.replacement.updateInstance('faces'); + + /** + * TODO: update both seperately when implemented properly + */ + //data.replacement.updateInstance('vertices'); + + GameLib.EntityManager.Instance.queryComponents(GameLib.Component.MESH).map( + function(mesh) { + if (mesh.geometry === data.current) { + mesh.geometry = data.replacement; + mesh.updateInstance('geometry'); + } + } + ) + } + +}; GameLib.System.Linking.prototype.removeComponent = function(data) { @@ -657,13 +674,7 @@ GameLib.System.Linking.prototype.instanceCreated = function(data) { function(componentId) { if (GameLib.EntityManager.Instance.idRegister[componentId].parentMesh === data.component.id) { GameLib.EntityManager.Instance.idRegister[componentId].parentMesh = data.component; - - /** - * Check if a component has this mesh as a parent - */ - if (GameLib.EntityManager.Instance.idRegister[componentId] instanceof GameLib.D3.Mesh) { - GameLib.EntityManager.Instance.idRegister[componentId].setParentMesh(data.component); - } + GameLib.EntityManager.Instance.idRegister[componentId].updateInstance('parentMesh'); } } ); @@ -682,12 +693,8 @@ GameLib.System.Linking.prototype.instanceCreated = function(data) { GameLib.EntityManager.Instance.queryComponents(GameLib.Component.MESH).map( function (mesh) { if (data.component.parentMesh === mesh.id) { - data.component.parentMesh = mesh; - - if (data.component instanceof GameLib.D3.Mesh) { - data.component.setParentMesh(mesh); - } + data.component.updateInstance('parentMesh'); } } ); @@ -891,7 +898,7 @@ GameLib.System.Linking.prototype.stop = function() { this.registerDependenciesSubscription.remove(); this.componentRemoveSubscription.remove(); this.resolveDependenciesSubscription.remove(); - //this.replaceComponentSubscription.remove(); + this.replaceComponentSubscription.remove(); /** * Parents