UNPKG

janusweb

Version:
194 lines (183 loc) 7.28 kB
elation.require(['janusweb.janusbase'], function() { elation.component.add('engine.things.janusimage', function() { this.postinit = function() { elation.engine.things.janusimage.extendclass.postinit.call(this); this.defineProperties({ image_id: { type: 'string', set: this.setMaterialDirty }, sbs3d: { type: 'boolean', default: false, set: this.setMaterialDirty }, ou3d: { type: 'boolean', default: false, set: this.setMaterialDirty }, reverse3d: { type: 'boolean', default: false, set: this.setMaterialDirty }, onloadstart: { type: 'callback' }, onloadprogress: { type: 'callback' }, onload: { type: 'callback' }, }); } this.createObject3D = function() { var geo = this.createGeometry(); var mat = this.createMaterial(); var mesh = new THREE.Mesh(geo, mat); if (this.texture && this.texture instanceof THREE.SBSTexture) { mesh.onBeforeRender = (renderer, scene, camera) => { if (camera.name) { this.texture.setEye(camera.name); } } } /* var geo = this.createGeometry(); var mat = this.createMaterial(); return new THREE.Mesh(geo, mat); } else { console.log('ERROR - could not find image ' + this.properties.image_id); } */ return mesh; } this.createGeometry = function() { var aspect = this.getAspect(), thickness = 0.1; //Math.max(this.scale.x, this.scale.z) / (10 * this.scale.z); var box = new THREE.BoxGeometry(2, 2 * aspect, thickness); box.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, thickness / this.scale.z)); // Flip the back face for images var uvs = box.attributes.uv; var start = 20, count = 4; for (var i = start; i < start + count; i++) { uvs.array[i*2] = 1.0 - uvs.array[i*2]; } return box; } this.createMaterial = function() { var matargs = { color: this.properties.color, transparent: (this.opacity < 1), opacity: this.opacity, alphaTest: this.alphatest }; this.asset = this.getAsset('image', this.image_id); if (this.asset) { this.texture = this.asset.getInstance(); if (this.texture) { this.dispatchEvent({type: 'loadstart'}); elation.events.add(this.asset, 'asset_load_progress', (ev) => { this.dispatchEvent({type: 'loadprogress', data: ev.data}); }); elation.events.add(this.texture, 'asset_load', elation.bind(this, this.imageloaded)); elation.events.add(this.texture, 'update', elation.bind(this, this.refresh)); matargs.transparent = this.asset.hasalpha; elation.events.add(this.asset, 'asset_load', ev => { matargs.transparent = this.asset.hasalpha; }); } } if (this.texture) { var sidemattex = this.texture.clone(); this.sidetex = sidemattex; sidemattex.repeat.x = .0001; matargs.map = this.texture; } var sidematargs = { map: sidemattex, color: this.properties.color, transparent: matargs.transparent, opacity: matargs.opacity, alphaTest: 0.2 }; var mat = (this.properties.lighting ? new THREE.MeshPhongMaterial(matargs) : new THREE.MeshBasicMaterial(matargs)); var sidemat = (this.properties.lighting ? new THREE.MeshPhongMaterial(sidematargs) : new THREE.MeshBasicMaterial(sidematargs)); var facemat = [sidemat,sidemat,sidemat,sidemat,mat,mat]; this.facematerial = facemat; this.frontmaterial = mat; this.sidematerial = sidemat; if (this.texture) { // Update diffuse map whenever the asset updates (gif frames, etc) elation.events.add(this.texture, 'asset_update', elation.bind(this, function(ev) { this.frontmaterial.map = ev.data; })); } return facemat; } this.setMaterialDirty = function() { this.materialNeedsUpdate = true; } this.handleFrameUpdates = function(ev) { elation.engine.things.janusobject.extendclass.handleFrameUpdates.call(this, ev); if (this.materialNeedsUpdate) { this.updateMaterial(); } } this.updateMaterial = function() { this.asset = this.getAsset('image', this.image_id, true); this.materialNeedsUpdate = false; var newtexture = false; if (this.asset) { newtexture = this.asset.getInstance(); } if (newtexture && newtexture !== this.texture) { this.texture = newtexture; if (newtexture.image) { this.imageloaded(); } else { elation.events.add(this.texture, 'asset_load', elation.bind(this, this.imageloaded)); } elation.events.add(this.texture, 'asset_update', elation.bind(this, function(ev) { this.frontmaterial.map = ev.data; })); } } this.getAspect = function() { var aspect = 1; if (this.asset && this.asset.rawimage) { var size = this.getSize(this.asset.rawimage); aspect = size.height / size.width; } if (this.sbs3d || (this.asset && this.asset.sbs3d)) aspect *= 2; if (this.ou3d || (this.asset && this.asset.ou3d)) aspect /= 2; return aspect; } this.getSize = function(image) { return {width: image.width, height: image.height}; } this.adjustAspectRatio = function() { var img = this.texture.image; var geo = this.createGeometry(); geo.computeBoundingBox(); if (this.colliders.children[0]) { this.colliders.children[0].geometry = geo; } this.objects['3d'].geometry = geo; } this.imageloaded = function(ev) { if (!this.frontmaterial) return; this.frontmaterial.map = this.texture; this.frontmaterial.needsUpdate = true; this.adjustAspectRatio(); setTimeout(() => { this.adjustAspectRatio(); }, 0); this.sidetex.image = this.texture.image; this.sidetex.needsUpdate = true; this.frontmaterial.transparent = this.asset.hasalpha; this.sidematerial.transparent = this.asset.hasalpha; if (this.properties.sbs3d || this.asset.sbs3d) { // TODO - to really support 3d video, we need to set offset based on which eye is being rendered var texture = new THREE.SBSTexture(this.texture.image); texture.reverse = this.properties.reverse3d || this.asset.reverse3d; texture.needsUpdate = true; this.texture = texture; this.frontmaterial.map = texture; /* this.sidematerial.map = texture.clone(); this.sidematerial.map.needsUpdate = true; this.sidematerial.map.repeat.x = .0001; */ //this.objects['3d'].onBeforeRender = () => { texture.swap(); } } this.dispatchEvent({type: 'load'}); this.refresh(); } this.getProxyObject = function(classdef) { if (!this._proxyobject) { this._proxyobject = elation.engine.things.janusimage.extendclass.getProxyObject.call(this, classdef); this._proxyobject._proxydefs = { id: [ 'property', 'image_id'], }; } return this._proxyobject; } }, elation.engine.things.janusbase); });