From 7abc6efc93fcbf1564b0a760841d663a309259cf Mon Sep 17 00:00:00 2001 From: kovacsv Date: Wed, 27 Oct 2021 08:25:47 +0200 Subject: [PATCH] Import all models as hierarchical model, but put all the meshes under the root node. --- source/export/exporter3dm.js | 7 +- source/export/exportergltf.js | 23 +++-- source/export/exporterobj.js | 10 +- source/import/importer3dm.js | 12 +-- source/import/importer3ds.js | 3 +- source/import/importergltf.js | 30 +++--- source/import/importerifc.js | 2 +- source/import/importerobj.js | 42 ++++----- source/import/importeroff.js | 12 +-- source/import/importerply.js | 2 +- source/import/importerstl.js | 2 +- source/import/importerthree.js | 2 +- source/model/model.js | 60 +++++++----- source/model/modelutils.js | 13 ++- source/model/node.js | 5 + source/threejs/threeconverter.js | 24 +---- test/tests/exporter_test.js | 38 ++++---- test/tests/model_test.js | 151 ++++------------------------- test/tests/modelutils_test.js | 8 +- test/utils/testutils.js | 157 +++++++++++++++++++++++++++---- website/o3dv/js/navigator.js | 9 +- 21 files changed, 305 insertions(+), 307 deletions(-) diff --git a/source/export/exporter3dm.js b/source/export/exporter3dm.js index 77bb1c9..e7d59d6 100644 --- a/source/export/exporter3dm.js +++ b/source/export/exporter3dm.js @@ -10,7 +10,7 @@ OV.Exporter3dm = class extends OV.ExporterBase { return format === OV.FileFormat.Binary && extension === '3dm'; } - + ExportContent (model, format, files, onFinish) { if (this.rhino === null) { @@ -43,8 +43,7 @@ OV.Exporter3dm = class extends OV.ExporterBase files.push (rhinoFile); let rhinoDoc = new this.rhino.File3dm (); - for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) { - let mesh = model.GetMesh (meshIndex); + model.EnumerateTransformedMeshInstances ((mesh) => { let meshBuffer = OV.ConvertMeshToMeshBuffer (mesh); for (let primitiveIndex = 0; primitiveIndex < meshBuffer.PrimitiveCount (); primitiveIndex++) { let primitive = meshBuffer.GetPrimitive (primitiveIndex); @@ -87,7 +86,7 @@ OV.Exporter3dm = class extends OV.ExporterBase rhinoAttributes.materialIndex = rhinoMaterialIndex; rhinoDoc.objects ().add (rhinoMesh, rhinoAttributes); } - } + }); let writeOptions = new this.rhino.File3dmWriteOptions (); writeOptions.version = 6; diff --git a/source/export/exportergltf.js b/source/export/exportergltf.js index 0f534ec..12c32ca 100644 --- a/source/export/exportergltf.js +++ b/source/export/exportergltf.js @@ -19,7 +19,7 @@ OV.ExporterGltf = class extends OV.ExporterBase { return (format === OV.FileFormat.Text && extension === 'gltf') || (format === OV.FileFormat.Binary && extension === 'glb'); } - + ExportContent (model, format, files, onFinish) { if (format === OV.FileFormat.Text) { @@ -56,7 +56,7 @@ OV.ExporterGltf = class extends OV.ExporterBase textureIndex = mainJson.textures.length; fileNameToIndex[fileName] = textureIndex; - + mainJson.images.push ({ uri : fileName }); @@ -68,7 +68,7 @@ OV.ExporterGltf = class extends OV.ExporterBase }); gltfFile.SetTextContent (JSON.stringify (mainJson, null, 4)); - binFile.SetBufferContent (mainBuffer); + binFile.SetBufferContent (mainBuffer); } ExportBinaryContent (model, files) @@ -88,7 +88,7 @@ OV.ExporterGltf = class extends OV.ExporterBase writer.WriteUnsignedCharacter8 (char); } } - + let glbFile = new OV.ExportedFile ('model.glb'); files.push (glbFile); @@ -144,7 +144,7 @@ OV.ExporterGltf = class extends OV.ExporterBase let glbSize = 12 + 8 + mainJsonBufferAlignedLength + 8 + mainBinaryBufferAlignedLength; let glbWriter = new OV.BinaryWriter (glbSize, true); - + glbWriter.WriteUnsignedInteger32 (0x46546C67); glbWriter.WriteUnsignedInteger32 (2); glbWriter.WriteUnsignedInteger32 (glbSize); @@ -171,8 +171,7 @@ OV.ExporterGltf = class extends OV.ExporterBase { let meshDataArr = []; - for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) { - let mesh = model.GetMesh (meshIndex); + model.EnumerateTransformedMeshInstances ((mesh) => { let buffer = OV.ConvertMeshToMeshBuffer (mesh); meshDataArr.push ({ name : mesh.GetName (), @@ -180,7 +179,7 @@ OV.ExporterGltf = class extends OV.ExporterBase offsets : [], sizes : [] }); - } + }); return meshDataArr; } @@ -294,7 +293,7 @@ OV.ExporterGltf = class extends OV.ExporterBase mode : 4, material : primitive.material }; - + let bounds = primitive.GetBounds (); mainJson.accessors.push ({ bufferView : bufferViewIndex, @@ -424,18 +423,18 @@ OV.ExporterGltf = class extends OV.ExporterBase } let metallicTexture = GetTextureParams (mainJson, material.metalnessMap, addTexture); if (metallicTexture !== null) { - jsonMaterial.pbrMetallicRoughness.metallicRoughnessTexture = metallicTexture; + jsonMaterial.pbrMetallicRoughness.metallicRoughnessTexture = metallicTexture; } else { jsonMaterial.pbrMetallicRoughness.metallicFactor = material.metalness; jsonMaterial.pbrMetallicRoughness.roughnessFactor = material.roughness; } let normalTexture = GetTextureParams (mainJson, material.normalMap, addTexture); if (normalTexture !== null) { - jsonMaterial.normalTexture = normalTexture; + jsonMaterial.normalTexture = normalTexture; } let emissiveTexture = GetTextureParams (mainJson, material.emissiveMap, addTexture); if (emissiveTexture !== null) { - jsonMaterial.emissiveTexture = emissiveTexture; + jsonMaterial.emissiveTexture = emissiveTexture; } mainJson.materials.push (jsonMaterial); diff --git a/source/export/exporterobj.js b/source/export/exporterobj.js index 8561388..9e4052d 100644 --- a/source/export/exporterobj.js +++ b/source/export/exporterobj.js @@ -9,7 +9,7 @@ OV.ExporterObj = class extends OV.ExporterBase { return format === OV.FileFormat.Text && extension === 'obj'; } - + ExportContent (model, format, files, onFinish) { function WriteTexture (mtlWriter, keyword, texture, files) @@ -59,7 +59,7 @@ OV.ExporterObj = class extends OV.ExporterBase let normalOffset = 0; let uvOffset = 0; let usedMaterialName = null; - model.EnumerateMeshes ((mesh) => { + model.EnumerateTransformedMeshInstances ((mesh) => { objWriter.WriteArrayLine (['g', this.GetExportedMeshName (mesh.GetName ())]); for (let vertexIndex = 0; vertexIndex < mesh.VertexCount (); vertexIndex++) { let vertex = mesh.GetVertex (vertexIndex); @@ -95,7 +95,7 @@ OV.ExporterObj = class extends OV.ExporterBase if (triangle.HasTextureUVs ()) { u0 = triangle.u0 + uvOffset + 1; u1 = triangle.u1 + uvOffset + 1; - u2 = triangle.u2 + uvOffset + 1; + u2 = triangle.u2 + uvOffset + 1; } objWriter.WriteArrayLine (['f', [v0, u0, n0].join ('/'), [v1, u1, n1].join ('/'), [v2, u2, n2].join ('/')]); } @@ -105,11 +105,11 @@ OV.ExporterObj = class extends OV.ExporterBase }); objFile.SetTextContent (objWriter.GetText ()); - onFinish (); + onFinish (); } GetHeaderText () { return '# exported by https://3dviewer.net'; - } + } }; diff --git a/source/import/importer3dm.js b/source/import/importer3dm.js index f5f87a9..a2a1d6c 100644 --- a/source/import/importer3dm.js +++ b/source/import/importer3dm.js @@ -5,7 +5,7 @@ OV.Importer3dm = class extends OV.ImporterBase super (); this.rhino = null; } - + CanImportExtension (extension) { return extension === '3dm'; @@ -101,7 +101,7 @@ OV.Importer3dm = class extends OV.ImporterBase let rhinoObjects = rhinoDoc.objects (); for (let i = 0; i < rhinoObjects.count; i++) { let rhinoObject = rhinoObjects.get (i); - this.ImportRhinoGeometryObject (rhinoDoc, rhinoObject, []); + this.ImportRhinoGeometryObject (rhinoDoc, rhinoObject, []); } } @@ -113,8 +113,8 @@ OV.Importer3dm = class extends OV.ImporterBase let objectType = rhinoGeometry.objectType; if (rhinoAttributes.isInstanceDefinitionObject && rhinoInstanceReferences.length === 0) { return; - } - + } + let rhinoMesh = null; let deleteMesh = false; @@ -145,7 +145,7 @@ OV.Importer3dm = class extends OV.ImporterBase deleteMesh = true; } else if (objectType === this.rhino.ObjectType.InstanceReference) { let parentDefinitionId = rhinoGeometry.parentIdefId; - let instanceDefinition = this.instanceDefinitions[parentDefinitionId]; + let instanceDefinition = this.instanceDefinitions[parentDefinitionId]; if (instanceDefinition !== undefined) { let instanceObjectIds = instanceDefinition.getObjectIds (); for (let i = 0; i < instanceObjectIds.length; i++) { @@ -199,7 +199,7 @@ OV.Importer3dm = class extends OV.ImporterBase let transformation = new OV.Transformation (matrix); OV.TransformMesh (mesh, transformation); } - this.model.AddMesh (mesh); + this.model.AddMeshToRootNode (mesh); } GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences) diff --git a/source/import/importer3ds.js b/source/import/importer3ds.js index 16ee8c6..01d6836 100644 --- a/source/import/importer3ds.js +++ b/source/import/importer3ds.js @@ -293,7 +293,7 @@ OV.Importer3ds = class extends OV.ImporterBase } } - let meshIndex = this.model.AddMesh (mesh); + let meshIndex = this.model.AddMeshToRootNode (mesh); this.meshNameToIndex[mesh.GetName ()] = meshIndex; this.meshTransformations.push (new OV.Matrix (transformation)); } @@ -519,6 +519,7 @@ OV.Importer3ds = class extends OV.ImporterBase let mesh = model.GetMesh (meshIndex); let clonedMesh = OV.CloneMesh (mesh); let clonedMeshIndex = model.AddMeshToIndex (clonedMesh, toIndex); + model.GetRootNode ().AddMeshIndexToIndex (clonedMeshIndex, toIndex); return clonedMeshIndex; } diff --git a/source/import/importergltf.js b/source/import/importergltf.js index ec598f8..8384fa5 100644 --- a/source/import/importergltf.js +++ b/source/import/importergltf.js @@ -78,7 +78,7 @@ OV.GltfNodeTree = class return null; } return matrix; - } + } }; OV.GltfBufferReader = class @@ -139,7 +139,7 @@ OV.GltfBufferReader = class { return this.reader.ReadArrayBuffer (byteLength); } - + GetDataCount () { return this.dataCount; @@ -249,7 +249,7 @@ OV.GltfBufferReader = class return 4; } return 0; - } + } }; OV.GltfExtensions = class @@ -269,7 +269,7 @@ OV.GltfExtensions = class if (extensionsRequired === undefined) { callbacks.onSuccess (); return; - } + } if (this.draco === null && extensionsRequired.indexOf ('KHR_draco_mesh_compression') !== -1) { OV.LoadExternalLibrary ('loaders/draco_decoder.js').then (() => { DracoDecoderModule ().then ((draco) => { @@ -336,7 +336,7 @@ OV.GltfExtensions = class let specularTexture = khrSpecularGlossiness.specularGlossinessTexture; if (specularTexture !== undefined) { material.specularMap = imporTextureFn (specularTexture); - } + } let glossiness = khrSpecularGlossiness.glossinessFactor; if (glossiness !== undefined) { material.shininess = glossiness; @@ -487,7 +487,7 @@ OV.ImporterGltf = class extends OV.ImporterBase { return OV.Direction.Y; } - + ClearContent () { this.bufferContents = null; @@ -626,7 +626,7 @@ OV.ImporterGltf = class extends OV.ImporterBase if (materials !== undefined) { for (let i = 0; i < materials.length; i++) { this.ImportMaterial (gltf, i); - } + } } let nodeTree = this.CollectMeshNodesForScene (gltf, defaultScene); @@ -814,7 +814,7 @@ OV.ImporterGltf = class extends OV.ImporterBase texture.name = textureParams.name; texture.url = textureParams.url; texture.buffer = textureParams.buffer; - + this.gltfExtensions.ProcessTexture (gltfTextureRef, texture); return texture; } @@ -849,7 +849,7 @@ OV.ImporterGltf = class extends OV.ImporterBase scale = node.scale; hasTransformation = true; } - + if (hasTransformation) { matrix.ComposeTRS ( OV.ArrayToCoord3D (translation), @@ -866,7 +866,7 @@ OV.ImporterGltf = class extends OV.ImporterBase } nodeTree.AddNodeMatrix (nodeIndex, matrix); - return matrix; + return matrix; } let gltfNode = gltf.nodes[nodeIndex]; @@ -874,7 +874,7 @@ OV.ImporterGltf = class extends OV.ImporterBase let gltfMesh = gltf.meshes[gltfMeshIndex]; let mesh = new OV.Mesh (); - this.model.AddMesh (mesh); + this.model.AddMeshToRootNode (mesh); if (gltfMesh.name !== undefined) { mesh.SetName (gltfMesh.name); } else if (gltfNode.name !== undefined) { @@ -889,7 +889,7 @@ OV.ImporterGltf = class extends OV.ImporterBase let matrix = GetNodeTransformation (gltf, nodeIndex, nodeTree); let transformation = new OV.Transformation (matrix); OV.TransformMesh (mesh, transformation); - } + } ImportPrimitive (gltf, primitive, mesh) { @@ -963,7 +963,7 @@ OV.ImporterGltf = class extends OV.ImporterBase } reader.EnumerateData ((data) => { vertexIndices.push (data); - }); + }); } else { for (let i = 0; i < mesh.VertexCount (); i++) { vertexIndices.push (i); @@ -1020,7 +1020,7 @@ OV.ImporterGltf = class extends OV.ImporterBase triangle.mat = primitive.material; } mesh.AddTriangle (triangle); - } + } GetReaderFromBufferView (bufferView) { @@ -1075,7 +1075,7 @@ OV.ImporterGltf = class extends OV.ImporterBase if (reader === null) { return null; } - + reader.SetComponentType (componentType); reader.SetDataType (type); reader.SetDataCount (count); diff --git a/source/import/importerifc.js b/source/import/importerifc.js index 3ea0c46..0b8bdff 100644 --- a/source/import/importerifc.js +++ b/source/import/importerifc.js @@ -104,7 +104,7 @@ OV.ImporterIfc = class extends OV.ImporterBase } this.expressIDToMesh[ifcMesh.expressID] = mesh; - this.model.AddMesh (mesh); + this.model.AddMeshToRootNode (mesh); } ImportProperties (modelID) diff --git a/source/import/importerobj.js b/source/import/importerobj.js index 4df68ff..258d1a3 100644 --- a/source/import/importerobj.js +++ b/source/import/importerobj.js @@ -14,18 +14,18 @@ OV.ImporterObj = class extends OV.ImporterBase { return OV.Direction.Y; } - + ClearContent () { this.globalVertices = null; this.globalNormals = null; this.globalUvs = null; - + this.currentMesh = null; this.currentMeshData = null; this.currentMaterial = null; this.currentMaterialIndex = null; - + this.meshNameToMeshData = null; this.materialNameToIndex = null; } @@ -39,12 +39,12 @@ OV.ImporterObj = class extends OV.ImporterBase this.currentMesh = null; this.currentMeshData = null; this.currentMaterial = null; - this.currentMaterialIndex = null; + this.currentMaterialIndex = null; this.meshNameToMeshData = {}; this.materialNameToIndex = {}; } - + ImportContent (fileContent, onFinish) { let textContent = OV.ArrayBufferToUtf8String (fileContent); @@ -55,7 +55,7 @@ OV.ImporterObj = class extends OV.ImporterBase }); onFinish (); } - + ProcessLine (line) { if (line[0] === '#') { @@ -66,7 +66,7 @@ OV.ImporterObj = class extends OV.ImporterBase if (parameters.length === 0) { return; } - + let keyword = parameters[0].toLowerCase (); parameters.shift (); @@ -78,7 +78,7 @@ OV.ImporterObj = class extends OV.ImporterBase return; } } - + AddNewMesh (name) { let meshData = this.meshNameToMeshData[name]; @@ -87,7 +87,7 @@ OV.ImporterObj = class extends OV.ImporterBase if (name !== null) { mesh.SetName (name); } - this.model.AddMesh (mesh); + this.model.AddMeshToRootNode (mesh); meshData = { mesh : mesh, data : { @@ -179,7 +179,7 @@ OV.ImporterObj = class extends OV.ImporterBase if (parameters.length === 0) { return true; } - + let material = new OV.Material (OV.MaterialType.Phong); let materialName = OV.NameFromLine (line, keyword.length, '#'); let materialIndex = this.model.AddMaterial (material); @@ -191,7 +191,7 @@ OV.ImporterObj = class extends OV.ImporterBase if (parameters.length === 0) { return true; } - + let materialName = OV.NameFromLine (line, keyword.length, '#'); let materialIndex = this.materialNameToIndex[materialName]; if (materialIndex !== undefined) { @@ -272,7 +272,7 @@ OV.ImporterObj = class extends OV.ImporterBase return true; } - return false; + return false; } ProcessFace (parameters) @@ -285,7 +285,7 @@ OV.ImporterObj = class extends OV.ImporterBase return count + index; } } - + function GetLocalIndex (globalValueArray, globalToCurrentIndices, globalIndex, valueAdderFunc) { if (isNaN (globalIndex) || globalIndex < 0 || globalIndex >= globalValueArray.length) { @@ -302,32 +302,32 @@ OV.ImporterObj = class extends OV.ImporterBase } return result; } - + function GetLocalVertexIndex (obj, mesh, globalIndex) { return GetLocalIndex (obj.globalVertices, obj.currentMeshData.globalToCurrentVertices, globalIndex, (val) => { return mesh.AddVertex (new OV.Coord3D (val.x, val.y, val.z)); }); } - + function GetLocalNormalIndex (obj, mesh, globalIndex) { return GetLocalIndex (obj.globalNormals, obj.currentMeshData.globalToCurrentNormals, globalIndex, (val) => { return mesh.AddNormal (new OV.Coord3D (val.x, val.y, val.z)); }); } - + function GetLocalUVIndex (obj, mesh, globalIndex) { return GetLocalIndex (obj.globalUvs, obj.currentMeshData.globalToCurrentUvs, globalIndex, (val) => { return mesh.AddTextureUV (new OV.Coord2D (val.x, val.y)); }); - } - + } + let vertices = []; let normals = []; let uvs = []; - + for (let i = 0; i < parameters.length; i++) { let vertexParams = parameters[i].split ('/'); vertices.push (GetRelativeIndex (parseInt (vertexParams[0], 10), this.globalVertices.length)); @@ -338,11 +338,11 @@ OV.ImporterObj = class extends OV.ImporterBase normals.push (GetRelativeIndex (parseInt (vertexParams[2], 10), this.globalNormals.length)); } } - + if (this.currentMesh === null) { this.AddNewMesh (''); } - + for (let i = 0; i < vertices.length - 2; i++) { let v0 = GetLocalVertexIndex (this, this.currentMesh, vertices[0]); let v1 = GetLocalVertexIndex (this, this.currentMesh, vertices[i + 1]); diff --git a/source/import/importeroff.js b/source/import/importeroff.js index f3a191f..3933548 100644 --- a/source/import/importeroff.js +++ b/source/import/importeroff.js @@ -4,7 +4,7 @@ OV.ImporterOff = class extends OV.ImporterBase { super (); } - + CanImportExtension (extension) { return extension === 'off'; @@ -14,7 +14,7 @@ OV.ImporterOff = class extends OV.ImporterBase { return OV.Direction.Y; } - + ClearContent () { this.mesh = null; @@ -24,7 +24,7 @@ OV.ImporterOff = class extends OV.ImporterBase ResetContent () { this.mesh = new OV.Mesh (); - this.model.AddMesh (this.mesh); + this.model.AddMeshToRootNode (this.mesh); this.status = { vertexCount : 0, faceCount : 0, @@ -43,7 +43,7 @@ OV.ImporterOff = class extends OV.ImporterBase }); onFinish (); } - + ProcessLine (line) { if (line[0] === '#') { @@ -54,7 +54,7 @@ OV.ImporterOff = class extends OV.ImporterBase if (parameters.length === 0) { return; } - + if (parameters[0] === 'OFF') { return; } @@ -72,7 +72,7 @@ OV.ImporterOff = class extends OV.ImporterBase this.mesh.AddVertex (new OV.Coord3D ( parseFloat (parameters[0]), parseFloat (parameters[1]), - parseFloat (parameters[2]) + parseFloat (parameters[2]) )); this.status.foundVertex += 1; } diff --git a/source/import/importerply.js b/source/import/importerply.js index e3bc4bc..5d6bb42 100644 --- a/source/import/importerply.js +++ b/source/import/importerply.js @@ -177,7 +177,7 @@ OV.ImporterPly = class extends OV.ImporterBase ResetContent () { this.mesh = new OV.Mesh (); - this.model.AddMesh (this.mesh); + this.model.AddMeshToRootNode (this.mesh); } ImportContent (fileContent, onFinish) diff --git a/source/import/importerstl.js b/source/import/importerstl.js index 31bd4b1..959d713 100644 --- a/source/import/importerstl.js +++ b/source/import/importerstl.js @@ -24,7 +24,7 @@ OV.ImporterStl = class extends OV.ImporterBase ResetContent () { this.mesh = new OV.Mesh (); - this.model.AddMesh (this.mesh); + this.model.AddMeshToRootNode (this.mesh); this.triangle = null; } diff --git a/source/import/importerthree.js b/source/import/importerthree.js index 68a83ff..230fcc8 100644 --- a/source/import/importerthree.js +++ b/source/import/importerthree.js @@ -465,7 +465,7 @@ OV.ImporterThree = class extends OV.ImporterBase OV.FlipMeshTrianglesOrientation (mesh); } } - this.model.AddMesh (mesh); + this.model.AddMeshToRootNode (mesh); child.geometry.dispose (); }); diff --git a/source/model/model.js b/source/model/model.js index 7c7f85d..d1e2a2c 100644 --- a/source/model/model.js +++ b/source/model/model.js @@ -23,39 +23,48 @@ OV.Model = class extends OV.ModelObject3D return this.meshes.length; } + MeshInstanceCount () + { + let count = 0; + this.EnumerateMeshInstances ((meshInstance) => { + count += 1; + }); + return count; + } + VertexCount () { let count = 0; - for (let i = 0; i < this.meshes.length; i++) { - count += this.meshes[i].VertexCount (); - } + this.EnumerateMeshInstances ((meshInstance) => { + count += meshInstance.VertexCount (); + }); return count; } NormalCount () { let count = 0; - for (let i = 0; i < this.meshes.length; i++) { - count += this.meshes[i].NormalCount (); - } + this.EnumerateMeshInstances ((meshInstance) => { + count += meshInstance.NormalCount (); + }); return count; } TextureUVCount () { let count = 0; - for (let i = 0; i < this.meshes.length; i++) { - count += this.meshes[i].TextureUVCount (); - } + this.EnumerateMeshInstances ((meshInstance) => { + count += meshInstance.TextureUVCount (); + }); return count; } TriangleCount () { let count = 0; - for (let i = 0; i < this.meshes.length; i++) { - count += this.meshes[i].TriangleCount (); - } + this.EnumerateMeshInstances ((meshInstance) => { + count += meshInstance.TriangleCount (); + }); return count; } @@ -127,11 +136,10 @@ OV.Model = class extends OV.ModelObject3D if (foundNode === null) { return null; } - // TODO: check it when every model is hierarchical - // const nodeMeshIndices = foundNode.GetMeshIndices (); - // if (nodeMeshIndices.indexOf (instanceId.meshIndex) === -1) { - // return null; - // } + const nodeMeshIndices = foundNode.GetMeshIndices (); + if (nodeMeshIndices.indexOf (instanceId.meshIndex) === -1) { + return null; + } let foundMesh = this.GetMesh (instanceId.meshIndex); return new OV.MeshInstance (foundNode, foundMesh); } @@ -164,22 +172,22 @@ OV.Model = class extends OV.ModelObject3D EnumerateVertices (onVertex) { - for (const mesh of this.meshes) { - mesh.EnumerateVertices (onVertex); - } + this.EnumerateMeshInstances ((meshInstance) => { + meshInstance.EnumerateVertices (onVertex); + }); } EnumerateTriangleVertexIndices (onTriangleVertexIndices) { - for (const mesh of this.meshes) { - mesh.EnumerateTriangleVertexIndices (onTriangleVertexIndices); - } + this.EnumerateMeshInstances ((meshInstance) => { + meshInstance.EnumerateTriangleVertexIndices (onTriangleVertexIndices); + }); } EnumerateTriangleVertices (onTriangleVertices) { - for (const mesh of this.meshes) { - mesh.EnumerateTriangleVertices (onTriangleVertices); - } + this.EnumerateMeshInstances ((meshInstance) => { + meshInstance.EnumerateTriangleVertices (onTriangleVertices); + }); } }; diff --git a/source/model/modelutils.js b/source/model/modelutils.js index fe801f5..6cce100 100644 --- a/source/model/modelutils.js +++ b/source/model/modelutils.js @@ -87,18 +87,17 @@ OV.CloneMesh = function (mesh) OV.EnumerateModelVerticesAndTriangles = function (model, callbacks) { - model.EnumerateMeshes ((mesh) => { - for (let vertexIndex = 0; vertexIndex < mesh.VertexCount (); vertexIndex++) { - let vertex = mesh.GetVertex (vertexIndex); + model.EnumerateMeshInstances ((meshInstance) => { + meshInstance.EnumerateVertices ((vertex) => { callbacks.onVertex (vertex.x, vertex.y, vertex.z); - } + }); }); let vertexOffset = 0; - model.EnumerateMeshes ((mesh) => { - mesh.EnumerateTriangleVertexIndices ((v0, v1, v2) => { + model.EnumerateMeshInstances ((meshInstance) => { + meshInstance.EnumerateTriangleVertexIndices ((v0, v1, v2) => { callbacks.onTriangle (v0 + vertexOffset, v1 + vertexOffset, v2 + vertexOffset); }); - vertexOffset += mesh.VertexCount (); + vertexOffset += meshInstance.VertexCount (); }); }; diff --git a/source/model/node.js b/source/model/node.js index 3a031bb..fec655e 100644 --- a/source/model/node.js +++ b/source/model/node.js @@ -117,6 +117,11 @@ OV.Node = class return this.meshIndices.length - 1; } + AddMeshIndexToIndex (index, toIndex) + { + this.meshIndices.splice (toIndex, 0, index); + } + MeshIndexCount () { return this.meshIndices.length; diff --git a/source/threejs/threeconverter.js b/source/threejs/threeconverter.js index d562096..bb8cf24 100644 --- a/source/threejs/threeconverter.js +++ b/source/threejs/threeconverter.js @@ -318,22 +318,6 @@ OV.ConvertModelToThreeObject = function (model, params, output, callbacks) }); } - function ConvertMeshList (threeObject, model, modelThreeMaterials, stateHandler) - { - OV.RunTasksBatch (model.MeshCount (), 100, { - runTask : (firstIndex, lastIndex, ready) => { - for (let meshIndex = firstIndex; meshIndex <= lastIndex; meshIndex++) { - let meshInstanceId = new OV.MeshInstanceId (model.GetRootNode ().GetId (), meshIndex); - ConvertMesh (threeObject, model, meshInstanceId, modelThreeMaterials); - } - ready (); - }, - onReady : () => { - stateHandler.OnModelLoaded (threeObject); - } - }); - } - let stateHandler = new OV.ThreeConversionStateHandler (callbacks); let modelThreeMaterials = []; @@ -343,11 +327,5 @@ OV.ConvertModelToThreeObject = function (model, params, output, callbacks) } let threeObject = new THREE.Object3D (); - let rootNode = model.GetRootNode (); - if (!rootNode.IsEmpty ()) { - ConvertNodeHierarchy (threeObject, model, modelThreeMaterials, stateHandler); - } else { - // TODO: remove - ConvertMeshList (threeObject, model, modelThreeMaterials, stateHandler); - } + ConvertNodeHierarchy (threeObject, model, modelThreeMaterials, stateHandler); }; diff --git a/test/tests/exporter_test.js b/test/tests/exporter_test.js index 73dfa03..c57220e 100644 --- a/test/tests/exporter_test.js +++ b/test/tests/exporter_test.js @@ -38,7 +38,7 @@ function CreateTestModel () let triangle1 = new OV.Triangle (0, 1, 2); triangle1.mat = 0; mesh1.AddTriangle (triangle1); - model.AddMesh (mesh1); + model.AddMeshToRootNode (mesh1); let mesh2 = new OV.Mesh (); mesh2.SetName ('TestMesh2'); @@ -56,8 +56,8 @@ function CreateTestModel () mesh2.AddTriangle (triangle2); mesh2.AddTriangle (triangle3); mesh2.AddTriangle (triangle4); - model.AddMesh (mesh2); - + model.AddMeshToRootNode (mesh2); + OV.FinalizeModel (model, null); return model; } @@ -138,19 +138,19 @@ describe ('Exporter', function () { 'f 4//4 8//4 6//4', '' ].join ('\n')); - + let textureFile1 = result[2]; assert.strictEqual (textureFile1.GetName (), 'texture1.png'); assert.strictEqual (textureFile1.GetBufferContent ().byteLength, 1); - + let textureFile2 = result[3]; assert.strictEqual (textureFile2.GetName (), 'texture2.png'); assert.strictEqual (textureFile2.GetBufferContent ().byteLength, 2); - + let textureFile3 = result[4]; assert.strictEqual (textureFile3.GetName (), 'texture3.png'); assert.strictEqual (textureFile3.GetBufferContent ().byteLength, 3); - + done (); }); }); @@ -197,7 +197,7 @@ describe ('Exporter', function () { '' ].join ('\n')); - done (); + done (); }); }); @@ -209,7 +209,7 @@ describe ('Exporter', function () { let stlFile = result[0]; assert.strictEqual (stlFile.GetName (), 'model.stl'); assert.strictEqual (stlFile.GetBufferContent ().byteLength, 284); - + let contentBuffer = stlFile.GetBufferContent (); let importer = new OV.ImporterStl (); importer.Import (stlFile.GetName (), 'stl', contentBuffer, { @@ -223,7 +223,7 @@ describe ('Exporter', function () { done (); } }); - + done (); }); }); @@ -253,7 +253,7 @@ describe ('Exporter', function () { '3 3 7 5', '' ].join ('\n')); - + done (); }); }); @@ -290,7 +290,7 @@ describe ('Exporter', function () { '3 3 7 5', '' ].join ('\n')); - + done (); }); }); @@ -303,7 +303,7 @@ describe ('Exporter', function () { let plyFile = result[0]; assert.strictEqual (plyFile.GetName (), 'model.ply'); assert.strictEqual (plyFile.GetBufferContent ().byteLength, 315); - + let contentBuffer = plyFile.GetBufferContent (); let importer = new OV.ImporterPly (); importer.Import (plyFile.GetName (), 'ply', contentBuffer, { @@ -316,7 +316,7 @@ describe ('Exporter', function () { assert.strictEqual (importedModel.TriangleCount (), 4); done (); } - }); + }); }); }); @@ -324,16 +324,16 @@ describe ('Exporter', function () { let model = CreateTestModel (); Export (model, OV.FileFormat.Text, 'gltf', function (result) { assert.strictEqual (result.length, 3); - + let gltfFile = result[0]; let binFile = result[1]; let textureFile = result[2]; assert.strictEqual (gltfFile.GetName (), 'model.gltf'); assert.strictEqual (binFile.GetName (), 'model.bin'); - + assert.strictEqual (textureFile.GetName (), 'texture1.png'); assert.strictEqual (textureFile.GetBufferContent ().byteLength, 1); - + let contentBuffer = gltfFile.GetBufferContent (); let importer = new OV.ImporterGltf (); importer.Import (gltfFile.GetName (), 'gltf', contentBuffer, { @@ -360,7 +360,7 @@ describe ('Exporter', function () { assert.strictEqual (importedModel.TriangleCount (), 4); done (); } - }); + }); }); }); @@ -397,5 +397,5 @@ describe ('Exporter', function () { } }); }); - }); + }); }); diff --git a/test/tests/model_test.js b/test/tests/model_test.js index dee16c3..0986130 100644 --- a/test/tests/model_test.js +++ b/test/tests/model_test.js @@ -1,4 +1,5 @@ var assert = require ('assert'); +var testUtils = require ('../utils/testutils.js'); describe ('Model', function () { it ('Default Initialization', function () { @@ -60,7 +61,7 @@ describe ('Model', function () { mesh.AddTriangle (new OV.Triangle (0, 1, 2)); mesh.AddTriangle (new OV.Triangle (0, 1, 2)); mesh.AddTriangle (new OV.Triangle (0, 1, 2)); - model.AddMesh (mesh); + model.AddMeshToRootNode (mesh); assert.strictEqual (model.VertexCount (), 3); assert.strictEqual (model.NormalCount (), 2); assert.strictEqual (model.TextureUVCount (), 1); @@ -75,14 +76,14 @@ describe ('Model', function () { mesh1.AddVertex (new OV.Coord3D (1.0, 0.0, 0.0)); mesh1.AddVertex (new OV.Coord3D (1.0, 1.0, 0.0)); mesh1.AddTriangle (new OV.Triangle (0, 1, 2)); - model.AddMesh (mesh1); + model.AddMeshToRootNode (mesh1); let mesh2 = new OV.Mesh (); mesh2.AddVertex (new OV.Coord3D (0.0, 0.0, 1.0)); mesh2.AddVertex (new OV.Coord3D (1.0, 0.0, 1.0)); mesh2.AddVertex (new OV.Coord3D (1.0, 1.0, 1.0)); mesh2.AddTriangle (new OV.Triangle (0, 1, 2)); - model.AddMesh (mesh2); + model.AddMeshToRootNode (mesh2); assert.strictEqual (model.MeshCount (), 2); assert.strictEqual (model.VertexCount (), 6); @@ -244,129 +245,6 @@ describe ('Color Conversion', function () { }); }); -function CreateHierarchicalModel () -{ - /* - + - + Node 1 - + Node 3 - Mesh 5 - Mesh 6 - Mesh 7 - + Node 4 - Mesh 7 - Mesh 3 - Mesh 4 - + Node 2 - Mesh 1 - Mesh 2 - */ - - let model = new OV.Model (); - let root = model.GetRootNode (); - - let node1 = new OV.Node (); - node1.SetName ('Node 1'); - - let node2 = new OV.Node (); - node2.SetName ('Node 2'); - - let node3 = new OV.Node (); - node3.SetName ('Node 3'); - - let node4 = new OV.Node (); - node4.SetName ('Node 4'); - - root.AddChildNode (node1); - root.AddChildNode (node2); - node1.AddChildNode (node3); - node1.AddChildNode (node4); - - let mesh1 = new OV.Mesh (); - mesh1.SetName ('Mesh 1'); - - let mesh2 = new OV.Mesh (); - mesh2.SetName ('Mesh 2'); - - let mesh3 = new OV.Mesh (); - mesh3.SetName ('Mesh 3'); - - let mesh4 = new OV.Mesh (); - mesh4.SetName ('Mesh 4'); - - let mesh5 = new OV.Mesh (); - mesh5.SetName ('Mesh 5'); - - let mesh6 = new OV.Mesh (); - mesh6.SetName ('Mesh 6'); - - let mesh7 = new OV.Mesh (); - mesh7.SetName ('Mesh 7'); - - let mesh1Ind = model.AddMesh (mesh1); - let mesh2Ind = model.AddMesh (mesh2); - let mesh3Ind = model.AddMesh (mesh3); - let mesh4Ind = model.AddMesh (mesh4); - let mesh5Ind = model.AddMesh (mesh5); - let mesh6Ind = model.AddMesh (mesh6); - let mesh7Ind = model.AddMesh (mesh7); - - root.AddMeshIndex (mesh1Ind); - root.AddMeshIndex (mesh2Ind); - node1.AddMeshIndex (mesh3Ind); - node1.AddMeshIndex (mesh4Ind); - node3.AddMeshIndex (mesh5Ind); - node3.AddMeshIndex (mesh6Ind); - node3.AddMeshIndex (mesh7Ind); - node4.AddMeshIndex (mesh7Ind); - - return model; -} - -function CreateTranslatedRotatedCubesModel () -{ - /* - + - + Translated - Cube - + Rotated - + Translated and Rotated - Cube - Cube - */ - - let model = new OV.Model (); - - let mesh = OV.GenerateCuboid (null, 1.0, 1.0, 1.0); - mesh.SetName ('Cube'); - let meshIndex = model.AddMesh (mesh); - - let root = model.GetRootNode (); - root.AddMeshIndex (0); - - let translatedNode = new OV.Node (); - translatedNode.SetName ('Translated'); - translatedNode.SetTransformation (new OV.Transformation (new OV.Matrix ().CreateTranslation (2.0, 0.0, 0.0))); - translatedNode.AddMeshIndex (0); - - let rotatedNode = new OV.Node (); - rotatedNode.SetName ('Rotated'); - - let rotation = OV.QuaternionFromAxisAngle (new OV.Coord3D (0.0, 0.0, 1.0), Math.PI / 2.0); - rotatedNode.SetTransformation (new OV.Transformation (new OV.Matrix ().CreateRotation (0.0, 0.0, 0.7071067811865475, 0.7071067811865476))); - - let translatedRotatedNode = new OV.Node (); - translatedRotatedNode.SetName ('Translated and Rotated'); - translatedRotatedNode.SetTransformation (new OV.Transformation (new OV.Matrix ().CreateTranslation (2.0, 0.0, 0.0))); - translatedRotatedNode.AddMeshIndex (0); - - root.AddChildNode (translatedNode); - root.AddChildNode (rotatedNode); - rotatedNode.AddChildNode (translatedRotatedNode); - - return model; -} - function GetModelTree (model) { function AddNodeToModelTree (model, node, modelTree) @@ -392,7 +270,7 @@ function GetModelTree (model) describe ('Node Hierarchy', function () { it ('Enumerate hierarchy', function () { - let model = CreateHierarchicalModel (); + let model = testUtils.GetHierarchicalModel (); let modelTree = GetModelTree (model); assert.deepStrictEqual (modelTree, { name : '', @@ -424,7 +302,7 @@ describe ('Node Hierarchy', function () { }); it ('Remove mesh', function () { - let model = CreateHierarchicalModel (); + let model = testUtils.GetHierarchicalModel (); model.RemoveMesh (2); let modelTree = GetModelTree (model); assert.deepStrictEqual (modelTree, { @@ -457,7 +335,7 @@ describe ('Node Hierarchy', function () { }); it ('Add mesh to index', function () { - let model = CreateHierarchicalModel (); + let model = testUtils.GetHierarchicalModel (); let mesh = new OV.Mesh (); mesh.SetName ('Mesh 8'); model.AddMeshToIndex (mesh, 3); @@ -492,7 +370,7 @@ describe ('Node Hierarchy', function () { }); it ('Enumerate mesh instances', function () { - let model = CreateTranslatedRotatedCubesModel (); + let model = testUtils.GetTranslatedRotatedCubesModel (); let modelTree = GetModelTree (model); assert.deepStrictEqual (modelTree, { name : '', @@ -539,7 +417,7 @@ describe ('Node Hierarchy', function () { }); it ('Enumerate transformed mesh instances', function () { - let model = CreateTranslatedRotatedCubesModel (); + let model = testUtils.GetTranslatedRotatedCubesModel (); let modelTree = GetModelTree (model); assert.deepStrictEqual (modelTree, { name : '', @@ -584,4 +462,15 @@ describe ('Node Hierarchy', function () { assert (OV.CoordIsEqual3D (boundingBox3.min, new OV.Coord3D (-1.0, 2.0, 0.0))); assert (OV.CoordIsEqual3D (boundingBox3.max, new OV.Coord3D (0.0, 3.0, 1.0))); }); + + it ('Instance counters', function () { + let model = testUtils.GetTranslatedRotatedCubesModel (); + OV.FinalizeModel (model, function () { return new OV.Material (OV.MaterialType.Phong) }); + assert.strictEqual (model.MeshCount (), 1); + assert.strictEqual (model.MeshInstanceCount (), 3); + assert.strictEqual (model.VertexCount (), 8 * 3); + assert.strictEqual (model.NormalCount (), 12 * 3); + assert.strictEqual (model.TextureUVCount (), 0); + assert.strictEqual (model.TriangleCount (), 12 * 3); + }); }); diff --git a/test/tests/modelutils_test.js b/test/tests/modelutils_test.js index 7eadb9c..caea250 100644 --- a/test/tests/modelutils_test.js +++ b/test/tests/modelutils_test.js @@ -28,14 +28,14 @@ describe ('Model Utils', function () { mesh1.AddVertex (new OV.Coord3D (1.0, 0.0, 0.0)); mesh1.AddVertex (new OV.Coord3D (1.0, 1.0, 0.0)); mesh1.AddTriangle (new OV.Triangle (0, 1, 2)); - model.AddMesh (mesh1); + model.AddMeshToRootNode (mesh1); var mesh2 = new OV.Mesh (); mesh2.AddVertex (new OV.Coord3D (0.0, 0.0, 1.0)); mesh2.AddVertex (new OV.Coord3D (1.0, 0.0, 1.0)); mesh2.AddVertex (new OV.Coord3D (1.0, 1.0, 1.0)); mesh2.AddTriangle (new OV.Triangle (0, 1, 2)); - model.AddMesh (mesh2); + model.AddMeshToRootNode (mesh2); OV.FinalizeModel (model, function () { return new OV.Material (OV.MaterialType.Phong); }); @@ -46,6 +46,10 @@ describe ('Model Utils', function () { let mesh2Bounds = OV.GetBoundingBox (model.GetMesh (1)); assert (OV.CoordIsEqual3D (mesh2Bounds.min, new OV.Coord3D (0.0, 0.0, 1.0))); assert (OV.CoordIsEqual3D (mesh2Bounds.max, new OV.Coord3D (1.0, 1.0, 1.0))); + + let modelBounds = OV.GetBoundingBox (model); + assert (OV.CoordIsEqual3D (modelBounds.min, new OV.Coord3D (0.0, 0.0, 0.0))); + assert (OV.CoordIsEqual3D (modelBounds.max, new OV.Coord3D (1.0, 1.0, 1.0))); }); it ('Tetrahedron Topology Calculation', function () { diff --git a/test/utils/testutils.js b/test/utils/testutils.js index e1f285e..5411f51 100644 --- a/test/utils/testutils.js +++ b/test/utils/testutils.js @@ -22,7 +22,7 @@ module.exports = for (i = 0; i < buffer.length; ++i) { uint8Array[i] = buffer[i]; } - return arrayBuffer + return arrayBuffer }, ModelToObject : function (model) @@ -88,7 +88,7 @@ module.exports = mesh.GetTextureUV (triangle.u1).y, mesh.GetTextureUV (triangle.u2).x, mesh.GetTextureUV (triangle.u2).y - ); + ); } meshObj.triangles.push (triangleObj); } @@ -142,11 +142,11 @@ module.exports = let model = new OV.Model (); let cube1 = OV.GenerateCuboid (null, 1.0, 1.0, 1.0); - model.AddMesh (cube1); - + model.AddMeshToRootNode (cube1); + let matrix = new OV.Matrix ().CreateTranslation (1.0, 1.0, 1.0); let cube2 = OV.GenerateCuboid (new OV.GeneratorParams ().SetTransformationMatrix (matrix), 1.0, 1.0, 1.0); - model.AddMesh (cube2); + model.AddMeshToRootNode (cube2); OV.FinalizeModel (model, function () { return new OV.Material (OV.MaterialType.Phong) }); return model; @@ -157,11 +157,11 @@ module.exports = let model = new OV.Model (); let cube1 = OV.GenerateCuboid (null, 1.0, 1.0, 1.0); - model.AddMesh (cube1); - + model.AddMeshToRootNode (cube1); + let matrix = new OV.Matrix ().CreateTranslation (1.0, 0.0, 1.0); let cube2 = OV.GenerateCuboid (new OV.GeneratorParams ().SetTransformationMatrix (matrix), 1.0, 1.0, 1.0); - model.AddMesh (cube2); + model.AddMeshToRootNode (cube2); OV.FinalizeModel (model, function () { return new OV.Material (OV.MaterialType.Phong) }); return model; @@ -172,16 +172,16 @@ module.exports = let model = new OV.Model (); let cube1 = OV.GenerateCuboid (null, 1.0, 1.0, 1.0); - model.AddMesh (cube1); - + model.AddMeshToRootNode (cube1); + let matrix = new OV.Matrix ().CreateTranslation (1.0, 0.0, 0.0); let cube2 = OV.GenerateCuboid (new OV.GeneratorParams ().SetTransformationMatrix (matrix), 1.0, 1.0, 1.0); - model.AddMesh (cube2); + model.AddMeshToRootNode (cube2); OV.FinalizeModel (model, function () { return new OV.Material (OV.MaterialType.Phong) }); return model; }, - + GetCubeWithOneMissingFaceMesh () { var cube = new OV.Mesh (); @@ -204,12 +204,12 @@ module.exports = cube.AddTriangle (new OV.Triangle (0, 3, 2)); cube.AddTriangle (new OV.Triangle (0, 2, 1)); return cube; - }, + }, GetTetrahedronMesh () { var tetrahedron = new OV.Mesh (); - + let a = 1.0; tetrahedron.AddVertex (new OV.Coord3D (+a, +a, +a)); tetrahedron.AddVertex (new OV.Coord3D (-a, -a, +a)); @@ -221,13 +221,136 @@ module.exports = tetrahedron.AddTriangle (new OV.Triangle (1, 2, 3)); return tetrahedron; - }, + }, GetModelWithOneMesh (mesh) { var model = new OV.Model (); - model.AddMesh (mesh); + model.AddMeshToRootNode (mesh); OV.FinalizeModel (model, function () { return new OV.Material (OV.MaterialType.Phong) }); return model; - } + }, + + GetHierarchicalModel () + { + /* + + + + Node 1 + + Node 3 + Mesh 5 + Mesh 6 + Mesh 7 + + Node 4 + Mesh 7 + Mesh 3 + Mesh 4 + + Node 2 + Mesh 1 + Mesh 2 + */ + + let model = new OV.Model (); + let root = model.GetRootNode (); + + let node1 = new OV.Node (); + node1.SetName ('Node 1'); + + let node2 = new OV.Node (); + node2.SetName ('Node 2'); + + let node3 = new OV.Node (); + node3.SetName ('Node 3'); + + let node4 = new OV.Node (); + node4.SetName ('Node 4'); + + root.AddChildNode (node1); + root.AddChildNode (node2); + node1.AddChildNode (node3); + node1.AddChildNode (node4); + + let mesh1 = new OV.Mesh (); + mesh1.SetName ('Mesh 1'); + + let mesh2 = new OV.Mesh (); + mesh2.SetName ('Mesh 2'); + + let mesh3 = new OV.Mesh (); + mesh3.SetName ('Mesh 3'); + + let mesh4 = new OV.Mesh (); + mesh4.SetName ('Mesh 4'); + + let mesh5 = new OV.Mesh (); + mesh5.SetName ('Mesh 5'); + + let mesh6 = new OV.Mesh (); + mesh6.SetName ('Mesh 6'); + + let mesh7 = new OV.Mesh (); + mesh7.SetName ('Mesh 7'); + + let mesh1Ind = model.AddMesh (mesh1); + let mesh2Ind = model.AddMesh (mesh2); + let mesh3Ind = model.AddMesh (mesh3); + let mesh4Ind = model.AddMesh (mesh4); + let mesh5Ind = model.AddMesh (mesh5); + let mesh6Ind = model.AddMesh (mesh6); + let mesh7Ind = model.AddMesh (mesh7); + + root.AddMeshIndex (mesh1Ind); + root.AddMeshIndex (mesh2Ind); + node1.AddMeshIndex (mesh3Ind); + node1.AddMeshIndex (mesh4Ind); + node3.AddMeshIndex (mesh5Ind); + node3.AddMeshIndex (mesh6Ind); + node3.AddMeshIndex (mesh7Ind); + node4.AddMeshIndex (mesh7Ind); + + return model; + }, + + GetTranslatedRotatedCubesModel () + { + /* + + + + Translated + Cube + + Rotated + + Translated and Rotated + Cube + Cube + */ + + let model = new OV.Model (); + + let mesh = OV.GenerateCuboid (null, 1.0, 1.0, 1.0); + mesh.SetName ('Cube'); + let meshIndex = model.AddMesh (mesh); + + let root = model.GetRootNode (); + root.AddMeshIndex (0); + + let translatedNode = new OV.Node (); + translatedNode.SetName ('Translated'); + translatedNode.SetTransformation (new OV.Transformation (new OV.Matrix ().CreateTranslation (2.0, 0.0, 0.0))); + translatedNode.AddMeshIndex (0); + + let rotatedNode = new OV.Node (); + rotatedNode.SetName ('Rotated'); + + let rotation = OV.QuaternionFromAxisAngle (new OV.Coord3D (0.0, 0.0, 1.0), Math.PI / 2.0); + rotatedNode.SetTransformation (new OV.Transformation (new OV.Matrix ().CreateRotation (rotation.x, rotation.y, rotation.z, rotation.w))); + + let translatedRotatedNode = new OV.Node (); + translatedRotatedNode.SetName ('Translated and Rotated'); + translatedRotatedNode.SetTransformation (new OV.Transformation (new OV.Matrix ().CreateTranslation (2.0, 0.0, 0.0))); + translatedRotatedNode.AddMeshIndex (0); + + root.AddChildNode (translatedNode); + root.AddChildNode (rotatedNode); + rotatedNode.AddChildNode (translatedRotatedNode); + + return model; + } } diff --git a/website/o3dv/js/navigator.js b/website/o3dv/js/navigator.js index 4cf145f..0b8ef28 100644 --- a/website/o3dv/js/navigator.js +++ b/website/o3dv/js/navigator.js @@ -250,14 +250,7 @@ OV.Navigator = class meshesItem.ShowChildren (true, null); let rootNode = model.GetRootNode (); - if (!rootNode.IsEmpty ()) { - AddModelNodeToTree (this, model, rootNode, meshesItem); - } else { - // TODO: remove - for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) { - AddMeshToNodeTree (this, model, rootNode, meshIndex, meshesItem); - } - } + AddModelNodeToTree (this, model, rootNode, meshesItem); } MeshItemCount ()