Import all models as hierarchical model, but put all the meshes under the root node.

This commit is contained in:
kovacsv 2021-10-27 08:25:47 +02:00
parent e6eff40543
commit 7abc6efc93
21 changed files with 305 additions and 307 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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';
}
}
};

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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]);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -465,7 +465,7 @@ OV.ImporterThree = class extends OV.ImporterBase
OV.FlipMeshTrianglesOrientation (mesh);
}
}
this.model.AddMesh (mesh);
this.model.AddMeshToRootNode (mesh);
child.geometry.dispose ();
});

View File

@ -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);
});
}
};

View File

@ -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 ();
});
};

View File

@ -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;

View File

@ -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);
};

View File

@ -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 () {
}
});
});
});
});
});

View File

@ -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 ()
{
/*
+ <Root>
+ 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 ()
{
/*
+ <Root>
+ 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 : '<Root>',
@ -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 : '<Root>',
@ -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 : '<Root>',
@ -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);
});
});

View File

@ -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 () {

View File

@ -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 ()
{
/*
+ <Root>
+ 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 ()
{
/*
+ <Root>
+ 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;
}
}

View File

@ -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 ()