From a60086c681dee7506b5f948839da4ee7a37b18a0 Mon Sep 17 00:00:00 2001 From: Sandro Weber <webers@in.tum.de> Date: Wed, 16 Dec 2020 11:16:41 +0000 Subject: [PATCH] Merged in NUIT-221-collada-loader-1.4.1 (pull request #47) [NUIT-221] mirroring frontend changes * [NUIT-221] mirroring frontend changes Approved-by: Stefano Nardo Approved-by: Manos Angelidis --- gz3d/build/gz3d.js | 275 +++++++++++++++++++++---------- gz3d/src/gz3d-animated-models.js | 24 ++- gz3d/src/gzautoalignmodel.js | 9 +- gz3d/src/gzbloomShader.js | 35 ++-- gz3d/src/gzcomposer.js | 96 +++++------ gz3d/src/gziface.js | 2 +- gz3d/src/gzlabelmanager.js | 2 +- gz3d/src/gzmanipulator.js | 8 +- gz3d/src/gzmultiview.js | 3 +- gz3d/src/gzscene.js | 110 ++++++++++++- 10 files changed, 379 insertions(+), 185 deletions(-) diff --git a/gz3d/build/gz3d.js b/gz3d/build/gz3d.js index b25f200..7d7f92a 100644 --- a/gz3d/build/gz3d.js +++ b/gz3d/build/gz3d.js @@ -207,13 +207,7 @@ GZ3D.AnimatedModel = function(scene) { }; GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { - this.loader = new THREE.ColladaLoader(); - this.loader.textureLoadedCallback = () => { - this.scene.refresh3DViews(); - }; - // Helper function to enable 'skinning' property so three.js treats meshes as deformable - var enableSkinning = function(skinnedMesh) { var materials = skinnedMesh.material.materials; if (materials !== null && materials !== undefined) { @@ -238,16 +232,18 @@ GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { element.totalSize = 0; element.done = false; GZ3D.assetProgressData.assets.push(element); - var scene = this.scene; - this.loader.load( + + this.scene.loadCollada( element.url, - function(collada) { + null, + null, + (dae) => { var modelParent = new THREE.Object3D(); modelParent.name = modelName + '_animated'; var linkParent = new THREE.Object3D(); // Set gray, phong-shaded material for loaded model - collada.scene.traverse(function(child) { + dae.traverse(function(child) { if (child instanceof THREE.Mesh) { var applyDefaultMaterial = true; @@ -273,13 +269,13 @@ GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { }); // Enable skinning for all child meshes - collada.scene.traverse(function(child) { + dae.traverse(function(child) { if (child instanceof THREE.SkinnedMesh) { enableSkinning(child); } }); - linkParent.add(collada.scene); + linkParent.add(dae); // Hide model coordinate frames for the time being; remove as soon as position offset and rotation axis issues are fixed /*var collada_scene_axes = new THREE.AxisHelper(2); @@ -316,13 +312,13 @@ GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { return boneList; }; - var boneList = getBoneList(collada.scene); + var boneList = getBoneList(dae); var boneHash = {}; for (var k = 0; k < boneList.length; k++) { boneHash[boneList[k].name] = boneList[k]; } // Skeleton visualization helper class - var helper = new THREE.SkeletonHelper(collada.scene); + var helper = new THREE.SkeletonHelper(dae); boneHash['Skeleton_Visual_Helper'] = helper; modelParent.userData = boneHash; @@ -1019,8 +1015,10 @@ GZ3D.AutoAlignModel.prototype.alignToObjects = function(position) { snap2bbox.setFromObject(snap2obj); if (Math.abs(snap2bbox.min.x) !== Infinity) { if (i === 0) { - var s = bbox.getSize(); - var s2 = snap2bbox.getSize(); + var s = new THREE.Vector3(); + bbox.getSize(s); + var s2 = new THREE.Vector3(); + snap2bbox.getSize(s2); if ( Math.abs(s.x - s2.x) > 0.01 || Math.abs(s.y - s2.y) > 0.01 @@ -1233,7 +1231,8 @@ GZ3D.AutoAlignModel.prototype.alignOnShape = function(position, hitDesc) { return; } - var q = hitDesc.object.getWorldQuaternion(); + var q = new THREE.Quaternion(); + hitDesc.object.getWorldQuaternion(q); var abv = new THREE.Vector3(); var acv = new THREE.Vector3(); @@ -1738,7 +1737,8 @@ GZ3D.BloomShader.prototype = Object.assign( this.highPassUniforms['tDiffuse'].value = readBuffer.texture; this.highPassUniforms['luminosityThreshold'].value = this.threshold; this.quad.material = this.materialHighPassFilter; - renderer.render(this.scene, this.camera, this.renderTargetBright, true); + renderer.setRenderTarget(this.renderTargetBright); + renderer.render(this.scene, this.camera); // 2. Blur All the mips progressively var inputRenderTarget = this.renderTargetBright; @@ -1752,12 +1752,9 @@ GZ3D.BloomShader.prototype = Object.assign( this.separableBlurMaterials[i].uniforms['direction'].value = GZ3D.BloomShader.BlurDirectionX; - renderer.render( - this.scene, - this.camera, - this.renderTargetsHorizontal[i], - true - ); + renderer.clear(); + renderer.setRenderTarget(this.renderTargetsHorizontal[i]); + renderer.render(this.scene, this.camera); this.separableBlurMaterials[i].uniforms[ 'colorTexture' @@ -1766,12 +1763,9 @@ GZ3D.BloomShader.prototype = Object.assign( this.separableBlurMaterials[i].uniforms['direction'].value = GZ3D.BloomShader.BlurDirectionY; - renderer.render( - this.scene, - this.camera, - this.renderTargetsVertical[i], - true - ); + renderer.clear(); + renderer.setRenderTarget(this.renderTargetsVertical[i]); + renderer.render(this.scene, this.camera); inputRenderTarget = this.renderTargetsVertical[i]; } @@ -1783,12 +1777,9 @@ GZ3D.BloomShader.prototype = Object.assign( this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors; - renderer.render( - this.scene, - this.camera, - this.renderTargetsHorizontal[0], - true - ); + renderer.clear(); + renderer.setRenderTarget(this.renderTargetsHorizontal[0]); + renderer.render(this.scene, this.camera); // Blend it additively over the input texture this.quad.material = this.materialCopy; @@ -1799,8 +1790,9 @@ GZ3D.BloomShader.prototype = Object.assign( if (maskActive) { renderer.context.enable(renderer.context.STENCIL_TEST); } - - renderer.render(this.scene, this.camera, readBuffer, false); + + renderer.setRenderTarget(readBuffer); + renderer.render(this.scene, this.camera); renderer.setClearColor(this.oldClearColor, this.oldClearAlpha); renderer.autoClear = oldAutoClear; @@ -2885,7 +2877,9 @@ GZ3D.Composer.prototype.render = function(view) { this.scene.background = null; // Some effects should be disabled during depth buffer rendering this.lensFlare.visible = false; this.scene.overrideMaterial = view.depthMaterial; - view.renderer.render(this.scene, camera, view.depthRenderTarget, true); // Render to depth buffer now! + view.renderer.clear(); + view.renderer.setRenderTarget(view.depthRenderTarget); + view.renderer.render(this.scene, camera); // Render to depth buffer now! this.scene.overrideMaterial = null; } @@ -3121,50 +3115,53 @@ GZ3D.Composer.prototype.buildSkin = function(skin) { skin.initialized = true; var parent = that.scene.getObjectByName(skin.parentObject, true); if (parent) { - var loader = new THREE.ColladaLoader(); + var uri = GZ3D.assetsPath + '/' + skin.mesh; + that.gz3dScene.loadCollada( + uri, + null, + null, + (dae) => { + var mapToMesh = that.scene.getObjectByName(skin.mapTo); - loader.load(GZ3D.assetsPath + '/' + skin.mesh, function(collada) { - var dae = collada.scene; - var mapToMesh = that.scene.getObjectByName(skin.mapTo); + if (skin.scale) + dae.scale.copy(new THREE.Vector3(skin.scale, skin.scale, skin.scale)); - if (skin.scale) - dae.scale.copy(new THREE.Vector3(skin.scale, skin.scale, skin.scale)); - - parent.add(dae); - that.gz3dScene.refresh3DViews(); + parent.add(dae); + that.gz3dScene.refresh3DViews(); - dae.traverse(function(object) { - object._isPartOfTheSkin = true; - }); + dae.traverse(function(object) { + object._isPartOfTheSkin = true; + }); - var skinBoneMap = []; - var skinnedObject = { - skinBoneMap: skinBoneMap, - definition: skin, - skinMesh: dae, - mapToMesh: mapToMesh, - parentMesh: parent - }; + var skinBoneMap = []; + var skinnedObject = { + skinBoneMap: skinBoneMap, + definition: skin, + skinMesh: dae, + mapToMesh: mapToMesh, + parentMesh: parent + }; - that.skinnedObjects.push(skinnedObject); + that.skinnedObjects.push(skinnedObject); - dae._skinnedObject = skinnedObject; - parent._skinnedObject = skinnedObject; - mapToMesh._skinnedObject = skinnedObject; + dae._skinnedObject = skinnedObject; + parent._skinnedObject = skinnedObject; + mapToMesh._skinnedObject = skinnedObject; - dae.traverse(function(bone) { - if (bone instanceof THREE.Bone) { - var r = mapToMesh.getObjectByName(skin.bonePrefix + bone.name); - if (r) { - skinBoneMap.push({ joint: r, bone: bone }); - that.setSkinVisibility(skinnedObject, skin.visible); + dae.traverse(function(bone) { + if (bone instanceof THREE.Bone) { + var r = mapToMesh.getObjectByName(skin.bonePrefix + bone.name); + if (r) { + skinBoneMap.push({ joint: r, bone: bone }); + that.setSkinVisibility(skinnedObject, skin.visible); - r._skinnedObject = skinnedObject; - bone._skinnedObject = skinnedObject; + r._skinnedObject = skinnedObject; + bone._skinnedObject = skinnedObject; + } } - } - }); - }); + }); + } + ); } } }; @@ -3181,11 +3178,9 @@ GZ3D.Composer.prototype.buildSkins = function() { if (!this.skinnedObjects) this.skinnedObjects = []; // Skins created from the .ini file of the experiment - if (cs.skins) cs.skins.forEach(skin => that.buildSkin(skin)); // Skins created dynamically from the frontend - if (this.skins) this.skins.forEach(skin => that.buildSkin(skin)); this.skinsInitialized = true; @@ -3212,7 +3207,8 @@ GZ3D.Composer.prototype.updateSkin = function() { var invM = new THREE.Matrix4(); invM.getInverse(bone.parent.matrixWorld); - var p = joint.getWorldPosition(); + var p = new THREE.Vector3(); + joint.getWorldPosition(p); var jM = new THREE.Matrix4(); var bp = new THREE.Vector3(), @@ -5979,7 +5975,7 @@ GZ3D.GZIface.prototype.createGeom = function( // HBP Change (Luc): we assume that all requested collada files are // are web-compliant - if (modelUri.indexOf('.dae') !== -1 || modelUri.indexOf('.DAE') !== -1) { + if (modelUri.substr(-4).toLowerCase() === '.dae') { var materialName = parent.name + '::' + element.url; that.scene.loadMesh( @@ -6817,7 +6813,7 @@ GZ3D.LabelManager.prototype.createLineLabel = function(parent) { linewidth: 3 }); var line = new THREE.Line(lineGeometry, lineMaterial); - lineGeometry.computeLineDistances(); + line.computeLineDistances(); this.scene.scene.add(line); @@ -8362,9 +8358,13 @@ GZ3D.Manipulator = function(gz3dScene, mobile) { } }; + let worldPose = new THREE.Vector3(); + let worldRotation = new THREE.Quaternion(); + currentObject.getWorldPosition(worldPose); + currentObject.getWorldQuaternion(worldRotation); var objectWorldPose = { - pos: currentObject.getWorldPosition(), - rot: currentObject.getWorldQuaternion() + pos: worldPose, + rot: worldRotation }; var mouseDistance = getMouseMoveDistance( @@ -9022,7 +9022,8 @@ GZ3D.MultiView.prototype.setShadowMaps = function(enabled) { GZ3D.MultiView.prototype.clearRenderTargets = function(target) { this.views.forEach(function(view, index, array) { - view.renderer.clearTarget(target); + view.renderer.setRenderTarget(target); + view.renderer.clear(); }); }; @@ -10385,6 +10386,7 @@ GZ3D.Scene.prototype.setPose = function(model, position, orientation) { model.quaternion.x = orientation.x; model.quaternion.y = orientation.y; model.quaternion.z = orientation.z; + this.refresh3DViews(); this.updateBoundingBox(model); }; @@ -11221,6 +11223,101 @@ GZ3D.Scene.prototype.loadMesh = function( } }; +GZ3D.Scene.prototype.preparePBRMaterials = function(basePath, collada) { + var libEffects = collada.library.effects; + var libMaterials = collada.library.materials; + var libImages = collada.library.images; + + for (const materialKey in libMaterials) { + var material = libMaterials[materialKey]; + var effect = libEffects[material.url]; + + function getTexturePath(textureObject) { + var sampler = effect.profile.samplers[textureObject.id]; + var surface = effect.profile.surfaces[sampler.source]; + + if (sampler !== undefined && surface !== null) { + var img = libImages[surface.init_from]; + + return basePath + '/' + img.build; + } + } + + var parameters = effect.profile.technique.parameters; + var parameter; + var pbrMaterial = null; + + var pbrKeyToThreeJSMap = { + Base_Color: 'map', + Metallic: 'metalnessMap', + Roughness: 'roughnessMap', + Mixed_AO: 'aoMap', + Emissive: 'emissiveMap', + Normal: 'normalMap', + Height: 'displacementMap' + }; + + for (var key in parameters) { + parameter = parameters[key]; + if (parameter.texture) { + var texturePath = getTexturePath(parameter.texture); + + if ( + texturePath && + (texturePath.indexOf('PBR_') >= 0 || + texturePath.indexOf('PBRFULL_') >= 0) + ) { + for (var k in pbrKeyToThreeJSMap) { + if (texturePath.indexOf(k) >= 0) { + if (pbrMaterial === null) { + pbrMaterial = {}; + } + + pbrMaterial[pbrKeyToThreeJSMap[k]] = texturePath; + + if ( + texturePath.indexOf('PBRFULL_') >= 0 && + k === 'Base_Color' + ) { + // If the prefix is PBRFULL it means that all the PBR textures are present + // but that only the basic color map have been linked to the dae. + + var allpbrkeywords = [ + 'Metallic', + 'Mixed_AO', + 'Roughness', + 'Normal', + 'Roughness' + ]; + + for (var pbri in allpbrkeywords) { + var pbrk = allpbrkeywords[pbri]; + var path = texturePath; + + path = path.replace('Base_Color', pbrk); + if (pbrk === 'Normal') { + // Normal map must be png. In case the Base_Color is a jpg, + // change extension to png + + path = path.replace('.jpg', '.png'); + path = path.replace('.jpeg', '.png'); + } + + pbrMaterial[pbrKeyToThreeJSMap[pbrk]] = path; + } + } + } + } + } + } + } + + if (pbrMaterial !== null) { + material.build.pbrMaterialDescription = pbrMaterial; // If PBR material has been found, store it for future usage + } + } +} + /** * Load collada file * @param {string} uri @@ -11236,7 +11333,6 @@ GZ3D.Scene.prototype.loadCollada = function( progressCallback ) { var dae; - var mesh = null; var cachedModel = this.cachedModels[uri]; if (cachedModel && cachedModel.referenceObject) { @@ -11250,12 +11346,8 @@ GZ3D.Scene.prototype.loadCollada = function( loader.textureLoadedCallback = () => { this.refresh3DViews(); }; - - // var loader = new ColladaLoader2(); - // loader.options.convertUpAxis = true; - var thatURI = uri; + var basePath = uri.substring(0, uri.lastIndexOf('/')); var thatSubmesh = submesh; - var thatCenterSubmesh = centerSubmesh; var that = this; loader.load( @@ -11270,8 +11362,13 @@ GZ3D.Scene.prototype.loadCollada = function( dae = collada.scene; dae.updateMatrix(); that.prepareColladaMesh(dae); - dae = dae.clone(); that.useColladaSubMesh(dae, thatSubmesh, centerSubmesh); + that.preparePBRMaterials(basePath, collada); + + // updating ColladaLoader to be able to load model specs v1.4.1 introduced a change in rotations + // this compensates for the difference in rotation + // automatic conversion of up-axis as claimed by ColladaLoader doesn't seem to work in our case + dae.quaternion.premultiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), Math.PI / 2)); dae.name = uri; callback(dae); diff --git a/gz3d/src/gz3d-animated-models.js b/gz3d/src/gz3d-animated-models.js index 20c5870..4259859 100644 --- a/gz3d/src/gz3d-animated-models.js +++ b/gz3d/src/gz3d-animated-models.js @@ -4,13 +4,7 @@ GZ3D.AnimatedModel = function(scene) { }; GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { - this.loader = new THREE.ColladaLoader(); - this.loader.textureLoadedCallback = () => { - this.scene.refresh3DViews(); - }; - // Helper function to enable 'skinning' property so three.js treats meshes as deformable - var enableSkinning = function(skinnedMesh) { var materials = skinnedMesh.material.materials; if (materials !== null && materials !== undefined) { @@ -35,16 +29,18 @@ GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { element.totalSize = 0; element.done = false; GZ3D.assetProgressData.assets.push(element); - var scene = this.scene; - this.loader.load( + + this.scene.loadCollada( element.url, - function(collada) { + null, + null, + (dae) => { var modelParent = new THREE.Object3D(); modelParent.name = modelName + '_animated'; var linkParent = new THREE.Object3D(); // Set gray, phong-shaded material for loaded model - collada.scene.traverse(function(child) { + dae.traverse(function(child) { if (child instanceof THREE.Mesh) { var applyDefaultMaterial = true; @@ -70,13 +66,13 @@ GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { }); // Enable skinning for all child meshes - collada.scene.traverse(function(child) { + dae.traverse(function(child) { if (child instanceof THREE.SkinnedMesh) { enableSkinning(child); } }); - linkParent.add(collada.scene); + linkParent.add(dae); // Hide model coordinate frames for the time being; remove as soon as position offset and rotation axis issues are fixed /*var collada_scene_axes = new THREE.AxisHelper(2); @@ -113,13 +109,13 @@ GZ3D.AnimatedModel.prototype.loadAnimatedModel = function(modelName) { return boneList; }; - var boneList = getBoneList(collada.scene); + var boneList = getBoneList(dae); var boneHash = {}; for (var k = 0; k < boneList.length; k++) { boneHash[boneList[k].name] = boneList[k]; } // Skeleton visualization helper class - var helper = new THREE.SkeletonHelper(collada.scene); + var helper = new THREE.SkeletonHelper(dae); boneHash['Skeleton_Visual_Helper'] = helper; modelParent.userData = boneHash; diff --git a/gz3d/src/gzautoalignmodel.js b/gz3d/src/gzautoalignmodel.js index afbb98f..2344d31 100644 --- a/gz3d/src/gzautoalignmodel.js +++ b/gz3d/src/gzautoalignmodel.js @@ -439,8 +439,10 @@ GZ3D.AutoAlignModel.prototype.alignToObjects = function(position) { snap2bbox.setFromObject(snap2obj); if (Math.abs(snap2bbox.min.x) !== Infinity) { if (i === 0) { - var s = bbox.getSize(); - var s2 = snap2bbox.getSize(); + var s = new THREE.Vector3(); + bbox.getSize(s); + var s2 = new THREE.Vector3(); + snap2bbox.getSize(s2); if ( Math.abs(s.x - s2.x) > 0.01 || Math.abs(s.y - s2.y) > 0.01 @@ -653,7 +655,8 @@ GZ3D.AutoAlignModel.prototype.alignOnShape = function(position, hitDesc) { return; } - var q = hitDesc.object.getWorldQuaternion(); + var q = new THREE.Quaternion(); + hitDesc.object.getWorldQuaternion(q); var abv = new THREE.Vector3(); var acv = new THREE.Vector3(); diff --git a/gz3d/src/gzbloomShader.js b/gz3d/src/gzbloomShader.js index a83d450..adccff1 100644 --- a/gz3d/src/gzbloomShader.js +++ b/gz3d/src/gzbloomShader.js @@ -204,7 +204,8 @@ GZ3D.BloomShader.prototype = Object.assign( this.highPassUniforms['tDiffuse'].value = readBuffer.texture; this.highPassUniforms['luminosityThreshold'].value = this.threshold; this.quad.material = this.materialHighPassFilter; - renderer.render(this.scene, this.camera, this.renderTargetBright, true); + renderer.setRenderTarget(this.renderTargetBright); + renderer.render(this.scene, this.camera); // 2. Blur All the mips progressively var inputRenderTarget = this.renderTargetBright; @@ -218,12 +219,9 @@ GZ3D.BloomShader.prototype = Object.assign( this.separableBlurMaterials[i].uniforms['direction'].value = GZ3D.BloomShader.BlurDirectionX; - renderer.render( - this.scene, - this.camera, - this.renderTargetsHorizontal[i], - true - ); + renderer.clear(); + renderer.setRenderTarget(this.renderTargetsHorizontal[i]); + renderer.render(this.scene, this.camera); this.separableBlurMaterials[i].uniforms[ 'colorTexture' @@ -232,12 +230,9 @@ GZ3D.BloomShader.prototype = Object.assign( this.separableBlurMaterials[i].uniforms['direction'].value = GZ3D.BloomShader.BlurDirectionY; - renderer.render( - this.scene, - this.camera, - this.renderTargetsVertical[i], - true - ); + renderer.clear(); + renderer.setRenderTarget(this.renderTargetsVertical[i]); + renderer.render(this.scene, this.camera); inputRenderTarget = this.renderTargetsVertical[i]; } @@ -249,12 +244,9 @@ GZ3D.BloomShader.prototype = Object.assign( this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors; - renderer.render( - this.scene, - this.camera, - this.renderTargetsHorizontal[0], - true - ); + renderer.clear(); + renderer.setRenderTarget(this.renderTargetsHorizontal[0]); + renderer.render(this.scene, this.camera); // Blend it additively over the input texture this.quad.material = this.materialCopy; @@ -265,8 +257,9 @@ GZ3D.BloomShader.prototype = Object.assign( if (maskActive) { renderer.context.enable(renderer.context.STENCIL_TEST); } - - renderer.render(this.scene, this.camera, readBuffer, false); + + renderer.setRenderTarget(readBuffer); + renderer.render(this.scene, this.camera); renderer.setClearColor(this.oldClearColor, this.oldClearAlpha); renderer.autoClear = oldAutoClear; diff --git a/gz3d/src/gzcomposer.js b/gz3d/src/gzcomposer.js index a5bb2c3..c61c602 100644 --- a/gz3d/src/gzcomposer.js +++ b/gz3d/src/gzcomposer.js @@ -965,7 +965,9 @@ GZ3D.Composer.prototype.render = function(view) { this.scene.background = null; // Some effects should be disabled during depth buffer rendering this.lensFlare.visible = false; this.scene.overrideMaterial = view.depthMaterial; - view.renderer.render(this.scene, camera, view.depthRenderTarget, true); // Render to depth buffer now! + view.renderer.clear(); + view.renderer.setRenderTarget(view.depthRenderTarget); + view.renderer.render(this.scene, camera); // Render to depth buffer now! this.scene.overrideMaterial = null; } @@ -1201,50 +1203,53 @@ GZ3D.Composer.prototype.buildSkin = function(skin) { skin.initialized = true; var parent = that.scene.getObjectByName(skin.parentObject, true); if (parent) { - var loader = new THREE.ColladaLoader(); - - loader.load(GZ3D.assetsPath + '/' + skin.mesh, function(collada) { - var dae = collada.scene; - var mapToMesh = that.scene.getObjectByName(skin.mapTo); - - if (skin.scale) - dae.scale.copy(new THREE.Vector3(skin.scale, skin.scale, skin.scale)); - - parent.add(dae); - that.gz3dScene.refresh3DViews(); - - dae.traverse(function(object) { - object._isPartOfTheSkin = true; - }); - - var skinBoneMap = []; - var skinnedObject = { - skinBoneMap: skinBoneMap, - definition: skin, - skinMesh: dae, - mapToMesh: mapToMesh, - parentMesh: parent - }; - - that.skinnedObjects.push(skinnedObject); - - dae._skinnedObject = skinnedObject; - parent._skinnedObject = skinnedObject; - mapToMesh._skinnedObject = skinnedObject; - - dae.traverse(function(bone) { - if (bone instanceof THREE.Bone) { - var r = mapToMesh.getObjectByName(skin.bonePrefix + bone.name); - if (r) { - skinBoneMap.push({ joint: r, bone: bone }); - that.setSkinVisibility(skinnedObject, skin.visible); + var uri = GZ3D.assetsPath + '/' + skin.mesh; + that.gz3dScene.loadCollada( + uri, + null, + null, + (dae) => { + var mapToMesh = that.scene.getObjectByName(skin.mapTo); + + if (skin.scale) + dae.scale.copy(new THREE.Vector3(skin.scale, skin.scale, skin.scale)); + + parent.add(dae); + that.gz3dScene.refresh3DViews(); - r._skinnedObject = skinnedObject; - bone._skinnedObject = skinnedObject; + dae.traverse(function(object) { + object._isPartOfTheSkin = true; + }); + + var skinBoneMap = []; + var skinnedObject = { + skinBoneMap: skinBoneMap, + definition: skin, + skinMesh: dae, + mapToMesh: mapToMesh, + parentMesh: parent + }; + + that.skinnedObjects.push(skinnedObject); + + dae._skinnedObject = skinnedObject; + parent._skinnedObject = skinnedObject; + mapToMesh._skinnedObject = skinnedObject; + + dae.traverse(function(bone) { + if (bone instanceof THREE.Bone) { + var r = mapToMesh.getObjectByName(skin.bonePrefix + bone.name); + if (r) { + skinBoneMap.push({ joint: r, bone: bone }); + that.setSkinVisibility(skinnedObject, skin.visible); + + r._skinnedObject = skinnedObject; + bone._skinnedObject = skinnedObject; + } } - } - }); - }); + }); + } + ); } } }; @@ -1261,11 +1266,9 @@ GZ3D.Composer.prototype.buildSkins = function() { if (!this.skinnedObjects) this.skinnedObjects = []; // Skins created from the .ini file of the experiment - if (cs.skins) cs.skins.forEach(skin => that.buildSkin(skin)); // Skins created dynamically from the frontend - if (this.skins) this.skins.forEach(skin => that.buildSkin(skin)); this.skinsInitialized = true; @@ -1292,7 +1295,8 @@ GZ3D.Composer.prototype.updateSkin = function() { var invM = new THREE.Matrix4(); invM.getInverse(bone.parent.matrixWorld); - var p = joint.getWorldPosition(); + var p = new THREE.Vector3(); + joint.getWorldPosition(p); var jM = new THREE.Matrix4(); var bp = new THREE.Vector3(), diff --git a/gz3d/src/gziface.js b/gz3d/src/gziface.js index 47707a5..f28470d 100644 --- a/gz3d/src/gziface.js +++ b/gz3d/src/gziface.js @@ -1465,7 +1465,7 @@ GZ3D.GZIface.prototype.createGeom = function( // HBP Change (Luc): we assume that all requested collada files are // are web-compliant - if (modelUri.indexOf('.dae') !== -1 || modelUri.indexOf('.DAE') !== -1) { + if (modelUri.substr(-4).toLowerCase() === '.dae') { var materialName = parent.name + '::' + element.url; that.scene.loadMesh( diff --git a/gz3d/src/gzlabelmanager.js b/gz3d/src/gzlabelmanager.js index 7647921..d4eb3e4 100644 --- a/gz3d/src/gzlabelmanager.js +++ b/gz3d/src/gzlabelmanager.js @@ -288,7 +288,7 @@ GZ3D.LabelManager.prototype.createLineLabel = function(parent) { linewidth: 3 }); var line = new THREE.Line(lineGeometry, lineMaterial); - lineGeometry.computeLineDistances(); + line.computeLineDistances(); this.scene.scene.add(line); diff --git a/gz3d/src/gzmanipulator.js b/gz3d/src/gzmanipulator.js index fc1088f..afc47d4 100644 --- a/gz3d/src/gzmanipulator.js +++ b/gz3d/src/gzmanipulator.js @@ -1360,9 +1360,13 @@ GZ3D.Manipulator = function(gz3dScene, mobile) { } }; + let worldPose = new THREE.Vector3(); + let worldRotation = new THREE.Quaternion(); + currentObject.getWorldPosition(worldPose); + currentObject.getWorldQuaternion(worldRotation); var objectWorldPose = { - pos: currentObject.getWorldPosition(), - rot: currentObject.getWorldQuaternion() + pos: worldPose, + rot: worldRotation }; var mouseDistance = getMouseMoveDistance( diff --git a/gz3d/src/gzmultiview.js b/gz3d/src/gzmultiview.js index a47d8b4..6ed99d2 100644 --- a/gz3d/src/gzmultiview.js +++ b/gz3d/src/gzmultiview.js @@ -370,6 +370,7 @@ GZ3D.MultiView.prototype.setShadowMaps = function(enabled) { GZ3D.MultiView.prototype.clearRenderTargets = function(target) { this.views.forEach(function(view, index, array) { - view.renderer.clearTarget(target); + view.renderer.setRenderTarget(target); + view.renderer.clear(); }); }; diff --git a/gz3d/src/gzscene.js b/gz3d/src/gzscene.js index dff1dc7..492f1db 100644 --- a/gz3d/src/gzscene.js +++ b/gz3d/src/gzscene.js @@ -877,6 +877,7 @@ GZ3D.Scene.prototype.setPose = function(model, position, orientation) { model.quaternion.x = orientation.x; model.quaternion.y = orientation.y; model.quaternion.z = orientation.z; + this.refresh3DViews(); this.updateBoundingBox(model); }; @@ -1713,6 +1714,101 @@ GZ3D.Scene.prototype.loadMesh = function( } }; +GZ3D.Scene.prototype.preparePBRMaterials = function(basePath, collada) { + var libEffects = collada.library.effects; + var libMaterials = collada.library.materials; + var libImages = collada.library.images; + + for (const materialKey in libMaterials) { + var material = libMaterials[materialKey]; + var effect = libEffects[material.url]; + + function getTexturePath(textureObject) { + var sampler = effect.profile.samplers[textureObject.id]; + var surface = effect.profile.surfaces[sampler.source]; + + if (sampler !== undefined && surface !== null) { + var img = libImages[surface.init_from]; + + return basePath + '/' + img.build; + } + } + + var parameters = effect.profile.technique.parameters; + var parameter; + var pbrMaterial = null; + + var pbrKeyToThreeJSMap = { + Base_Color: 'map', + Metallic: 'metalnessMap', + Roughness: 'roughnessMap', + Mixed_AO: 'aoMap', + Emissive: 'emissiveMap', + Normal: 'normalMap', + Height: 'displacementMap' + }; + + for (var key in parameters) { + parameter = parameters[key]; + if (parameter.texture) { + var texturePath = getTexturePath(parameter.texture); + + if ( + texturePath && + (texturePath.indexOf('PBR_') >= 0 || + texturePath.indexOf('PBRFULL_') >= 0) + ) { + for (var k in pbrKeyToThreeJSMap) { + if (texturePath.indexOf(k) >= 0) { + if (pbrMaterial === null) { + pbrMaterial = {}; + } + + pbrMaterial[pbrKeyToThreeJSMap[k]] = texturePath; + + if ( + texturePath.indexOf('PBRFULL_') >= 0 && + k === 'Base_Color' + ) { + // If the prefix is PBRFULL it means that all the PBR textures are present + // but that only the basic color map have been linked to the dae. + + var allpbrkeywords = [ + 'Metallic', + 'Mixed_AO', + 'Roughness', + 'Normal', + 'Roughness' + ]; + + for (var pbri in allpbrkeywords) { + var pbrk = allpbrkeywords[pbri]; + var path = texturePath; + + path = path.replace('Base_Color', pbrk); + if (pbrk === 'Normal') { + // Normal map must be png. In case the Base_Color is a jpg, + // change extension to png + + path = path.replace('.jpg', '.png'); + path = path.replace('.jpeg', '.png'); + } + + pbrMaterial[pbrKeyToThreeJSMap[pbrk]] = path; + } + } + } + } + } + } + } + + if (pbrMaterial !== null) { + material.build.pbrMaterialDescription = pbrMaterial; // If PBR material has been found, store it for future usage + } + } +} + /** * Load collada file * @param {string} uri @@ -1728,7 +1824,6 @@ GZ3D.Scene.prototype.loadCollada = function( progressCallback ) { var dae; - var mesh = null; var cachedModel = this.cachedModels[uri]; if (cachedModel && cachedModel.referenceObject) { @@ -1742,12 +1837,8 @@ GZ3D.Scene.prototype.loadCollada = function( loader.textureLoadedCallback = () => { this.refresh3DViews(); }; - - // var loader = new ColladaLoader2(); - // loader.options.convertUpAxis = true; - var thatURI = uri; + var basePath = uri.substring(0, uri.lastIndexOf('/')); var thatSubmesh = submesh; - var thatCenterSubmesh = centerSubmesh; var that = this; loader.load( @@ -1762,8 +1853,13 @@ GZ3D.Scene.prototype.loadCollada = function( dae = collada.scene; dae.updateMatrix(); that.prepareColladaMesh(dae); - dae = dae.clone(); that.useColladaSubMesh(dae, thatSubmesh, centerSubmesh); + that.preparePBRMaterials(basePath, collada); + + // updating ColladaLoader to be able to load model specs v1.4.1 introduced a change in rotations + // this compensates for the difference in rotation + // automatic conversion of up-axis as claimed by ColladaLoader doesn't seem to work in our case + dae.quaternion.premultiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), Math.PI / 2)); dae.name = uri; callback(dae); -- GitLab