Hierarchical glTF import.
This commit is contained in:
parent
71cfe70c71
commit
3423baa2b2
Binary file not shown.
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
@ -37,50 +37,6 @@ OV.GltfConstants =
|
||||
BINARY_CHUNK_TYPE : 0x004E4942
|
||||
};
|
||||
|
||||
OV.GltfNodeTree = class
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
this.nodes = [];
|
||||
this.nodeToParent = {};
|
||||
this.nodeMatrices = {};
|
||||
}
|
||||
|
||||
AddMeshNode (nodeIndex)
|
||||
{
|
||||
this.nodes.push (nodeIndex);
|
||||
return this.nodes.length - 1;
|
||||
}
|
||||
|
||||
AddNodeParent (nodeIndex, parentIndex)
|
||||
{
|
||||
this.nodeToParent[nodeIndex] = parentIndex;
|
||||
}
|
||||
|
||||
GetNodeParent (nodeIndex)
|
||||
{
|
||||
let parentIndex = this.nodeToParent[nodeIndex];
|
||||
if (parentIndex === undefined || parentIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
return parentIndex;
|
||||
}
|
||||
|
||||
AddNodeMatrix (nodeIndex, matrix)
|
||||
{
|
||||
this.nodeMatrices[nodeIndex] = matrix;
|
||||
}
|
||||
|
||||
GetNodeMatrix (nodeIndex)
|
||||
{
|
||||
let matrix = this.nodeMatrices[nodeIndex];
|
||||
if (matrix === undefined) {
|
||||
return null;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
};
|
||||
|
||||
OV.GltfBufferReader = class
|
||||
{
|
||||
constructor (buffer)
|
||||
@ -614,26 +570,22 @@ OV.ImporterGltf = class extends OV.ImporterBase
|
||||
|
||||
ImportModel (gltf)
|
||||
{
|
||||
let defaultScene = this.GetDefaultScene (gltf);
|
||||
if (defaultScene === null) {
|
||||
this.SetError ('No default scene found.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.ImportModelProperties (gltf);
|
||||
|
||||
let materials = gltf.materials;
|
||||
if (materials !== undefined) {
|
||||
for (let i = 0; i < materials.length; i++) {
|
||||
this.ImportMaterial (gltf, i);
|
||||
for (let material of materials) {
|
||||
this.ImportMaterial (gltf, material);
|
||||
}
|
||||
}
|
||||
|
||||
let nodeTree = this.CollectMeshNodesForScene (gltf, defaultScene);
|
||||
for (let i = 0; i < nodeTree.nodes.length; i++) {
|
||||
let nodeIndex = nodeTree.nodes[i];
|
||||
this.ImportMeshNode (gltf, nodeIndex, nodeTree);
|
||||
let meshes = gltf.meshes;
|
||||
if (meshes !== undefined) {
|
||||
for (let mesh of meshes) {
|
||||
this.ImportMesh (gltf, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
this.ImportNodes (gltf);
|
||||
this.ImportModelProperties (gltf);
|
||||
}
|
||||
|
||||
ImportModelProperties (gltf)
|
||||
@ -670,39 +622,13 @@ OV.ImporterGltf = class extends OV.ImporterBase
|
||||
return gltf.scenes[defaultSceneIndex];
|
||||
}
|
||||
|
||||
CollectMeshNodesForScene (gltf, scene)
|
||||
{
|
||||
function CollectMeshNodeIndices (gltf, parentIndex, nodeIndex, nodeTree)
|
||||
{
|
||||
let node = gltf.nodes[nodeIndex];
|
||||
if (node.mesh !== undefined) {
|
||||
nodeTree.AddMeshNode (nodeIndex);
|
||||
}
|
||||
nodeTree.AddNodeParent (nodeIndex, parentIndex);
|
||||
if (node.children !== undefined) {
|
||||
for (let i = 0; i < node.children.length; i++) {
|
||||
let childNodeIndex = node.children[i];
|
||||
CollectMeshNodeIndices (gltf, nodeIndex, childNodeIndex, nodeTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let nodeTree = new OV.GltfNodeTree ();
|
||||
for (let i = 0; i < scene.nodes.length; i++) {
|
||||
let nodeIndex = scene.nodes[i];
|
||||
CollectMeshNodeIndices (gltf, -1, nodeIndex, nodeTree);
|
||||
}
|
||||
return nodeTree;
|
||||
}
|
||||
|
||||
ImportMaterial (gltf, materialIndex)
|
||||
ImportMaterial (gltf, gltfMaterial)
|
||||
{
|
||||
function GetMaterialComponent (component)
|
||||
{
|
||||
return parseInt (Math.round (OV.LinearToSRGB (component) * 255.0), 10);
|
||||
}
|
||||
|
||||
let gltfMaterial = gltf.materials[materialIndex];
|
||||
let material = new OV.Material (OV.MaterialType.Physical);
|
||||
if (gltfMaterial.name !== undefined) {
|
||||
material.name = gltfMaterial.name;
|
||||
@ -819,76 +745,18 @@ OV.ImporterGltf = class extends OV.ImporterBase
|
||||
return texture;
|
||||
}
|
||||
|
||||
ImportMeshNode (gltf, nodeIndex, nodeTree)
|
||||
ImportMesh (gltf, gltfMesh)
|
||||
{
|
||||
function GetNodeTransformation (gltf, nodeIndex, nodeTree)
|
||||
{
|
||||
let node = gltf.nodes[nodeIndex];
|
||||
let matrix = nodeTree.GetNodeMatrix (nodeIndex);
|
||||
if (matrix !== null) {
|
||||
return matrix;
|
||||
}
|
||||
|
||||
matrix = new OV.Matrix ().CreateIdentity ();
|
||||
if (node.matrix !== undefined) {
|
||||
matrix.Set (node.matrix);
|
||||
} else {
|
||||
let hasTransformation = false;
|
||||
let translation = [0.0, 0.0, 0.0];
|
||||
let rotation = [0.0, 0.0, 0.0, 1.0];
|
||||
let scale = [1.0, 1.0, 1.0];
|
||||
if (node.translation !== undefined) {
|
||||
translation = node.translation;
|
||||
hasTransformation = true;
|
||||
}
|
||||
if (node.rotation !== undefined) {
|
||||
rotation = node.rotation;
|
||||
hasTransformation = true;
|
||||
}
|
||||
if (node.scale !== undefined) {
|
||||
scale = node.scale;
|
||||
hasTransformation = true;
|
||||
}
|
||||
|
||||
if (hasTransformation) {
|
||||
matrix.ComposeTRS (
|
||||
OV.ArrayToCoord3D (translation),
|
||||
OV.ArrayToQuaternion (rotation),
|
||||
OV.ArrayToCoord3D (scale)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let parentNodeIndex = nodeTree.GetNodeParent (nodeIndex);
|
||||
if (parentNodeIndex !== null) {
|
||||
let parentMatrix = GetNodeTransformation (gltf, parentNodeIndex, nodeTree);
|
||||
matrix = matrix.MultiplyMatrix (parentMatrix);
|
||||
}
|
||||
|
||||
nodeTree.AddNodeMatrix (nodeIndex, matrix);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
let gltfNode = gltf.nodes[nodeIndex];
|
||||
let gltfMeshIndex = gltfNode.mesh;
|
||||
let gltfMesh = gltf.meshes[gltfMeshIndex];
|
||||
|
||||
let mesh = new OV.Mesh ();
|
||||
this.model.AddMeshToRootNode (mesh);
|
||||
this.model.AddMesh (mesh);
|
||||
if (gltfMesh.name !== undefined) {
|
||||
mesh.SetName (gltfMesh.name);
|
||||
} else if (gltfNode.name !== undefined) {
|
||||
mesh.SetName (gltfNode.name);
|
||||
}
|
||||
|
||||
for (let i = 0; i < gltfMesh.primitives.length; i++) {
|
||||
let primitive = gltfMesh.primitives[i];
|
||||
this.ImportPrimitive (gltf, primitive, mesh);
|
||||
}
|
||||
|
||||
let matrix = GetNodeTransformation (gltf, nodeIndex, nodeTree);
|
||||
let transformation = new OV.Transformation (matrix);
|
||||
OV.TransformMesh (mesh, transformation);
|
||||
}
|
||||
|
||||
ImportPrimitive (gltf, primitive, mesh)
|
||||
@ -1022,6 +890,71 @@ OV.ImporterGltf = class extends OV.ImporterBase
|
||||
mesh.AddTriangle (triangle);
|
||||
}
|
||||
|
||||
ImportNodes (gltf)
|
||||
{
|
||||
let scene = this.GetDefaultScene (gltf);
|
||||
if (scene === null) {
|
||||
return;
|
||||
}
|
||||
let rootNode = this.model.GetRootNode ();
|
||||
for (let nodeIndex of scene.nodes) {
|
||||
let gltfNode = gltf.nodes[nodeIndex];
|
||||
this.ImportNode (gltf, gltfNode, rootNode);
|
||||
}
|
||||
}
|
||||
|
||||
ImportNode (gltf, gltfNode, parentNode)
|
||||
{
|
||||
function GetNodeTransformation (gltfNode)
|
||||
{
|
||||
let matrix = new OV.Matrix ().CreateIdentity ();
|
||||
if (gltfNode.matrix !== undefined) {
|
||||
matrix.Set (gltfNode.matrix);
|
||||
} else {
|
||||
let translation = [0.0, 0.0, 0.0];
|
||||
let rotation = [0.0, 0.0, 0.0, 1.0];
|
||||
let scale = [1.0, 1.0, 1.0];
|
||||
if (gltfNode.translation !== undefined) {
|
||||
translation = gltfNode.translation;
|
||||
}
|
||||
if (gltfNode.rotation !== undefined) {
|
||||
rotation = gltfNode.rotation;
|
||||
}
|
||||
if (gltfNode.scale !== undefined) {
|
||||
scale = gltfNode.scale;
|
||||
}
|
||||
matrix.ComposeTRS (
|
||||
OV.ArrayToCoord3D (translation),
|
||||
OV.ArrayToQuaternion (rotation),
|
||||
OV.ArrayToCoord3D (scale)
|
||||
);
|
||||
}
|
||||
return new OV.Transformation (matrix);
|
||||
}
|
||||
|
||||
if (gltfNode.children === undefined && gltfNode.mesh === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let node = new OV.Node ();
|
||||
if (gltfNode.name !== undefined) {
|
||||
node.SetName (gltfNode.name);
|
||||
}
|
||||
node.SetTransformation (GetNodeTransformation (gltfNode));
|
||||
parentNode.AddChildNode (node);
|
||||
|
||||
if (gltfNode.children !== undefined) {
|
||||
for (let childIndex of gltfNode.children) {
|
||||
let childGltfNode = gltf.nodes[childIndex];
|
||||
this.ImportNode (gltf, childGltfNode, node);
|
||||
}
|
||||
}
|
||||
|
||||
if (gltfNode.mesh !== undefined) {
|
||||
node.AddMeshIndex (gltfNode.mesh);
|
||||
}
|
||||
}
|
||||
|
||||
GetReaderFromBufferView (bufferView)
|
||||
{
|
||||
let bufferIndex = bufferView.buffer || 0;
|
||||
|
||||
@ -18,6 +18,17 @@ describe ('Gltf Importer', function () {
|
||||
let testFile = testFileList[i];
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelNodesToTree (model), {
|
||||
name : '<Root>',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [],
|
||||
meshNames : ['']
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
});
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
@ -57,6 +68,23 @@ describe ('Gltf Importer', function () {
|
||||
let testFile = testFileList[i];
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelNodesToTree (model), {
|
||||
name : '<Root>',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [],
|
||||
meshNames : ['Mesh']
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
});
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
@ -75,15 +103,15 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it ('BoxInterleaved', function (done) {
|
||||
let testFileList = [
|
||||
['BoxInterleaved/glTF', 'BoxInterleaved.gltf'],
|
||||
@ -95,6 +123,23 @@ describe ('Gltf Importer', function () {
|
||||
let testFile = testFileList[i];
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelNodesToTree (model), {
|
||||
name : '<Root>',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [],
|
||||
meshNames : ['Mesh']
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
});
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
@ -113,12 +158,12 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -133,6 +178,23 @@ describe ('Gltf Importer', function () {
|
||||
let testFile = testFileList[i];
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelNodesToTree (model), {
|
||||
name : '<Root>',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [],
|
||||
meshNames : ['Mesh']
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
});
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
@ -151,7 +213,7 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
@ -170,6 +232,22 @@ describe ('Gltf Importer', function () {
|
||||
let testFile = testFileList[i];
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelNodesToTree (model), {
|
||||
name : '<Root>',
|
||||
childNodes : [
|
||||
{
|
||||
name : '',
|
||||
childNodes : [],
|
||||
meshNames : ['']
|
||||
},
|
||||
{
|
||||
name : '',
|
||||
childNodes : [],
|
||||
meshNames : ['']
|
||||
}
|
||||
],
|
||||
meshNames : []
|
||||
});
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
@ -199,7 +277,7 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
@ -207,7 +285,7 @@ describe ('Gltf Importer', function () {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it ('OrientationTest', function (done) {
|
||||
let testFileList = [
|
||||
['OrientationTest/glTF', 'OrientationTest.gltf'],
|
||||
@ -380,7 +458,7 @@ describe ('Gltf Importer', function () {
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -415,7 +493,7 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
@ -451,7 +529,7 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
@ -495,5 +573,5 @@ describe ('Gltf Importer', function () {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -29,26 +29,6 @@ describe ('O3dv Importer', function () {
|
||||
meshNames : ['Cube']
|
||||
});
|
||||
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'Green' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
assert.strictEqual (model.MeshInstanceCount (), 3);
|
||||
let boundingBox = OV.GetBoundingBox (model);
|
||||
assert (OV.CoordIsEqual3D (boundingBox.min, new OV.Coord3D (-1.0, 0.0, 0.0)));
|
||||
|
||||
@ -139,11 +139,9 @@ module.exports =
|
||||
});
|
||||
}
|
||||
|
||||
var mesh, meshObj, boundingBox;
|
||||
for (i = 0; i < model.MeshCount (); i++) {
|
||||
mesh = model.GetMesh (i);
|
||||
boundingBox = OV.GetBoundingBox (mesh);
|
||||
meshObj = {
|
||||
model.EnumerateTransformedMeshInstances ((mesh) => {
|
||||
let boundingBox = OV.GetBoundingBox (mesh);
|
||||
let meshObj = {
|
||||
name : mesh.GetName (),
|
||||
vertexCount : mesh.VertexCount (),
|
||||
normalCount : mesh.NormalCount (),
|
||||
@ -155,7 +153,7 @@ module.exports =
|
||||
}
|
||||
};
|
||||
obj.meshes.push (meshObj);
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
OV.FeatureSet =
|
||||
{
|
||||
NavigatorTree : true
|
||||
NavigatorTree : false
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user