From fefee144bd00f63c2ccbad0f196423ddbd538011 Mon Sep 17 00:00:00 2001 From: kovacsv Date: Fri, 3 Mar 2023 20:23:30 +0100 Subject: [PATCH] Read custom properties from glTF elements #368 --- source/engine/import/importergltf.js | 60 ++-- test/testfiles/gltf/Properties/properties.glb | Bin 0 -> 5288 bytes .../testfiles/gltf/Properties/properties.gltf | 306 ++++++++++++++++++ test/tests/importergltf_test.js | 27 ++ 4 files changed, 371 insertions(+), 22 deletions(-) create mode 100644 test/testfiles/gltf/Properties/properties.glb create mode 100644 test/testfiles/gltf/Properties/properties.gltf diff --git a/source/engine/import/importergltf.js b/source/engine/import/importergltf.js index f61fc86..b641a3f 100644 --- a/source/engine/import/importergltf.js +++ b/source/engine/import/importergltf.js @@ -641,33 +641,41 @@ export class ImporterGltf extends ImporterBase } } - this.ImportNodes (gltf); - this.ImportModelProperties (gltf); + this.ImportProperties (this.model, gltf.asset, 'Asset properties'); + this.ImportScene (gltf); } - ImportModelProperties (gltf) + ImportProperties (modelObject, gltfObject, propertyGroupName) { - function ImportProperties (model, propertyGroupName, propertyObject) - { - let propertyGroup = new PropertyGroup (propertyGroupName); - for (let propertyName in propertyObject) { - if (Object.prototype.hasOwnProperty.call (propertyObject, propertyName)) { - if (typeof propertyObject[propertyName] === 'string') { - const property = new Property (PropertyType.Text, propertyName, propertyObject[propertyName]); - propertyGroup.AddProperty (property); - } - } - } - if (propertyGroup.PropertyCount () > 0) { - model.AddPropertyGroup (propertyGroup); - } - return propertyGroup; + if (gltfObject === undefined || gltfObject === null) { + return; } - ImportProperties (this.model, 'Asset properties', gltf.asset); - if (gltf.asset['extras']) { - ImportProperties (this.model, 'Extras', gltf.asset['extras']); + let propertyGroup = new PropertyGroup (propertyGroupName); + for (let propertyName in gltfObject) { + if (Object.prototype.hasOwnProperty.call (gltfObject, propertyName)) { + let property = null; + let propertyValue = gltfObject[propertyName]; + if (typeof propertyValue === 'string') { + property = new Property (PropertyType.Text, propertyName, propertyValue); + } else if (typeof propertyValue === 'number') { + if (Number.isInteger (propertyValue)) { + property = new Property (PropertyType.Integer, propertyName, propertyValue); + } else { + property = new Property (PropertyType.Number, propertyName, propertyValue); + } + } + if (property !== null) { + propertyGroup.AddProperty (property); + } + } } + + if (propertyGroup.PropertyCount () === 0) { + return; + } + + modelObject.AddPropertyGroup (propertyGroup); } GetDefaultScene (gltf) @@ -790,6 +798,7 @@ export class ImporterGltf extends ImporterBase ImportMesh (gltf, gltfMesh) { let mesh = new Mesh (); + this.model.AddMesh (mesh); if (gltfMesh.name !== undefined) { mesh.SetName (gltfMesh.name); @@ -799,6 +808,8 @@ export class ImporterGltf extends ImporterBase let primitive = gltfMesh.primitives[i]; this.ImportPrimitive (gltf, primitive, mesh); } + + this.ImportProperties (mesh, gltfMesh.extras, 'Mesh properties'); } ImportPrimitive (gltf, primitive, mesh) @@ -982,17 +993,20 @@ export class ImporterGltf extends ImporterBase mesh.AddTriangle (triangle); } - ImportNodes (gltf) + ImportScene (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); } + + this.ImportProperties (this.model, scene.extras, 'Scene properties'); } ImportNode (gltf, gltfNode, parentNode) @@ -1046,6 +1060,8 @@ export class ImporterGltf extends ImporterBase if (gltfNode.children === undefined || gltfNode.children.length === 0) { node.SetType (NodeType.MeshNode); } + let mesh = this.model.GetMesh (gltfNode.mesh); + this.ImportProperties (mesh, gltfNode.extras, 'Node properties'); node.AddMeshIndex (gltfNode.mesh); } } diff --git a/test/testfiles/gltf/Properties/properties.glb b/test/testfiles/gltf/Properties/properties.glb new file mode 100644 index 0000000000000000000000000000000000000000..5f9154f338f49a8be6df1e971e57d97eb66b97af GIT binary patch literal 5288 zcmcIm+iu%N5Z$D=q)9JH)Ap6%GozA}B3XW@oHz;UHnsxW2nrZRP06$@Kq3u_auXN< z_&NOx_tSdLXxE}hNtV!d;pLf~nLRVRJG*jkaQOPJQtGcKO1*rb)UOBay(>Eyjl$I4 zys~>?6ed9$C-$cO+j$a4@yP07iuGa;MyFw7?flfXE~}MVrPj0^`!Y;M{WyZNUvce^ zjy>vvz}|GVG_p63uI%uAngkH9>;syuw@G{vCg}(3AWiyF53^;O6}}IK7lRPI1;3pr z4SOMS@=B)HgE&CuZsi%GN5K%mC$qs4#it=Na2?O_k3SwyHTj(O;5AKY%IDa#mYZZr zdy^}o4#Uy8ELn%&9(O{^vp5@Da;5D^J#Y6XcE`rnM595F$~GcZ*Lhm4xNfb{Y}A_# zx8CsUZsT~$SHTIFtv6d_V&u0;ul{D1hZDN!B)ef637A=*W-9N)1f9XuE;DgTsJzD2e)v}YKv+4>!sz)OYDD0 ztGaGla}rxCE!o-8xm=+9b=gI=m+Ar65A`r(nbrc;=4#`*;pOzP%wg~z&!mTEQc9$c2mR=&=g1$p zQ<-JId$nDa2QANzXYDrj>2$v|9k1Ey)63Cu+U4n@l(ki{Odb7T`}v#a`=$6;e3{@s z+Z>e4ZS2c7NAg&Ha?|PM%|SKY7X4owJc{!+_GxnEgKw@g9cx1wPRlM|KrDKLiu5(p>zu%+3|ERcDtX*EZIO-6(`^ z)Ul3y=<1ThOQAPvYlJQ>+w=TF@MXJJ3hq_?HKLcN*WERumy_RU^4_m_JxPz-}~x& z^_jY>?%{h+Jy4I-S0H?Z{wX?RN=LkJ|DT(l0{|7g6e3*E#KGOusG7Pdq_a?C>Gdk9va^ZD_;{{e(zg zbRzxOh_su=wXumV%h@2ai9HihK4vc_gPdM-uFS*yOdgqzLpsQ&6?3EB~iXv7Ttgh*d>BK_Ei zw427Yv579r*&wrtJrhwrW-lg#oL+OT%)|Ul9+{3qI>@FKbEDqmV{G&M#gF{gnkk#0 O$xZCEX}yeR{Qm*nn;XCY literal 0 HcmV?d00001 diff --git a/test/testfiles/gltf/Properties/properties.gltf b/test/testfiles/gltf/Properties/properties.gltf new file mode 100644 index 0000000..327df2c --- /dev/null +++ b/test/testfiles/gltf/Properties/properties.gltf @@ -0,0 +1,306 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v3.4.49", + "version" : "2.0" + }, + "scene" : 0, + "scenes" : [ + { + "extras" : { + "Scene Property String" : "scene example", + "Scene Property Integer" : 1, + "Scene Property Float" : 0.5 + }, + "name" : "Scene", + "nodes" : [ + 0, + 1, + 2 + ] + } + ], + "nodes" : [ + { + "extras" : { + "Node Property Float" : 0.5, + "Node Property String" : "node example" + }, + "mesh" : 0, + "name" : "Cube 1 Node" + }, + { + "mesh" : 1, + "name" : "Cube 2 Node", + "translation" : [ + 0, + 0, + -3.0047976970672607 + ] + }, + { + "mesh" : 2, + "name" : "Cube 3 Node", + "translation" : [ + -2.802919626235962, + 0, + 0 + ] + } + ], + "materials" : [ + { + "doubleSided" : true, + "extras" : { + "Material Property Float" : 1.0, + "Material Property String" : "material example" + }, + "name" : "Material 1", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.800000011920929, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + }, + { + "doubleSided" : true, + "name" : "Material 2", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0.800000011920929, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + }, + { + "doubleSided" : true, + "name" : "Material 3", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0.800000011920929, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + } + ], + "meshes" : [ + { + "extras" : { + "Mesh Property Float" : 0.5, + "Mesh Property String" : "mesh example" + }, + "name" : "Cube 1", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "TEXCOORD_0" : 1, + "NORMAL" : 2 + }, + "indices" : 3, + "material" : 0 + } + ] + }, + { + "name" : "Cube 2", + "primitives" : [ + { + "attributes" : { + "POSITION" : 4, + "TEXCOORD_0" : 5, + "NORMAL" : 6 + }, + "indices" : 3, + "material" : 1 + } + ] + }, + { + "name" : "Cube 3", + "primitives" : [ + { + "attributes" : { + "POSITION" : 7, + "TEXCOORD_0" : 8, + "NORMAL" : 9 + }, + "indices" : 3, + "material" : 2 + } + ] + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 24, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 24, + "type" : "VEC2" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3" + }, + { + "bufferView" : 3, + "componentType" : 5123, + "count" : 36, + "type" : "SCALAR" + }, + { + "bufferView" : 4, + "componentType" : 5126, + "count" : 24, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 24, + "type" : "VEC2" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3" + }, + { + "bufferView" : 7, + "componentType" : 5126, + "count" : 24, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 8, + "componentType" : 5126, + "count" : 24, + "type" : "VEC2" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 0, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 192, + "byteOffset" : 288, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 480, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 72, + "byteOffset" : 768, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 840, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 192, + "byteOffset" : 1128, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 1320, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 1608, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 192, + "byteOffset" : 1896, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 2088, + "target" : 34962 + } + ], + "buffers" : [ + { + "byteLength" : 2376, + "uri" : "data:application/octet-stream;base64,AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AAAAPgAAAD8AAMA+AABAPwAAwD4AAEA/AAAgPwAAAAAAACA/AACAPwAAYD8AAIA+AAAAPgAAgD4AAMA+AAAAAAAAwD4AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAQAOABQAAQAUAAcACgAGABIACgASABYAFwATAAwAFwAMABAADwADAAkADwAJABUABQACAAgABQAIAAsAEQANAAAAEQAAAAQAAACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AAAAPgAAAD8AAMA+AABAPwAAwD4AAEA/AAAgPwAAAAAAACA/AACAPwAAYD8AAIA+AAAAPgAAgD4AAMA+AAAAAAAAwD4AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AAAAPgAAAD8AAMA+AABAPwAAwD4AAEA/AAAgPwAAAAAAACA/AACAPwAAYD8AAIA+AAAAPgAAgD4AAMA+AAAAAAAAwD4AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACA" + } + ] +} diff --git a/test/tests/importergltf_test.js b/test/tests/importergltf_test.js index 9a7ae19..0b6c2f0 100644 --- a/test/tests/importergltf_test.js +++ b/test/tests/importergltf_test.js @@ -656,6 +656,33 @@ describe ('Gltf Importer', function () { }); } }); + + it ('Properties', function (done) { + let testFileList = [ + ['Properties', 'properties.gltf'], + ['Properties', 'properties.glb'] + ]; + let processed = 0; + for (let i = 0; i < testFileList.length; i++) { + let testFile = testFileList[i]; + ImportGltfFile (testFile[0], testFile[1], function (model) { + assert.ok (OV.CheckModel (model)); + assert.equal (model.PropertyGroupCount (), 2); + assert.equal (model.GetPropertyGroup (0).PropertyCount (), 2); + assert.equal (model.GetPropertyGroup (1).PropertyCount (), 3); + + let firstMesh = model.GetMesh (0); + assert.equal (firstMesh.PropertyGroupCount (), 2); + assert.equal (firstMesh.GetPropertyGroup (0).PropertyCount (), 2); + assert.equal (firstMesh.GetPropertyGroup (1).PropertyCount (), 2); + + processed += 1; + if (processed == testFileList.length) { + done (); + } + }); + } + }); }); }