From c7abedc0c78cc60c71c50d1f7640f90ad7a1cb2c Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Sun, 6 May 2018 17:18:37 +0200 Subject: [PATCH] created initial ar components --- src/r3-a-1-event.js | 4 + src/r3-a-component-a.js | 30 ++++- src/r3-api-ar.js | 73 +++++++++++ src/r3-api-video.js | 66 ++++++++++ src/r3-ar.js | 229 +++++++++++++++++++++++++++++++++++ src/r3-augmented-runtime.js | 53 ++++++++ src/r3-d3-api-a-object.js | 32 +++-- src/r3-d3-api-bone-weight.js | 13 -- src/r3-d3-api-bone.js | 88 ++++---------- src/r3-d3-api-skeleton.js | 32 ----- src/r3-d3-api-z-object.js | 12 +- src/r3-d3-bone.js | 140 ++++++--------------- src/r3-system-ar.js | 96 +++++++++++++++ src/r3-system-render.js | 56 ++++++++- src/r3-video.js | 160 ++++++++++++++++++++++++ 15 files changed, 859 insertions(+), 225 deletions(-) create mode 100644 src/r3-api-ar.js create mode 100644 src/r3-api-video.js create mode 100644 src/r3-ar.js create mode 100644 src/r3-augmented-runtime.js create mode 100644 src/r3-system-ar.js create mode 100644 src/r3-video.js diff --git a/src/r3-a-1-event.js b/src/r3-a-1-event.js index 808c064..9a1156f 100644 --- a/src/r3-a-1-event.js +++ b/src/r3-a-1-event.js @@ -133,6 +133,8 @@ R3.Event.SET_ACTIVE_RENDER_CONFIGURATION = 0x73; R3.Event.REPLACE_COMPONENT = 0x74; R3.Event.COMPONENT_REPLACED = 0x75; R3.Event.ENGINE_FIRED_PARTICLES_ZERO = 0x76; +R3.Event.GET_DEFAULT_SCENE = 0x77; +R3.Event.GET_DEFAULT_CAMERA = 0x78; /** * Returns string name of event ID @@ -261,6 +263,8 @@ R3.Event.GetEventName = function(number) { case 0x74 : return 'replace_component'; case 0x75 : return 'component_replaced'; case 0x76 : return 'engine_fired_particles_zero'; + case 0x77 : return 'get_default_scene'; + case 0x78 : return 'get_default_camera'; break; } diff --git a/src/r3-a-component-a.js b/src/r3-a-component-a.js index 13dae37..f3deef9 100644 --- a/src/r3-a-component-a.js +++ b/src/r3-a-component-a.js @@ -406,8 +406,10 @@ R3.Component.SHADER_FRAGMENT = 0xa0; R3.Component.GEOMETRY_BUFFER_INSTANCED = 0xa1; R3.Component.MATERIAL_SHADER_RAW = 0xa2; R3.Component.MATERIAL_POINTS = 0xa3; +R3.Component.VIDEO = 0xa4; +R3.Component.AR = 0xa5; -R3.Component.MAX_COMPONENTS = 0xa4; +R3.Component.MAX_COMPONENTS = 0xa6; R3.Component.GRAPHICS_RUNTIME = 0x1; R3.Component.PHYSICS_RUNTIME = 0x2; @@ -416,6 +418,7 @@ R3.Component.STATISTICS_RUNTIME = 0x4; R3.Component.DEFAULT_RUNTIME = 0x5; R3.Component.GUI_RUNTIME = 0x6; R3.Component.CODER_RUNTIME = 0x7; +R3.Component.AUGMENTED_RUNTIME = 0x8; R3.Component.GetCompentTypes = function(constructor) { @@ -1406,6 +1409,18 @@ R3.Component.GetComponentInfo = function(number) { constructor : R3.D3.Material.Points, apiConstructor : R3.D3.API.Material.Points }; + case 0xa4 : return { + name : 'R3.Video', + runtime : R3.Component.GRAPHICS_RUNTIME, + constructor : R3.Video, + apiConstructor : R3.API.Video + }; + case 0xa5 : return { + name : 'R3.AR', + runtime : R3.Component.AUGMENTED_RUNTIME, + constructor : R3.AR, + apiConstructor : R3.API.AR + }; break; } @@ -1444,6 +1459,10 @@ R3.Component.GetRuntimeName = function(runtime) { return 'Coder'; } + if (runtime === R3.Component.AUGMENTED_RUNTIME) { + return 'Augmented'; + } + return 'Default'; }; @@ -1953,6 +1972,15 @@ R3.Component.GetRuntimeObject = function(runtimeInfo) { return runtime.statistics; + } else if (runtimeInfo === R3.Component.AUGMENTED_RUNTIME) { + + if (R3.Utils.UndefinedOrNull(runtime.augmented)) { + console.warn('no augmented runtime'); + return null; + } + + return runtime.augmented; + } else if (runtimeInfo === R3.Component.DEFAULT_RUNTIME) { } else { diff --git a/src/r3-api-ar.js b/src/r3-api-ar.js new file mode 100644 index 0000000..490191d --- /dev/null +++ b/src/r3-api-ar.js @@ -0,0 +1,73 @@ +/** + * R3.API.AR + * @param id + * @param name + * @param parentEntity + * @param video + * @param pathCamera + * @param pathMarker + * @param scene + * @param camera + * @param markerRoot + * @constructor + */ +R3.API.AR = function( + id, + name, + parentEntity, + video, + pathCamera, + pathMarker, + scene, + camera, + markerRoot +) { + if (R3.Utils.UndefinedOrNull(id)) { + id = R3.Utils.RandomId(); + } + this.id = id; + + if (R3.Utils.UndefinedOrNull(name)) { + name = 'AR (' + id + ')'; + } + this.name = name; + + if (R3.Utils.UndefinedOrNull(video)) { + video = new R3.API.Video(); + } + this.video = video; + + if (R3.Utils.UndefinedOrNull(pathCamera)) { + pathCamera = 'Data/camera_para.dat'; + } + this.pathCamera = pathCamera; + + if (R3.Utils.UndefinedOrNull(pathMarker)) { + pathMarker = 'Data/patt.hiro'; + } + this.pathMarker = pathMarker; + + if (R3.Utils.UndefinedOrNull(scene)) { + scene = null; + } + this.scene = scene; + + if (R3.Utils.UndefinedOrNull(camera)) { + camera = null; + } + this.camera = camera; + + if (R3.Utils.UndefinedOrNull(markerRoot)) { + markerRoot = new R3.D3.API.Object(); + } + this.markerRoot = markerRoot; + + R3.API.Component.call( + this, + R3.Component.AR, + parentEntity + ); +}; + +R3.API.AR.prototype = Object.create(R3.API.Component.prototype); +R3.API.AR.prototype.constructor = R3.API.AR; diff --git a/src/r3-api-video.js b/src/r3-api-video.js new file mode 100644 index 0000000..b8cd51e --- /dev/null +++ b/src/r3-api-video.js @@ -0,0 +1,66 @@ +/** + * R3.API.Video + * @param id + * @param name + * @param parentEntity + * @param autoUpdateSize + * @param width + * @param height + * @param offset + * @param source + * @constructor + */ +R3.API.Video = function( + id, + name, + parentEntity, + autoUpdateSize, + width, + height, + offset, + source +) { + if (R3.Utils.UndefinedOrNull(id)) { + id = R3.Utils.RandomId(); + } + this.id = id; + + if (R3.Utils.UndefinedOrNull(name)) { + name = 'Video (' + id + ')'; + } + this.name = name; + + if (R3.Utils.UndefinedOrNull(autoUpdateSize)) { + autoUpdateSize = true; + } + this.autoUpdateSize = autoUpdateSize; + + if (R3.Utils.UndefinedOrNull(width)) { + width = 320; + } + this.width = width; + + if (R3.Utils.UndefinedOrNull(height)) { + height = 240; + } + this.height = height; + + if (R3.Utils.UndefinedOrNull(offset)) { + offset = new R3.API.Vector2(0,0); + } + this.offset = offset; + + if (R3.Utils.UndefinedOrNull(source)) { + source = "Data/output_4.ogg"; + } + this.source = source; + + R3.API.Component.call( + this, + R3.Component.VIDEO, + parentEntity + ); +}; + +R3.API.Video.prototype = Object.create(R3.API.Component.prototype); +R3.API.Video.prototype.constructor = R3.API.Video; diff --git a/src/r3-ar.js b/src/r3-ar.js new file mode 100644 index 0000000..71b44ca --- /dev/null +++ b/src/r3-ar.js @@ -0,0 +1,229 @@ +/** + * AR object + * @param augmented + * @param apiAR + * @returns {R3.AR} + * @constructor + */ +R3.AR = function( + augmented, + apiAR +) { + this.augmented = augmented; + + if (R3.Utils.UndefinedOrNull(apiAR)) { + apiAR = {}; + } + + R3.API.AR.call( + this, + apiAR.id, + apiAR.name, + apiAR.parentEntity, + apiAR.video, + apiAR.pathCamera, + apiAR.pathMarker, + apiAR.scene, + apiAR.camera, + apiAR.markerRoot + ); + + if ( + R3.Utils.Defined(this.video) && + R3.Utils.Defined(this.video.componentType) && + !(this.video instanceof R3.Video) + ) { + this.video = R3.Component.ConstructFromObject(this.video); + } + + if ( + R3.Utils.Defined(this.markerRoot) && + R3.Utils.Defined(this.markerRoot.componentType) && + !(this.markerRoot instanceof R3.D3.Object) + ) { + this.markerRoot = R3.Component.ConstructFromObject(this.markerRoot); + } + + R3.Component.call( + this, + { + 'video' : R3.Video, + 'scene' : R3.D3.Scene, + 'camera' : R3.D3.Camera, + 'markerRoot' : R3.D3.Object + } + ); +}; + +R3.AR.prototype = Object.create(R3.Component.prototype); +R3.AR.prototype.constructor = R3.AR; + +/** + * Creates a light instance + * @returns {*} + */ +R3.AR.prototype.createInstance = function() { + + if (this.augmented.augmentedType !== R3.AugmentedRuntime.JS_AR_TOOLKIT_5) { + console.warn('this augmented runtime is not implemented'); + return; + } + + if (this.scene === null) { + + R3.Event.Emit( + R3.Event.GET_DEFAULT_SCENE, + null, + function(scene) { + this.scene = scene; + }.bind(this) + ); + + if (this.scene === null) { + console.warn('there is no default scene to create an AR component with'); + return; + } + } + + if (this.camera === null) { + + R3.Event.Emit( + R3.Event.GET_DEFAULT_CAMERA, + null, + function(camera) { + this.camera = camera; + }.bind(this) + ); + + if (this.camera === null) { + console.warn('there is no default camera to create an AR component with'); + return; + } + } + + ARController.getUserMediaThreeScene( + { + maxARVideoSize: 320, + cameraParam: 'Data/camera_para-iPhone 5 rear 640x480 1.0m.dat', + + onSuccess: function( + arScene, + arController, + arCamera + ) { + + arScene.scene = this.scene.instance; + + arScene.camera = this.camera.instance; + + arController.loadMarker( + this.pathMarker, + function(markerId) { + + var markerRoot = arController.createThreeMarker(markerId); + + this.markerRoot.instance = markerRoot; + + this.markerRoot.instance.markerMatrix = new Float64Array(12); + + // var cameraMatrix = arController.getCameraMatrix(); + // this.camera.instance.projectionMatrix.fromArray(cameraMatrix); + + var child = null; + var c = arScene.scene.children.length - 1; + + for (c; c >= 0; c -= 1) { + child = arScene.scene.children[c]; + markerRoot.add(child); + arScene.scene.remove(child); + } + + arScene.scene.add(markerRoot); + + //arScene.scene.add(this.camera.instance); + + this.instance = { + arScene : arScene, + arController : arController, + arCamera : arCamera + }; + + R3.Component.prototype.createInstance.call(this); + + }.bind(this) + ); + + }.bind(this) + } + ); + +}; + +/** + * Updates the instance with the current state + */ +R3.AR.prototype.updateInstance = function(property) { + + if (R3.Utils.UndefinedOrNull(property)) { + console.warn('unknown property update for AR: ' + property); + } + + if (property === 'id') { + return; + } + + if (property === 'name') { + return; + } + + if (property === 'video') { + console.warn('todo: update video'); + return; + } + + if (property === 'pathCamera') { + console.warn('todo: update pathCamera'); + return; + } + + if (property === 'pathMarker') { + console.warn('todo: update pathMarker'); + return; + } + + if (property === 'scene') { + console.warn('todo: update scene'); + return; + } + + if (property === 'camera') { + console.warn('todo: update camera'); + return; + } + + if (property === 'markerRoot') { + console.warn('todo: update markerRoot'); + return; + } + + R3.Component.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a R3.AR to a R3.API.AR + * @returns {R3.API.AR} + */ +R3.AR.prototype.toApiObject = function() { + + return new R3.API.AR( + this.id, + this.name, + R3.Utils.IdOrNull(this.parentEntity), + this.video.toApiObject(), + this.pathCamera, + this.pathMarker, + R3.Utils.IdOrNull(this.scene), + R3.Utils.IdOrNull(this.camera), + R3.Utils.IdOrNull(this.markerRoot) + ); +}; diff --git a/src/r3-augmented-runtime.js b/src/r3-augmented-runtime.js new file mode 100644 index 0000000..2f11bd8 --- /dev/null +++ b/src/r3-augmented-runtime.js @@ -0,0 +1,53 @@ +/** + * Augmented + * @param id + * @param name + * @param augmentedType + * @constructor + */ +R3.AugmentedRuntime = function( + id, + name, + augmentedType +) { + if (R3.Utils.UndefinedOrNull(id)) { + id = R3.Utils.RandomId(); + } + this.id = id; + + if (R3.Utils.UndefinedOrNull(name)) { + name = 'Augmented (' + id + ')'; + } + this.name = name; + + if (R3.Utils.UndefinedOrNull(augmentedType)) { + augmentedType = R3.AugmentedRuntime.AR_JS; + } + this.augmentedType = augmentedType; + + this.createInstance(); +}; + +/** + * R3.AugmentedRuntime Types + * @type {number} + */ +R3.AugmentedRuntime.JS_AR_TOOLKIT_5 = 0x1; +R3.AugmentedRuntime.AR_JS = 0x2; + +R3.AugmentedRuntime.prototype.createInstance = function() { + if (this.augmentedType === R3.AugmentedRuntime.JS_AR_TOOLKIT_5) { + this.instance = { + ARController : ARController, + ARCameraParam : ARCameraParam + }; + } else { + this.instance = null; + } +}; + +R3.AugmentedRuntime.prototype.updateInstance = function(property) { + if (property === 'augmentedType') { + this.createInstance(); + } +}; diff --git a/src/r3-d3-api-a-object.js b/src/r3-d3-api-a-object.js index 54e6125..43679fa 100644 --- a/src/r3-d3-api-a-object.js +++ b/src/r3-d3-api-a-object.js @@ -65,6 +65,13 @@ R3.D3.API.Object = function( case R3.D3.API.Object.OBJECT_TYPE_MESH : name = 'Mesh'; break; + + /** + * Bones + */ + case R3.D3.API.Object.OBJECT_TYPE_BONE : + name = 'Bone'; + break; } name += ' (' + this.id + ')'; } @@ -147,6 +154,12 @@ R3.D3.API.Object.GetComponentType = function(objectType) { case R3.D3.API.Object.OBJECT_TYPE_MESH : componentType = R3.Component.MESH; break; + /** + * Bones + */ + case R3.D3.API.Object.OBJECT_TYPE_BONE : + componentType = R3.Component.BONE; + break; default: throw new Error('unsupported camera type: ' + objectType); } @@ -154,20 +167,25 @@ R3.D3.API.Object.GetComponentType = function(objectType) { return componentType; }; -R3.D3.API.Object.OBJECT_TYPE_NONE = 0x0; +R3.D3.API.Object.OBJECT_TYPE_NONE = 0x0; /** * Cameras * @type {number} */ -R3.D3.API.Object.OBJECT_TYPE_CAMERA = 0x11; -R3.D3.API.Object.OBJECT_TYPE_CAMERA_PERSPECTIVE = 0x12;//0x1; -R3.D3.API.Object.OBJECT_TYPE_CAMERA_ORTHOGRAPHIC = 0x13;//0x2; -R3.D3.API.Object.OBJECT_TYPE_CAMERA_STEREO = 0x14;//0x3; -R3.D3.API.Object.OBJECT_TYPE_CAMERA_CUBE = 0x15;//0x4; +R3.D3.API.Object.OBJECT_TYPE_CAMERA = 0x11; +R3.D3.API.Object.OBJECT_TYPE_CAMERA_PERSPECTIVE = 0x12;//0x1; +R3.D3.API.Object.OBJECT_TYPE_CAMERA_ORTHOGRAPHIC = 0x13;//0x2; +R3.D3.API.Object.OBJECT_TYPE_CAMERA_STEREO = 0x14;//0x3; +R3.D3.API.Object.OBJECT_TYPE_CAMERA_CUBE = 0x15;//0x4; /** * Meshes * @type {number} */ -R3.D3.API.Object.OBJECT_TYPE_MESH = 0x21; +R3.D3.API.Object.OBJECT_TYPE_MESH = 0x21; + +/** + * Bones + */ +R3.D3.API.Object.OBJECT_TYPE_BONE = 0x31; \ No newline at end of file diff --git a/src/r3-d3-api-bone-weight.js b/src/r3-d3-api-bone-weight.js index 26e139f..0a65279 100644 --- a/src/r3-d3-api-bone-weight.js +++ b/src/r3-d3-api-bone-weight.js @@ -11,16 +11,3 @@ R3.D3.API.BoneWeight = function ( this.boneIndex = boneIndex; this.weight = weight; }; - -/** - * Object to R3.D3.API.BoneWeight - * @param objectBoneWeight - * @returns {R3.D3.API.BoneWeight} - * @constructor - */ -R3.D3.API.BoneWeight.FromObject = function(objectBoneWeight) { - return new R3.D3.API.BoneWeight( - objectBoneWeight.boneIndex, - objectBoneWeight.weight - ) -}; diff --git a/src/r3-d3-api-bone.js b/src/r3-d3-api-bone.js index de34c70..77327cb 100644 --- a/src/r3-d3-api-bone.js +++ b/src/r3-d3-api-bone.js @@ -1,37 +1,25 @@ /** - * Bone Superset - * @param id - * @param name string + * R3.D3.API.Bone + * @param apiD3Object * @param childBoneIds * @param parentBoneIds - * @param quaternion R3.API.Quaternion - * @param position R3.API.Vector3 - * @param scale R3.API.Vector3 - * @param up R3.API.Vector3 - * @param parentEntity * @constructor */ R3.D3.API.Bone = function ( - id, - name, + apiD3Object, childBoneIds, - parentBoneIds, - position, - quaternion, - scale, - up, - parentEntity + parentBoneIds ) { - if (R3.Utils.UndefinedOrNull(id)) { - id = R3.Utils.RandomId(); + if (R3.Utils.UndefinedOrNull(apiD3Object)) { + apiD3Object = { + objectType : R3.D3.API.Object.OBJECT_TYPE_BONE + }; } - this.id = id; - if (R3.Utils.UndefinedOrNull(name)) { - name = 'Bone (' + this.id + ')'; + if (R3.Utils.UndefinedOrNull(apiD3Object.objectType)) { + apiD3Object.objectType = R3.D3.API.Object.OBJECT_TYPE_BONE; } - this.name = name; if (R3.Utils.UndefinedOrNull(childBoneIds)) { childBoneIds = []; @@ -43,51 +31,21 @@ R3.D3.API.Bone = function ( } this.parentBoneIds = parentBoneIds; - if (R3.Utils.UndefinedOrNull(position)) { - position = new R3.API.Vector3(); - } - this.position = position; - - if (R3.Utils.UndefinedOrNull(quaternion)) { - quaternion = new R3.API.Quaternion(); - } - this.quaternion = quaternion; - - if (R3.Utils.UndefinedOrNull(scale)) { - scale = new R3.API.Vector3(1,1,1); - } - this.scale = scale; - - if (R3.Utils.UndefinedOrNull(up)) { - up = new R3.API.Vector3(0,1,0); - } - this.up = up; - - R3.API.Component.call( + R3.D3.API.Object.call( this, - R3.Component.BONE, - parentEntity + apiD3Object.id, + apiD3Object.name, + apiD3Object.objectType, + apiD3Object.parentEntity, + apiD3Object.useQuaternion, + apiD3Object.position, + apiD3Object.quaternion, + apiD3Object.rotation, + apiD3Object.scale, + apiD3Object.up, + apiD3Object.lookAt ); }; -R3.D3.API.Bone.prototype = Object.create(R3.API.Component.prototype); +R3.D3.API.Bone.prototype = Object.create(R3.D3.API.Object.prototype); R3.D3.API.Bone.prototype.constructor = R3.D3.API.Bone; - -/** - * Returns an API bone from an Object bone - * @param objectBone - * @constructor - */ -R3.D3.API.Bone.FromObject = function(objectBone) { - return new R3.D3.API.Bone( - objectBone.id, - objectBone.name, - objectBone.childBoneIds, - objectBone.parentBoneIds, - R3.API.Vector3.FromObject(objectBone.position), - R3.API.Quaternion.FromObject(objectBone.quaternion), - R3.API.Vector3.FromObject(objectBone.scale), - R3.API.Vector3.FromObject(objectBone.up), - objectBone.parentEntity - ); -}; diff --git a/src/r3-d3-api-skeleton.js b/src/r3-d3-api-skeleton.js index e5a64ea..757280c 100644 --- a/src/r3-d3-api-skeleton.js +++ b/src/r3-d3-api-skeleton.js @@ -87,35 +87,3 @@ R3.D3.API.Skeleton = function ( R3.D3.API.Skeleton.prototype = Object.create(R3.API.Component.prototype); R3.D3.API.Skeleton.prototype.constructor = R3.D3.API.Skeleton; - -/** - * Creates an API skeleton from an Object skeleton - * @param objectSkeleton - * @constructor - */ -R3.D3.API.Skeleton.FromObject = function(objectSkeleton) { - return new R3.D3.API.Skeleton( - objectSkeleton.id, - objectSkeleton.name, - objectSkeleton.bones.map( - function (objectBone) { - return R3.D3.API.Bone.FromObject(objectBone); - } - ), - objectSkeleton.boneInverses.map( - function (boneInverse) { - return R3.D3.API.Matrix4.FromObject(boneInverse); - } - ), - objectSkeleton.useVertexTexture, - objectSkeleton.boneTextureWidth, - objectSkeleton.boneTextureHeight, - objectSkeleton.boneMatrices.map( - function (boneMatrix) { - return R3.D3.API.Matrix4.FromObject(boneMatrix); - } - ), - objectSkeleton.boneTexture, - objectSkeleton.parentEntity - ); -}; \ No newline at end of file diff --git a/src/r3-d3-api-z-object.js b/src/r3-d3-api-z-object.js index 9712d26..340e6e6 100644 --- a/src/r3-d3-api-z-object.js +++ b/src/r3-d3-api-z-object.js @@ -114,8 +114,7 @@ R3.D3.Object.GetLinkedObjects = function(objectType) { R3.D3.Object.prototype.createInstance = function() { if (!this.instance) { - console.warn('do not call the R3.D3.Object constructor directly'); - return; + this.instance = new THREE.Object3D(); } this.updateInstance('position'); @@ -214,6 +213,15 @@ R3.D3.Object.prototype.updateInstance = function(property) { } } + // if (!this.instance.matrixAutoUpdate) { + // this.instance.updateMatrixWorld(); + // this.instance.children.map( + // function(child){ + // child.updateMatrixWorld(); + // } + // ) + // } + if (R3.Utils.Defined(this.instance.updateProjectionMatrix)) { this.instance.updateProjectionMatrix(); } diff --git a/src/r3-d3-bone.js b/src/r3-d3-bone.js index 6563509..f9f6bc7 100644 --- a/src/r3-d3-bone.js +++ b/src/r3-d3-bone.js @@ -1,64 +1,39 @@ /** - * Bone Superset + * R3.D3.Bone * @constructor * @param graphics R3.GraphicsRuntime - * @param apiBone R3.D3.API.Bone + * @param apiD3ObjectBone */ R3.D3.Bone = function ( graphics, - apiBone + apiD3ObjectBone ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); - if (R3.Utils.UndefinedOrNull(apiBone)) { - apiBone = {}; + if (R3.Utils.UndefinedOrNull(apiD3ObjectBone)) { + apiD3ObjectBone = { + objectType: R3.D3.API.Object.OBJECT_TYPE_BONE + }; } - R3.D3.API.Bone.call( + R3.D3.API.Bone.call( this, - apiBone.id, - apiBone.name, - apiBone.childBoneIds, - apiBone.parentBoneIds, - apiBone.position, - apiBone.quaternion, - apiBone.scale, - apiBone.up, - apiBone.parentEntity + apiD3ObjectBone, + apiD3ObjectBone.childBoneIds, + apiD3ObjectBone.parentBoneIds ); - this.position = new R3.Vector3( - graphics, - this.position, + R3.D3.Object.call( + this, + this.graphics, this ); - - this.quaternion = new R3.Quaternion( - graphics, - this.quaternion, - this - ); - - this.scale = new R3.Vector3( - graphics, - this.scale, - this - ); - - this.up = new R3.Vector3( - graphics, - this.up, - this - ); - - R3.Component.call(this); }; -R3.D3.Bone.prototype = Object.create(R3.Component.prototype); +R3.D3.Bone.prototype = Object.create(R3.D3.Object.prototype); R3.D3.Bone.prototype.constructor = R3.D3.Bone; - /** * Creates an instance bone @@ -67,52 +42,34 @@ R3.D3.Bone.prototype.createInstance = function() { this.instance = new THREE.Bone(); - this.instance.name = this.name; - - this.instance.position.x = this.position.x; - this.instance.position.y = this.position.y; - this.instance.position.z = this.position.z; - - this.instance.quaternion.x = this.quaternion.x; - this.instance.quaternion.y = this.quaternion.y; - this.instance.quaternion.z = this.quaternion.z; - this.instance.quaternion.w = this.quaternion.w; - - this.instance.scale.x = this.scale.x; - this.instance.scale.y = this.scale.y; - this.instance.scale.z = this.scale.z; - - this.instance.up.x = this.up.x; - this.instance.up.y = this.up.y; - this.instance.up.z = this.up.z; - - R3.Component.prototype.createInstance.call(this); + R3.D3.Object.prototype.createInstance.call(this); }; /** * Updates the instance */ R3.D3.Bone.prototype.updateInstance = function(property) { - this.instance.name = this.name; - this.instance.position.x = this.position.x; - this.instance.position.y = this.position.y; - this.instance.position.z = this.position.z; + if (!this.instance) { + console.warn('bone instance not ready'); + } - this.instance.quaternion.x = this.quaternion.x; - this.instance.quaternion.y = this.quaternion.y; - this.instance.quaternion.z = this.quaternion.z; - this.instance.quaternion.w = this.quaternion.w; + if (property === 'name') { + this.instance.name = this.name; + return; + } - this.instance.scale.x = this.scale.x; - this.instance.scale.y = this.scale.y; - this.instance.scale.z = this.scale.z; + if (property === 'childBoneIds') { + console.warn('todo: child bone ids update'); + return; + } - this.instance.up.x = this.up.x; - this.instance.up.y = this.up.y; - this.instance.up.z = this.up.z; + if (property === 'parentBoneIds') { + console.warn('todo: parent bone ids update'); + return; + } - R3.Component.prototype.updateInstance.call(this, property); + R3.D3.Object.prototype.updateInstance.call(this, property); }; /** @@ -121,38 +78,13 @@ R3.D3.Bone.prototype.updateInstance = function(property) { */ R3.D3.Bone.prototype.toApiObject = function() { + var apiD3Object = R3.D3.Object.prototype.toApiObject.call(this); + var apiBone = new R3.D3.API.Bone( - this.id, - this.name, + apiD3Object, this.childBoneIds, - this.parentBoneIds, - this.position.toApiObject(), - this.quaternion.toApiObject(), - this.scale.toApiObject(), - this.up.toApiObject(), - R3.Utils.IdOrNull(this.parentEntity) + this.parentBoneIds ); return apiBone; -}; - -/** - * Returns a R3.D3.Bone from a bone Object - * @param graphics R3.GraphicsRuntime - * @param objectBone Object - * @returns {R3.D3.Bone} - * @constructor - */ -R3.D3.Bone.FromObject = function( - graphics, - objectBone -) { - var apiBone = R3.D3.API.Bone.FromObject(objectBone); - - var bone = R3.D3.Bone( - graphics, - apiBone - ); - - return bone; }; \ No newline at end of file diff --git a/src/r3-system-ar.js b/src/r3-system-ar.js new file mode 100644 index 0000000..2ed27ed --- /dev/null +++ b/src/r3-system-ar.js @@ -0,0 +1,96 @@ +/** + * R3.System.AR + * @param apiSystem R3.API.System + * @constructor + */ +R3.System.AR = function( + apiSystem +) { + R3.System.call( + this, + apiSystem + ); + + this.instanceCreatedSubscription = null; + + this.removeComponentSubscription = null; + + this.beforeRenderSubscription = null; + + this.arComponents = []; + +}; + +R3.System.AR.prototype = Object.create(R3.System.prototype); +R3.System.AR.prototype.constructor = R3.System.AR; + +/** + * Start this system (add all event listeners) + */ +R3.System.AR.prototype.start = function() { + + R3.System.prototype.start.call(this); + + this.instanceCreatedSubscription = this.subscribe( + R3.Event.INSTANCE_CREATED, + this.instanceCreated + ); + + this.removeComponentSubscription = this.subscribe( + R3.Event.REMOVE_COMPONENT, + this.removeComponent + ); + + this.beforeRenderSubscription = this.subscribe( + R3.Event.BEFORE_RENDER, + this.beforeRender + ); + +}; + +/** + * From now on we want to track everything about a component, only from the systems that are active + * @param data + */ +R3.System.AR.prototype.instanceCreated = function(data) { + if (data.component instanceof R3.D3.AR) { + R3.Utils.PushUnique(this.arComponents, data.component); + } +}; + +/** + * Removes an AR component from the System + * @param data + */ +R3.System.AR.prototype.removeComponent = function(data) { + + if (data.component instanceof R3.D3.AR) { + + var index = this.arComponents.indexOf(data.component); + + if (index === -1) { + console.warn('AR system out of sync'); + return; + } + + this.arComponents.splice(index, 1); + } +}; + +R3.System.AR.prototype.beforeRender = function(data) { + console.log('AR Render'); +}; + + +/** + * Stop this system (remove all event listeners) + */ +R3.System.AR.prototype.stop = function() { + + R3.System.prototype.stop.call(this); + + this.instanceCreatedSubscription.remove(); + this.removeComponentSubscription.remove(); + this.beforeRenderSubscription.remove(); + +}; diff --git a/src/r3-system-render.js b/src/r3-system-render.js index f2646ed..cb7b53f 100644 --- a/src/r3-system-render.js +++ b/src/r3-system-render.js @@ -66,6 +66,8 @@ R3.System.Render.prototype.start = function() { this.cubeCameras = R3.EntityManager.Instance.queryComponents(R3.Component.CAMERA_CUBE); + this.arComponents = R3.EntityManager.Instance.queryComponents(R3.Component.AR); + this.excludedFromEnvironment = []; R3.EntityManager.Instance.queryComponentsByConstructor(R3.D3.Mesh).map( @@ -368,6 +370,10 @@ R3.System.Render.prototype.instanceCreated = function(data) { this.cubeCameras.push(data.component); } + if (data.component instanceof R3.AR) { + this.arComponents.push(data.component); + } + if ( data.component instanceof R3.D3.Mesh && data.component.excludeFromEnvironment @@ -595,6 +601,20 @@ R3.System.Render.prototype.removeComponent = function(data) { } } + if (data.component instanceof R3.AR) { + + index = this.arComponents.indexOf(data.component); + + if (index !== -1) { + console.log('removing ar component from render system'); + + this.arComponents.splice(index, 1); + + } else { + console.log('failed to find the ar component in the render system : ' + data.component.name); + } + } + if (data.component instanceof R3.D3.Mesh) { index = this.excludedFromEnvironment.indexOf(data.component); if (index !== -1) { @@ -668,6 +688,17 @@ R3.System.Render.prototype.render = function(data) { } } + var arComponent = null; + + if (this.arComponents.length > 1) { + console.warn('only one AR component supported at this time'); + return; + } + + if (this.arComponents.length === 1) { + arComponent = this.arComponents[0]; + } + var size = renderer.getSize(); renderer.viewports.map( @@ -737,7 +768,28 @@ R3.System.Render.prototype.render = function(data) { return; } - renderer.render(scene, camera); + if (arComponent) { + + arComponent.instance.arScene.process(); + + // if (arComponent.markerRoot.instance.visible) { + // arComponent.instance.arController.getTransMatSquareCont( + // 0, + // 1, + // arComponent.markerRoot.instance.markerMatrix, + // arComponent.markerRoot.instance.markerMatrix + // ); + // } + // + // arComponent.instance.arController.transMatToGLMat( + // arComponent.markerRoot.instance.markerMatrix, + // arComponent.markerRoot.instance.matrix.elements + // ); + + arComponent.instance.arScene.renderOn(renderer.instance); + } else { + renderer.render(scene, camera); + } } }.bind(this) @@ -823,5 +875,7 @@ R3.System.Render.prototype.stop = function() { this.statistics = []; this.cubeCameras = []; + + this.arComponents = []; }; diff --git a/src/r3-video.js b/src/r3-video.js new file mode 100644 index 0000000..815d96c --- /dev/null +++ b/src/r3-video.js @@ -0,0 +1,160 @@ +/** + * Video object + * @param graphics + * @param apiVideo + * @returns {R3.Video} + * @constructor + */ +R3.Video = function( + graphics, + apiVideo +) { + this.graphics = graphics; + + if (R3.Utils.UndefinedOrNull(apiVideo)) { + apiVideo = {}; + } + + R3.API.Video.call( + this, + apiVideo.id, + apiVideo.name, + apiVideo.parentEntity, + apiVideo.autoUpdateSize, + apiVideo.width, + apiVideo.height, + apiVideo.offset, + apiVideo.source + ); + + this.offset = new R3.Vector2( + this.graphics, + this.offset, + this + ); + + R3.Component.call(this); +}; + +R3.Video.prototype = Object.create(R3.Component.prototype); +R3.Video.prototype.constructor = R3.Video; + +/** + * Creates a light instance + * @returns {*} + */ +R3.Video.prototype.createInstance = function() { + + this.instance = document.createElement('video'); + + this.instance.setAttribute('id', this.id); + + this.instance.setAttribute('width', this.width); + + this.instance.setAttribute('height', this.height); + + this.instance.setAttribute('style', 'left: ' + this.offset.x + 'px;top: ' + this.offset.y + 'px'); + + this.instance.setAttribute('loop', ''); + + this.instance.setAttribute('controls', ''); + + this.instance.setAttribute('autoplay', ''); + + this.instance.setAttribute('webkit-playsinline', ''); + + if (this.autoUpdateSize) { + /** + * Update our size from the instance size + */ + this.width = this.instance.width; + this.height = this.instance.height; + } else { + /** + * Update our instance with our size + */ + this.instance.width = this.width; + this.instance.height = this.height; + } + + this.instance.setAttribute('src', this.source); + + R3.Component.prototype.createInstance.call(this); +}; + +/** + * Updates the instance with the current state + */ +R3.Video.prototype.updateInstance = function(property) { + + if (R3.Utils.UndefinedOrNull(property)) { + console.warn('unknown property update for Video: ' + property); + } + + if (property === 'id') { + this.instance.setAttribute('id', this.id); + return; + } + + if (property === 'offset') { + this.instance.style.left = this.offset.x + 'px'; + this.instance.style.top = this.offset.y + 'px'; + return; + } + + if ( + property === 'autoUpdateSize' || + property === 'width' || + property === 'height' + ) { + /** + * We cannot control everything about the canvas - this is dependent on where the canvas lives and its + * dimensions can also be controlled via CSS - + * + * This means - autoUpdateSize works a little different for this component - instead of getting our size and + * applying it, it gets our canvas size and applies it, or applies our size to the canvas - of course + * the user settings override this. + */ + if (this.autoUpdateSize) { + + /** + * Update from our canvas size + */ + this.width = this.instance.width; + this.height = this.instance.height; + + } else { + + /** + * Command our canvas to take a size - this is not guaranteed however - CSS wins + */ + this.instance.width = this.width; + this.instance.height = this.height; + } + return; + } + + if (property === 'source') { + this.instance.src = this.source; + return; + } + + R3.Component.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a R3.Video to a R3.API.Video + * @returns {R3.API.Video} + */ +R3.Video.prototype.toApiObject = function() { + return new R3.API.Video( + this.id, + this.name, + R3.Utils.IdOrNull(this.parentEntity), + this.autoUpdateSize, + this.width, + this.height, + this.offset.toApiObject(), + this.source + ); +};