diff --git a/docs/Doxyfile b/docs/Doxyfile
index 8364763..33cd01c 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = "MaterialXglTF"
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 0.0.1
+PROJECT_NUMBER = 0.0.3
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/src/materialxgltf/data/BoomBoxWithAxes.mtlx.glb b/docs/data/BoomBoxWithAxes.mtlx_sphere.glb
similarity index 83%
rename from src/materialxgltf/data/BoomBoxWithAxes.mtlx.glb
rename to docs/data/BoomBoxWithAxes.mtlx_sphere.glb
index 797b836..aefb0e3 100644
Binary files a/src/materialxgltf/data/BoomBoxWithAxes.mtlx.glb and b/docs/data/BoomBoxWithAxes.mtlx_sphere.glb differ
diff --git a/docs/data/Geometry/test_cube.bin b/docs/data/Geometry/test_cube.bin
new file mode 100644
index 0000000..883d154
Binary files /dev/null and b/docs/data/Geometry/test_cube.bin differ
diff --git a/docs/data/Geometry/test_cube.gltf b/docs/data/Geometry/test_cube.gltf
new file mode 100644
index 0000000..5d16be5
--- /dev/null
+++ b/docs/data/Geometry/test_cube.gltf
@@ -0,0 +1,230 @@
+{
+ "asset":{
+ "generator":"Khronos glTF Blender I/O v3.6.28",
+ "version":"2.0"
+ },
+ "extensionsUsed":[
+ "KHR_materials_clearcoat",
+ "KHR_materials_transmission",
+ "KHR_materials_specular",
+ "KHR_materials_ior"
+ ],
+ "scene":0,
+ "scenes":[
+ {
+ "name":"Scene",
+ "nodes":[
+ 0
+ ]
+ }
+ ],
+ "nodes":[
+ {
+ "mesh":0,
+ "name":"Cube"
+ }
+ ],
+ "materials":[
+ {
+ "doubleSided":true,
+ "extensions":{
+ "KHR_materials_clearcoat":{
+ "clearcoatFactor":0.022727273404598236,
+ "clearcoatRoughnessFactor":0.1663636416196823
+ },
+ "KHR_materials_transmission":{
+ "transmissionFactor":0.22727273404598236
+ },
+ "KHR_materials_specular":{
+ "specularColorFactor":[
+ 0.38111396192933505,
+ 0.2244931429797119,
+ 0.2450934815163317
+ ]
+ },
+ "KHR_materials_ior":{
+ "ior":9.94999885559082
+ }
+ },
+ "name":"Material",
+ "pbrMetallicRoughness":{
+ "baseColorFactor":[
+ 0.8000000715255737,
+ 0.009745790623128414,
+ 0.11368794739246368,
+ 1
+ ],
+ "metallicFactor":0.17272727191448212,
+ "roughnessFactor":0.5
+ }
+ },
+ {
+ "doubleSided":true,
+ "emissiveFactor":[
+ 0.014503229409456253,
+ 0.014503229409456253,
+ 0.014503229409456253
+ ],
+ "extensions":{
+ "KHR_materials_clearcoat":{
+ "clearcoatFactor":0.059090908616781235,
+ "clearcoatRoughnessFactor":0.11181817948818207
+ },
+ "KHR_materials_transmission":{
+ "transmissionFactor":0.06818182021379471
+ },
+ "KHR_materials_specular":{
+ "specularColorFactor":[
+ 0.10496773232530021,
+ 0.11140182461173363,
+ 0.2498355062097603
+ ]
+ },
+ "KHR_materials_ior":{
+ "ior":10.249999046325684
+ }
+ },
+ "name":"Material.001",
+ "pbrMetallicRoughness":{
+ "baseColorFactor":[
+ 0.033420365303754807,
+ 0.06746689230203629,
+ 0.8000000715255737,
+ 1
+ ],
+ "metallicFactor":0.09545454382896423,
+ "roughnessFactor":0.5
+ }
+ }
+ ],
+ "meshes":[
+ {
+ "name":"Cube",
+ "primitives":[
+ {
+ "attributes":{
+ "POSITION":0,
+ "NORMAL":1,
+ "TEXCOORD_0":2
+ },
+ "indices":3,
+ "material":0
+ }
+ ]
+ }
+ ],
+ "accessors":[
+ {
+ "bufferView":0,
+ "componentType":5126,
+ "count":24,
+ "max":[
+ 1,
+ 1,
+ 1
+ ],
+ "min":[
+ -1,
+ -1,
+ -1
+ ],
+ "type":"VEC3"
+ },
+ {
+ "bufferView":1,
+ "componentType":5126,
+ "count":24,
+ "type":"VEC3"
+ },
+ {
+ "bufferView":2,
+ "componentType":5126,
+ "count":24,
+ "type":"VEC2"
+ },
+ {
+ "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":"VEC3"
+ },
+ {
+ "bufferView":6,
+ "componentType":5126,
+ "count":24,
+ "type":"VEC2"
+ }
+ ],
+ "bufferViews":[
+ {
+ "buffer":0,
+ "byteLength":288,
+ "byteOffset":0,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":288,
+ "byteOffset":288,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":192,
+ "byteOffset":576,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":72,
+ "byteOffset":768,
+ "target":34963
+ },
+ {
+ "buffer":0,
+ "byteLength":288,
+ "byteOffset":840,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":288,
+ "byteOffset":1128,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":192,
+ "byteOffset":1416,
+ "target":34962
+ }
+ ],
+ "buffers":[
+ {
+ "byteLength":1608,
+ "uri":"test_cube.bin"
+ }
+ ]
+}
diff --git a/docs/data/Geometry/test_sphere.bin b/docs/data/Geometry/test_sphere.bin
new file mode 100644
index 0000000..60d4581
Binary files /dev/null and b/docs/data/Geometry/test_sphere.bin differ
diff --git a/docs/data/Geometry/test_sphere.gltf b/docs/data/Geometry/test_sphere.gltf
new file mode 100644
index 0000000..c9372df
--- /dev/null
+++ b/docs/data/Geometry/test_sphere.gltf
@@ -0,0 +1,228 @@
+{
+ "asset":{
+ "generator":"Khronos glTF Blender I/O v3.5.30",
+ "version":"2.0"
+ },
+ "scene":0,
+ "scenes":[
+ {
+ "name":"Scene",
+ "nodes":[
+ 0
+ ]
+ }
+ ],
+ "nodes":[
+ {
+ "mesh":0,
+ "name":"Sphere"
+ }
+ ],
+ "animations":[
+ {
+ "channels":[
+ {
+ "sampler":0,
+ "target":{
+ "node":0,
+ "path":"translation"
+ }
+ },
+ {
+ "sampler":1,
+ "target":{
+ "node":0,
+ "path":"rotation"
+ }
+ },
+ {
+ "sampler":2,
+ "target":{
+ "node":0,
+ "path":"scale"
+ }
+ }
+ ],
+ "name":"SphereAction",
+ "samplers":[
+ {
+ "input":5,
+ "interpolation":"STEP",
+ "output":6
+ },
+ {
+ "input":5,
+ "interpolation":"STEP",
+ "output":7
+ },
+ {
+ "input":5,
+ "interpolation":"STEP",
+ "output":8
+ }
+ ]
+ }
+ ],
+ "materials":[
+ {
+ "doubleSided":true,
+ "name":"Material.001",
+ "pbrMetallicRoughness":{
+ "baseColorFactor":[
+ 0.800000011920929,
+ 0.800000011920929,
+ 0.800000011920929,
+ 1
+ ],
+ "metallicFactor":0,
+ "roughnessFactor":0.5
+ }
+ }
+ ],
+ "meshes":[
+ {
+ "name":"Sphere",
+ "primitives":[
+ {
+ "attributes":{
+ "POSITION":0,
+ "TEXCOORD_0":1,
+ "NORMAL":2,
+ "TANGENT":3
+ },
+ "indices":4
+ }
+ ]
+ }
+ ],
+ "accessors":[
+ {
+ "bufferView":0,
+ "componentType":5126,
+ "count":559,
+ "max":[
+ 0.9999997019767761,
+ 1,
+ 0.9999993443489075
+ ],
+ "min":[
+ -0.9999990463256836,
+ -1,
+ -1
+ ],
+ "type":"VEC3"
+ },
+ {
+ "bufferView":1,
+ "componentType":5126,
+ "count":559,
+ "type":"VEC2"
+ },
+ {
+ "bufferView":2,
+ "componentType":5126,
+ "count":559,
+ "type":"VEC3"
+ },
+ {
+ "bufferView":3,
+ "componentType":5126,
+ "count":559,
+ "type":"VEC4"
+ },
+ {
+ "bufferView":4,
+ "componentType":5123,
+ "count":2880,
+ "type":"SCALAR"
+ },
+ {
+ "bufferView":5,
+ "componentType":5126,
+ "count":1,
+ "max":[
+ 0.041666666666666664
+ ],
+ "min":[
+ 0.041666666666666664
+ ],
+ "type":"SCALAR"
+ },
+ {
+ "bufferView":6,
+ "componentType":5126,
+ "count":1,
+ "type":"VEC3"
+ },
+ {
+ "bufferView":7,
+ "componentType":5126,
+ "count":1,
+ "type":"VEC4"
+ },
+ {
+ "bufferView":8,
+ "componentType":5126,
+ "count":1,
+ "type":"VEC3"
+ }
+ ],
+ "bufferViews":[
+ {
+ "buffer":0,
+ "byteLength":6708,
+ "byteOffset":0,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":4472,
+ "byteOffset":6708,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":6708,
+ "byteOffset":11180,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":8944,
+ "byteOffset":17888,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":5760,
+ "byteOffset":26832,
+ "target":34963
+ },
+ {
+ "buffer":0,
+ "byteLength":4,
+ "byteOffset":32592
+ },
+ {
+ "buffer":0,
+ "byteLength":12,
+ "byteOffset":32596
+ },
+ {
+ "buffer":0,
+ "byteLength":16,
+ "byteOffset":32608
+ },
+ {
+ "buffer":0,
+ "byteLength":12,
+ "byteOffset":32624
+ }
+ ],
+ "buffers":[
+ {
+ "byteLength":32636,
+ "uri":"test_sphere.bin"
+ }
+ ]
+}
diff --git a/docs/data/Physical/Aluminum.mtlx b/docs/data/Physical/Aluminum.mtlx
new file mode 100644
index 0000000..1a5a88f
--- /dev/null
+++ b/docs/data/Physical/Aluminum.mtlx
@@ -0,0 +1,12 @@
+
+
The MaterialX files for these materials were downloaded from the Physical Based Site
+maintained by Anton Palmqvist.
This notebook provides a set of sample code which demonstrates the -workflow to convert between glTF and MaterialX.
-The sample input file is the "BoomBox with Axes" file from the glTF sample repository found here is used to demonstrate glTF to MaterialX conversion.
-The resulting MaterialX file after conversion is used to demonstrate conversion to glTF.
-This notebook provides a set of sample code which demonstrates the workflow to convert between glTF and MaterialX.
+The sample input file is the "BoomBox with Axes" file from the glTF sample repository found here is used to demonstrate glTF to MaterialX conversion. The resulting MaterialX file after conversion is used to demonstrate conversion to glTF.
++ | + |
---|---|
The following are some examples from conversion of Substance3D materials to glTF
++ | + |
---|---|
Translation and baking are useful to just convert shading models. Below is a snapshot of a few materials which were downloaded from +the Physical Based Site which is maintained by Anton Palmqvist. The materials were converted from MaterialX with the preview using the ThreeJS editor:
+The following are convenience functions and command line tools which are provided as part of this package.
+mtlx2gltf.py`` contains a command line tool that uses a utility function
mtlx2gltf to convert from MaterialX to glTF. Various command line options are mapped to conversion options (
MTLX2GLTFOptions`).usage: mtlx2gltf.py [-h] [--gltfFileName GLTFFILENAME] [--gltfGeomFileName GLTFGEOMFILENAME] [--primsPerMaterial PRIMSPERMATERIAL]
+ [--packageBinary PACKAGEBINARY] [--translateShaders TRANSLATESHADERS] [--bakeTextures BAKETEXTURES]
+ [--bakeResolution BAKERESOLUTION]
+ mtlxFileName
+
+Utility to convert a MaterialX file to a glTF file
+
+positional arguments:
+ mtlxFileName Path containing MaterialX file to convert.
+
+options:
+ -h, --help show this help message and exit
+ --gltfFileName GLTFFILENAME
+ Name of MaterialX output file. If not specified the glTF name with "_tomtlx.mtlx" suffix will be used
+ --gltfGeomFileName GLTFGEOMFILENAME
+ Name of MaterialX output file. If not specified the glTF name with "_tomtlx.mtlx" suffix will be used
+ --primsPerMaterial PRIMSPERMATERIAL
+ Create a new primitive per material and assign the material. Default is False
+ --packageBinary PACKAGEBINARY
+ Create a biary packaged GLB file. Default is False
+ --translateShaders TRANSLATESHADERS
+ Translate shaders to glTF. Default is False
+ --bakeTextures BAKETEXTURES
+ Bake pattern graphs as textures. Default is False
+ --bakeResolution BAKERESOLUTION
+ Bake image resolution. Default is 256
+
GLTF2MTLXOptions
).usage: gltf2mtlx.py [-h] [--mtlxFileName MTLXFILENAME] [--createAssignments CREATEASSIGNMENTS] gltfFileName
+
+Utility to convert a glTF file to MaterialX file
+
+positional arguments:
+ gltfFileName Path containing glTF file to convert.
+
+options:
+ -h, --help show this help message and exit
+ --mtlxFileName MTLXFILENAME
+ Name of MaterialX output file. If not specified the glTF name with "_tomtlx.mtlx" suffix will be used
+ --createAssignments CREATEASSIGNMENTS
+ Create material assignments. Default is True
+
glTF does not allow for any pathing specifieds on resources such as image and geometry uris. As such the proper pathing
+must be set before packaging to glb files. This is handled during the packaing process which uses the pygltflib
Python package.
By default mtlx2gltf
adds search paths (mx.FileSearchPath) to attempt to find the absoluate location of the uri resources, sets the uri and hen performs binary packing. Thus it is possible for instance to specify embedding geometry which is not in the same folder as the root glTF file.
The examples at the beginning of this document show an example Adobe Substance 3D material which was exported and mapped to a MaterialX material. Then it was converted to glTF with different geometry paths.
+<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.js"></script>
+<model-viewer style='background-color:rgba(0, 0, 0, 1.0); width: 48em; height: 48em' id='viewer1' ar interaction-prompt='none' camera-controls touch-action='pan-y' src='./docs/data/BoomBoxWithAxes_primMaterials.glb' shadow-intensity='0.3' alt='BoomBox With Axes Per Prim Material' poster='./docs/data/BoomBoxWithAxes_primMaterials.png'></model-viewer>
The following shows is a set of progressive examples to convert from a glTF file to MaterialX and then to a new glTF file for "shader ball" preview of extracted materials.
Note that the sample data is included as part of the package for convenience.
-The sample input file is the "BoomBox with Axes" file from the glTF sample repository found here.
+The sample input file is the "BoomBox with Axes" file from the glTF sample repository found here.
This is converted from glTF to a MaterialX document which can be previewed / modified using an integration which supports MaterialX. Here the file is loaded into the "MaterialX Graph Editor" which comes with MaterialX releases.
+This is converted from glTF to a MaterialX document which can be previewed / modified using an integration which supports MaterialX. Here the file is loaded into the "MaterialX Graph Editor" which comes with MaterialX releases.
The converted materials are then used to create a new glTF file using sample "shaderball" data with each material found assigned to different instances of the "shaderball"
A Jupyter
notebook which performs the same steps is available here. This or any other notebook can be used if the user wishes to test the package in an interactive environment.
A Jupyter
notebook which performs the same steps is available here.
This or any other notebook can be used if the user wishes to test the package in an interactive environment.
All materials are assumed to use glTF PBR surface shaders. Conversion to this shading model can be performed via MaterialX utilities, which includes texture baking.
-Please refer to the sample Jupyter notebook for an example of shader translation and baking using some convenience functions included with the package. Note that they do not need to be used as the core MaterialX distribution provides access to the APIs used in this package.
+Please refer to the sample Jupyter notebook for an example of shader translation and baking using some convenience functions included with the package. Note that they do not need to be used as the core MaterialX distribution provides access to the APIs used in this package.