2171 @brief Convert a MaterialX document to glTF.
2172 @param doc: The MaterialX document to convert.
2173 @param gltfJson: The glTF document to write to.
2174 @param resetMaterials: Whether to clear any existing glTF materials.
2179 addInputsFromNodeDef = self.
_options[
'writeDefaultInputs']
2181 for material
in doc.getMaterialNodes():
2182 shaderNodes = mx.getShaderNodes(material)
2183 for shaderNode
in shaderNodes:
2184 category = shaderNode.getCategory()
2185 path = shaderNode.getNamePath()
2186 if category == MTLX_GLTF_PBR_CATEGORY
and path
not in pbrNodes:
2187 if addInputsFromNodeDef:
2188 hasNormal = shaderNode.getInput(
'normal')
2189 hasTangent = shaderNode.getInput(
'tangent')
2190 shaderNode.addInputsFromNodeDef()
2192 shaderNode.removeChild(
'tangent')
2194 shaderNode.removeChild(
'normal')
2195 pbrNodes[path] = shaderNode
2196 elif category == MTLX_UNLIT_CATEGORY_STRING
and path
not in unlitNodes:
2197 if addInputsFromNodeDef:
2198 hasNormal = shaderNode.getInput(
'normal')
2199 hasTangent = shaderNode.getInput(
'tangent')
2200 shaderNode.addInputsFromNodeDef()
2202 shaderNode.removeChild(
'tangent')
2204 shaderNode.removeChild(
'normal')
2205 unlitNodes[path] = shaderNode
2207 materials_count = len(pbrNodes) + len(unlitNodes)
2208 if materials_count == 0:
2213 if 'materials' in gltfJson
and not resetMaterials:
2214 materials = gltfJson[
'materials']
2216 materials = gltfJson[
'materials'] = list()
2219 if 'textures' in gltfJson:
2220 textures = gltfJson[
'textures']
2222 textures = gltfJson[
'textures'] = list()
2225 if 'images' in gltfJson:
2226 images = gltfJson[
'images']
2228 images = gltfJson[
'images'] = list()
2231 if 'samplers' in gltfJson:
2232 samplers = gltfJson[
'samplers']
2234 samplers = gltfJson[
'samplers'] = list()
2237 extensionsUsed =
None
2238 if not 'extensionsUsed' in gltfJson:
2239 gltfJson[
'extensionsUsed'] = []
2240 extensionsUsed = gltfJson[
'extensionsUsed']
2244 COLOR_SEMANTIC =
'color'
2246 for name
in unlitNodes:
2249 unlitExtension =
'KHR_materials_unlit'
2250 if not unlitExtension
in extensionsUsed:
2251 extensionsUsed.append(unlitExtension)
2252 mat_extensions = material[
'extensions'] = {}
2253 mat_extensions[unlitExtension] = {}
2255 unlitNode = unlitNodes[name]
2256 material[
'name'] = name
2257 roughness = material[
'pbrMetallicRoughness'] = {}
2259 base_color_set =
False
2260 base_color = [ 1.0, 1.0, 1.0, 1.0 ]
2262 imageNode = unlitNode.getConnectedNode(
'emission_color')
2265 fileInput = imageNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2266 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2267 filename = fileInput.getResolvedValueString()
2269 if len(filename) == 0:
2275 textures.append(texture)
2277 roughness[
'baseColorTexture'] = {}
2278 roughness[
'baseColorTexture'][
'index'] = len(textures) - 1
2283 color = unlitNode.getInputValue(
'emission_color')
2285 base_color[0] = color[0]
2286 base_color[1] = color[1]
2287 base_color[2] = color[2]
2288 base_color_set =
True
2291 color = unlitNode.getInputValue(
'emission_color')
2293 base_color[0] = color[0]
2294 base_color[1] = color[1]
2295 base_color[2] = color[2]
2296 base_color_set =
True
2298 value = unlitNode.getInputValue(
'opacity')
2300 base_color[3] = value
2301 base_color_set =
True
2304 roughness[
'baseColorFactor'] = base_color
2307 roughness[
'baseColorFactor'] = base_color
2309 materials.append(material)
2311 for name
in pbrNodes:
2316 if not 'extensions' in material:
2317 material[
'extensions'] = {}
2318 extensions = material[
'extensions']
2320 pbrNode = pbrNodes[name]
2322 print(
'- Convert MaterialX node to glTF:', pbrNode.getNamePath())
2325 material[
'name'] = name
2329 roughness = material[
'pbrMetallicRoughness'] = {}
2332 base_color = [ 1.0, 1.0, 1.0, 1.0 ]
2333 base_color_set =
False
2336 imageNode = pbrNode.getConnectedNode(
'base_color')
2338 if self.
_options[
'createProceduralTextures']:
2340 if imageNode.getParent().isA(mx.NodeGraph):
2341 imageGraph = imageNode.getParent()
2345 print(
'- Generate KHR procedurals for graph: ' + imageGraph.getName())
2346 self.
log(
'- Generate KHR procedurals for graph: ' + imageGraph.getName())
2351 extensionName =
'KHR_procedurals'
2352 if extensionName
not in extensionsUsed:
2353 extensionsUsed.append(extensionName)
2359 graphOutputs, procDict = self.
graphToJson(imageGraph, gltfJson, materials, textures, images, samplers)
2360 outputs = imageGraph.getOutputs()
2361 if len(outputs) > 0:
2362 connectionName = outputs[0].getNamePath()
2363 inputBaseColor = pbrNode.getInput(
'base_color')
2364 outputSpecifier = inputBaseColor.getAttribute(
'output')
2365 if len(outputSpecifier) > 0:
2366 connectionName = imageGraph.getNamePath() +
'/' + outputSpecifier
2369 baseColorEntry = roughness[
'baseColorTexture'] = {}
2370 baseColorEntry[
'index'] = 0
2371 if 'extensions' not in baseColorEntry:
2372 baseColorEntry[
'extensions'] = {}
2373 extensions = baseColorEntry[
'extensions']
2374 if extensionName
not in extensions:
2375 extensions[extensionName] = {}
2376 procExtensions = extensions[extensionName]
2377 procExtensions[
'index'] = procDict[connectionName]
2381 fileInput = imageNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2382 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2383 filename = fileInput.getResolvedValueString()
2385 if len(filename) == 0:
2391 textures.append(texture)
2393 roughness[
'baseColorTexture'] = {}
2394 roughness[
'baseColorTexture'][
'index'] = len(textures) - 1
2399 color = pbrNode.getInputValue(
'base_color')
2401 base_color[0] = color[0]
2402 base_color[1] = color[1]
2403 base_color[2] = color[2]
2404 base_color_set =
True
2407 color = pbrNode.getInputValue(
'base_color')
2409 base_color[0] = color[0]
2410 base_color[1] = color[1]
2411 base_color[2] = color[2]
2412 base_color_set =
True
2414 value = pbrNode.getInputValue(
'alpha')
2416 base_color[3] = value
2417 base_color_set =
True
2420 roughness[
'baseColorFactor'] = base_color
2427 metallicFactor = pbrNode.getInputValue(
'metallic')
2435 extractInputs = [
'metallic',
'roughness',
'occlusion' ]
2436 filenames = [ EMPTY_STRING, EMPTY_STRING, EMPTY_STRING ]
2437 imageNamePaths = [ EMPTY_STRING, EMPTY_STRING, EMPTY_STRING ]
2438 roughnessInputs = [
'metallicFactor',
'roughnessFactor',
'' ]
2440 IN_STRING = MTLX_IN_STRING
2443 extractCategory =
'extract'
2444 for e
in range(0, 3):
2445 inputName = extractInputs[e]
2446 pbrInput = pbrNode.getInput(inputName)
2449 connectedNode = pbrNode.getConnectedNode(inputName)
2451 if connectedNode.getCategory() == extractCategory:
2452 imageNode = connectedNode.getConnectedNode(IN_STRING)
2454 imageNode = connectedNode
2457 fileInput = imageNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2458 filename = EMPTY_STRING
2459 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2460 filename = fileInput.getResolvedValueString()
2461 filenames[e] = filename
2462 imageNamePaths[e] = imageNode.getNamePath()
2466 if len(roughnessInputs[e]):
2467 value = pbrInput.getValue()
2469 roughness[roughnessInputs[e]] = value
2479 metallicFilename = mx.FilePath(filenames[0])
2480 roughnessFilename = mx.FilePath(filenames[1])
2481 occlusionFilename = mx.FilePath(filenames[2])
2482 origMetallicFilename = metallicFilename
2483 metallicFilename = self.
_options[
'searchPath'].find(metallicFilename)
2484 origRoughnessFilename = roughnessFilename
2485 roughnessFilename = self.
_options[
'searchPath'].find(roughnessFilename)
2486 origOcclusionFilename = occlusionFilename
2487 occlusionFilename = self.
_options[
'searchPath'].find(occlusionFilename)
2490 if metallicFilename == roughnessFilename:
2491 if roughnessFilename == occlusionFilename:
2493 if not roughnessFilename.isEmpty():
2494 print(
'- Append single ORM texture', origRoughnessFilename.asString())
2496 self.
initialize_gtlf_texture(texture, imageNamePaths[0], origRoughnessFilename.asString(mx.FormatPosix), images)
2498 textures.append(texture)
2500 roughness[
'metallicRoughnessTexture'] = {}
2501 roughness[
'metallicRoughnessTexture'][
'index'] = len(textures) - 1
2504 if not metallicFilename.isEmpty():
2505 print(
'- Append single metallic-roughness texture', origMetallicFilename.asString())
2507 self.
initialize_gtlf_texture(texture, imageNamePaths[0], origMetallicFilename.asString(mx.FormatPosix), images)
2509 textures.append(texture)
2511 roughness[
'metallicRoughnessTexture'] = {}
2512 roughness[
'metallicRoughnessTexture'][
'index'] = len(textures) - 1
2515 if not occlusionFilename.isEmpty():
2516 print(
'- Append single occlusion texture', origOcclusionFilename.asString())
2518 self.
initialize_gtlf_texture(texture, imageNamePaths[2], origOcclusionFilename.asString(mx.FormatPosix), images)
2520 textures.append(texture)
2523 material[
'occlusionTexture'] = {}
2524 material[
'occlusionTexture'][
'index'] = len(textures) - 1
2527 elif not metallicFilename.isEmpty()
or not (roughnessFilename).isEmpty():
2528 loader = mx_render.StbImageLoader.create()
2529 handler = mx_render.ImageHandler.create(loader)
2530 handler.setSearchPath(self.
_options[
'searchPath'])
2532 ormFilename = origRoughnessFilename
if metallicFilename.isEmpty()
else origMetallicFilename
2537 roughnessImage = handler.acquireImage(roughnessFilename)
if not roughnessFilename.isEmpty()
else None
2539 imageWidth = max(roughnessImage.getWidth(), imageWidth)
2540 imageHeight = max(roughnessImage.getHeight(), imageHeight)
2542 metallicImage = handler.acquireImage(metallicFilename)
if not metallicFilename.isEmpty()
else None
2544 imageWidth = max(metallicImage.getWidth(), imageWidth)
2545 imageHeight = max(metallicImage.getHeight(), imageHeight)
2548 if (imageWidth * imageHeight) != 0:
2549 color = mx.Color4(0.0)
2550 outputImage = mx_render.createUniformImage(imageWidth, imageHeight,
2551 3, mx_render.BaseType.UINT8, color)
2553 uniformRoughnessColor = 1.0
2554 if 'roughnessFactor' in roughness:
2555 uniformRoughnessColor = roughness[
'roughnessFactor']
2557 roughness[
'roughnessFactor'] = 1.0
2559 uniformMetallicColor = 1.0
2560 if 'metallicFactor' in roughness:
2561 uniformMetallicColor = roughness[
'metallicFactor']
2563 roughness[
'metallicFactor'] = 1.0
2565 for y
in range(0, imageHeight):
2566 for x
in range(0, imageWidth):
2567 finalColor = outputImage.getTexelColor(x, y)
2568 finalColor[1] = roughnessImage.getTexelColor(x, y)[0]
if roughnessImage
else uniformRoughnessColor
2569 finalColor[2] = metallicImage.getTexelColor(x, y)[0]
if metallicImage
else uniformMetallicColor
2570 outputImage.setTexelColor(x, y, finalColor)
2572 ormFilename.removeExtension()
2573 ormfilePath = ormFilename.asString(mx.FormatPosix) +
'_combined.png'
2575 saved = loader.saveImage(ormfilePath, outputImage, flipImage)
2577 uri = mx.FilePath(ormfilePath).getBaseName()
2578 print(
'- Merged metallic-roughness to single texture:', uri,
'Saved: ', saved)
2582 textures.append(texture)
2584 roughness[
'metallicRoughnessTexture'] = {}
2585 roughness[
'metallicRoughnessTexture'][
'index'] = len(textures) - 1
2588 filename = EMPTY_STRING
2589 imageNode = pbrNode.getConnectedNode(
'normal')
2592 if imageNode.getCategory() ==
'normalmap':
2593 imageNode = imageNode.getConnectedNode(IN_STRING)
2595 fileInput = imageNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2596 filename = EMPTY_STRING
2597 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2598 filename = fileInput.getResolvedValueString()
2599 if len(filename) == 0:
2604 textures.append(texture)
2606 material[
'normalTexture'] = {}
2607 material[
'normalTexture'][
'index'] = len(textures) - 1
2612 outputExtension = {}
2614 'transmissionTexture',
'transmissionFactor', outputExtension, textures, images, samplers)
2615 if len(outputExtension) > 0:
2616 extensionName =
'KHR_materials_transmission'
2617 extensions[extensionName] = outputExtension
2618 if extensionName
not in extensionsUsed:
2619 extensionsUsed.append(extensionName)
2622 imageNode = pbrNode.getConnectedNode(
'specular_color')
2625 if imageNode.getParent().isA(mx.NodeGraph):
2626 imageGraph = imageNode.getParent()
2630 extensionName =
'KHR_procedurals'
2631 if extensionName
not in extensionsUsed:
2632 extensionsUsed.append(extensionName)
2633 if extensionName
not in extensions:
2634 extensions[extensionName] = {}
2635 outputExtension = extensions[extensionName]
2637 graphOutputs, procDict = self.
graphToJson(imageGraph, gltfJson, materials, textures, images, samplers)
2638 outputs = imageGraph.getOutputs()
2639 if len(outputs) > 0:
2640 connectionName = outputs[0].getNamePath()
2641 inputBaseColor = pbrNode.getInput(
'specular_color')
2642 outputSpecifier = inputBaseColor.getAttribute(
'output')
2643 if len(outputSpecifier) > 0:
2644 connectionName = imageGraph.getNamePath() +
'/' + outputSpecifier
2645 outputExtension[
'specularColorTexture'] = procDict[connectionName]
2648 outputExtension = {}
2650 'specularColorTexture',
'specularColorFactor', outputExtension, textures, images, samplers)
2652 'specularTexture',
'specularFactor', outputExtension, textures, images, samplers)
2653 if len(outputExtension) > 0:
2654 extensionName =
'KHR_materials_specular'
2655 if extensionName
not in extensionsUsed:
2656 extensionsUsed.append(extensionName)
2657 extensions[extensionName] = outputExtension
2661 'emissiveTexture',
'emissiveFactor', material, textures, images, samplers)
2664 outputExtension = {}
2666 '',
'emissiveStrength', outputExtension, textures, images, samplers)
2667 if len(outputExtension) > 0:
2668 extensionName =
'KHR_materials_emissive_strength'
2669 if extensionName
not in extensionsUsed:
2670 extensionsUsed.append(extensionName)
2671 extensions[extensionName] = outputExtension
2674 outputExtension = {}
2676 '',
'ior', outputExtension, textures, images, samplers)
2677 if len(outputExtension) > 0:
2678 extensionName =
'KHR_materials_ior'
2679 if extensionName
not in extensionsUsed:
2680 extensionsUsed.append(extensionName)
2681 extensions[extensionName] = outputExtension
2684 outputExtension = {}
2686 'sheenColorTexture',
'sheenColorFactor', outputExtension, textures, images, samplers)
2688 'sheenRoughnessTexture',
'sheenRoughnessFactor', outputExtension, textures, images, samplers)
2689 if len(outputExtension) > 0:
2690 extensionName =
'KHR_materials_sheen'
2691 if extensionName
not in extensionsUsed:
2692 extensionsUsed.append(extensionName)
2693 extensions[extensionName] = outputExtension
2696 outputExtension = {}
2698 'clearcoatTexture',
'clearcoatFactor', outputExtension, textures, images, samplers)
2700 'clearcoatRoughnessTexture',
'clearcoatRoughnessFactor', outputExtension, textures, images, samplers)
2701 if len(outputExtension) > 0:
2702 extensionName =
'KHR_materials_clearcoat'
2703 if extensionName
not in extensionsUsed:
2704 extensionsUsed.append(extensionName)
2705 extensions[extensionName] = outputExtension
2709 outputExtension = {}
2710 thicknessInput = pbrNode.getInput(
'thickness')
2713 thicknessNode = thicknessInput.getConnectedNode()
2714 thicknessFileName = EMPTY_STRING
2716 fileInput = thicknessNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2717 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2718 thicknessFileName = fileInput.getResolvedValueString()
2720 if len(thicknessFileName) > 0:
2723 textures.append(texture)
2725 outputExtension[
'thicknessTexture'] = {}
2726 outputExtension[
'thicknessTexture'][
'index'] = len(textures) - 1
2730 thicknessValue = thicknessInput.getValue()
2731 if thicknessValue
and thicknessValue > 0.0:
2732 outputExtension[
'thicknessFactor'] = thicknessValue
2735 attenuationInput = pbrNode.getInput(
'attenuation_color')
2736 if attenuationInput:
2737 attenuationValue = attenuationInput.getValue()
2738 if attenuationValue
and (attenuationValue[0] > 0.0
or attenuationValue[1] > 0.0
or attenuationValue[2] > 0.0):
2739 inputType = attenuationInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE)
2740 outputExtension[
'attenuationColor'] = self.
stringToScalar(attenuationInput.getValueString(), inputType)
2741 attenuationInput = pbrNode.getInput(
'attenuation_distance')
2742 if attenuationInput:
2743 attenuationValue = attenuationInput.getValue()
2744 if attenuationValue:
2745 outputExtension[
'attenuationDistance'] = attenuationValue
2747 if len(outputExtension) > 0:
2748 extensionName =
'KHR_materials_volume'
2749 if extensionName
not in extensionsUsed:
2750 extensionsUsed.append(extensionName)
2751 extensions[extensionName] = outputExtension
2754 filename = EMPTY_STRING
2755 imageNode = pbrNode.getConnectedNode(
'clearcoat_normal')
2758 if imageNode.getCategory() ==
'normalmap':
2759 imageNode = imageNode.getConnectedNode(IN_STRING)
2761 fileInput = imageNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2762 filename = EMPTY_STRING
2763 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2764 filename = fileInput.getResolvedValueString()
2765 if filename == EMPTY_STRING:
2771 textures.append(texture)
2773 outputExtension[
'clearcoatNormalTexture'] = {}
2774 outputExtension[
'clearcoatNormalTexture'][
'index'] = len(textures) - 1
2777 alphModeInput = pbrNode.getInput(
'alpha_mode')
2779 value = alphModeInput.getValue()
2782 alphaModeMap[0] =
'OPAQUE'
2783 alphaModeMap[1] =
'MASK'
2784 alphaModeMap[2] =
'BLEND'
2785 self.
writeFloatInput(pbrNode,
'alpha_mode',
'',
'alphaMode', material, textures, images, samplers, alphaModeMap)
2787 self.
writeFloatInput(pbrNode,
'alpha_cutoff',
'',
'alphaCutoff', material, textures, images, samplers)
2791 outputExtension = {}
2793 'iridescenceTexture',
'iridescenceFactor', outputExtension, textures, images, samplers)
2795 'iridescenceTexture',
'iridescenceIor', outputExtension, textures, images, samplers)
2796 if len(outputExtension) > 0:
2797 extensionName =
'KHR_materials_iridescence'
2798 if extensionName
not in extensionsUsed:
2799 extensionsUsed.append(extensionName)
2800 extensions[extensionName] = outputExtension
2807 thicknessInput = pbrNode.getInput(
'iridescence_thickness')
2810 thicknessNode = thicknessInput.getConnectedNode()
2811 thicknessFileName = mx.FilePath()
2813 fileInput = thicknessNode.getInput(mx.Implementation.FILE_ATTRIBUTE)
2814 thicknessFileName = EMPTY_STRING
2815 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2816 thicknessFileName = fileInput.getResolvedValueString()
2820 textures.append(texture)
2822 outputExtension[
'iridescenceThicknessTexture'] = {}
2823 outputExtension[
'iridescenceThicknessTexture'][
'index'] = len(textures) - 1
2825 thickessInput = thicknessNode.getInput(
'thicknessMin')
2826 thicknessValue = thickessInput.getValue()
if thickessInput
else None
2828 outputExtension[
'iridescenceThicknessMinimum'] = thicknessValue
2829 thickessInput = thicknessNode.getInput(
'thicknessMax')
2830 thicknessValue = thickessInput.getValue()
if thickessInput
else None
2832 outputExtension[
'iridescenceThicknessMaximum'] = thicknessValue
2836 anisotropy_strength_input = pbrNode.getInput(
'anisotropy_strength')
2837 if anisotropy_strength_input:
2838 outputExtension = {}
2839 anisotropy_strength_texture = anisotropy_strength_input.getConnectedNode()
2840 if anisotropy_strength_texture:
2841 fileInput = anisotropy_strength_texture.getInput(mx.Implementation.FILE_ATTRIBUTE)
2842 filename = EMPTY_STRING
2843 if fileInput
and fileInput.getAttribute(mx.TypedElement.TYPE_ATTRIBUTE) == mx.FILENAME_TYPE_STRING:
2844 filename = fileInput.getResolvedValueString()
2845 if len(filename) > 0:
2849 textures.append(texture)
2851 outputExtension[
'anisotropyTexture'] = {}
2852 outputExtension[
'anisotropyTexture'][
'index'] = len(textures) - 1
2855 strengthInput = anisotropy_strength_texture.getInput(
'anisotropy_strength')
2857 outputExtension[
'anisotropyStrength'] = strengthInput.getValue()
2859 outputExtension[
'anisotropyStrength'] = 1.0
2862 rotationInput = anisotropy_strength_texture.getInput(
'anisotropy_rotation')
2864 outputExtension[
'anisotropyRotation'] = rotationInput.getValue()
2867 anisotropy_strength_value = anisotropy_strength_input.getValue()
2868 if anisotropy_strength_value > 0:
2869 outputExtension[
'anisotropyStrength'] = anisotropy_strength_value
2872 anisotropy_rotation = pbrNode.getInput(
'anisotropy_rotation')
2873 if anisotropy_rotation:
2874 rotationValue = anisotropy_rotation.getValue()
2876 outputExtension[
'anisotropyRotation'] = rotationValue
2878 if len(outputExtension) > 0:
2879 extensionName =
'KHR_materials_anisotropy'
2880 if extensionName
not in extensionsUsed:
2881 extensionsUsed.append(extensionName)
2882 extensions[extensionName] = outputExtension
2884 if len(material[
'extensions']) == 0:
2885 del material[
'extensions']
2887 materials.append(material)
2890 if len(gltfJson[
'extensionsUsed']) == 0:
2891 del gltfJson[
'extensionsUsed']
2892 if len(gltfJson[
'samplers']) == 0:
2893 del gltfJson[
'samplers']
2894 if len(gltfJson[
'images']) == 0:
2895 del gltfJson[
'images']
2896 if len(gltfJson[
'textures']) == 0:
2897 del gltfJson[
'textures']