owned this note
owned this note
Published
Linked with GitHub
# Export from Blender
[toc]
1. Unhide all assets by pressing alt-h in blender window
2. Copy paste below into the scripting area, change name to export.py
3. Change export path to your username in Windows or if using linux change path to export dir
4. Hit run, glb files should be in your export folder

## Export glb WITH Armature
```python!
import bpy
import os
# Set the export path
export_path = "/home/jin/Desktop/Exports/"
# Get a list of all visible objects in the scene
visible_objects = [obj for obj in bpy.context.scene.objects if obj.visible_get()]
# Iterate over each visible object and export it as a separate glTF binary file
for obj in visible_objects:
# Check if the object is a mesh
if obj.type != 'MESH':
continue # Skip non-mesh objects
# Set the filename for the exported glTF file
filename = obj.name + ".glb"
filepath = os.path.join(export_path, filename)
# Select the extended parent object
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
extended_parent = obj
while extended_parent.parent:
extended_parent = extended_parent.parent
extended_parent.select_set(True)
# Export the object as a glTF binary file
bpy.ops.export_scene.gltf(filepath=filepath, export_format='GLB', use_selection=True)
# Delete the object from the scene
bpy.ops.object.delete()
```
### StructRNA Error
If having ReferenceError StructRNA try this
```python!
import bpy
import os
# Set the export path
export_path = "/home/jin/Desktop/Exports/"
# Get a list of all visible objects in the scene
visible_objects = [obj for obj in bpy.context.scene.objects if obj.visible_get()]
# List to store objects to be deleted
objects_to_delete = []
# Iterate over each visible object and export it as a separate glTF binary file
for obj in visible_objects:
print("Processing object:", obj.name)
# Check if the object is a mesh
if obj.type != 'MESH':
print("Skipping non-mesh object:", obj.name)
continue # Skip non-mesh objects
# Check if the object has an associated armature
if not obj.parent or obj.parent.type != 'ARMATURE':
print("Skipping object without associated armature:", obj.name)
continue # Skip objects without an associated armature
# Set the filename for the exported glTF file
filename = obj.name + ".glb"
filepath = os.path.join(export_path, filename)
# Select the object and its armature
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
obj.parent.select_set(True)
# Export the object and its armature as a glTF binary file
print("Exporting:", obj.name)
bpy.ops.export_scene.gltf(filepath=filepath, export_format='GLB', use_selection=True)
# Mark the object for deletion
objects_to_delete.append(obj)
# Delete the objects outside the loop
for obj in objects_to_delete:
# Check if the object still exists before deleting it
if obj.name in bpy.context.scene.objects:
# Delete the object from the scene
print("Deleting:", obj.name)
bpy.data.objects.remove(obj)
else:
print("Object has already been deleted:", obj.name)
```
### Export Without Armature
```python=
import bpy
import os
# Set the export path
export_path = "C:/Users/test/Desktop/Exports"
# Get a list of all visible objects in the scene
visible_objects = [obj for obj in bpy.context.scene.objects if obj.visible_get()]
# Iterate over each visible object and export it as a separate glTF binary file
for obj in visible_objects:
# Check if the object is a mesh
if obj.type != 'MESH':
continue # Skip non-mesh objects
# Set the filename for the exported glTF file
filename = obj.name + ".glb"
filepath = os.path.join(export_path, filename)
# Select the object
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
# Export the object as a glTF binary file
bpy.ops.export_scene.gltf(filepath=filepath, export_format='GLB', use_selection=True)
# Delete the object from the scene
bpy.ops.object.delete()
```
Drag all the exported GLBs to the root of the pertanent folder, and then send back and let jin deal with it.
---
## Convert Mtoon to Principled BSDF
```python!
import bpy
# Get all materials in the scene
materials = bpy.data.materials
# Iterate over each material
for material in materials:
if material.node_tree:
nodes = material.node_tree.nodes
# Remove all nodes except Image Texture and Material Output
nodes_to_remove = [node for node in nodes if node.type != "TEX_IMAGE" and node.type != "OUTPUT_MATERIAL"]
for node in nodes_to_remove:
nodes.remove(node)
# Check if the material has an Image Texture node
image_texture = None
for node in nodes:
if node.type == "TEX_IMAGE":
image_texture = node
break
# If Image Texture node exists, connect it to Base Color
if image_texture:
# If Principled BSDF node doesn't exist, add it
principled_bsdf = nodes.get("Principled BSDF")
if not principled_bsdf:
principled_bsdf = nodes.new("ShaderNodeBsdfPrincipled")
# Connect Image Texture to Base Color
has_connection = False
for link in material.node_tree.links:
if link.to_node == principled_bsdf and link.to_socket.name == "Base Color":
if link.from_node == image_texture:
has_connection = True
break
# If the connection doesn't exist, create it
if not has_connection:
material.node_tree.links.new(image_texture.outputs["Color"], principled_bsdf.inputs["Base Color"])
# Check if the material has a Material Output node
material_output = None
for node in nodes:
if node.type == "OUTPUT_MATERIAL":
material_output = node
break
# If Material Output node doesn't exist, add it
if not material_output:
material_output = nodes.new("ShaderNodeOutputMaterial")
# Connect Principled BSDF to Material Output
has_bsdf_connection = False
for link in material.node_tree.links:
if link.from_node == principled_bsdf and link.from_socket.name == "BSDF":
if link.to_node == material_output and link.to_socket.name == "Surface":
has_bsdf_connection = True
break
# If the connection doesn't exist, create it
if not has_bsdf_connection:
material.node_tree.links.new(principled_bsdf.outputs["BSDF"], material_output.inputs["Surface"])
# Remove unconnected Image Texture nodes
for node in nodes:
if node.type == "TEX_IMAGE" and not node.outputs["Color"].is_linked:
nodes.remove(node)
```
### Reduce Specular
```python!
import bpy
# Get all materials in the scene
materials = bpy.data.materials
# Iterate over each material
for material in materials:
if material.node_tree:
nodes = material.node_tree.nodes
# Check if the material has a Principled BSDF node
principled_bsdf = nodes.get("Principled BSDF")
if principled_bsdf:
# Set the specular value to 0.05
principled_bsdf.inputs["Specular"].default_value = 0.05
```
---
## Export HAIR
not sure if still needed
```python=
import bpy
import os
# Set the export path
export_path = "/home/jin/Desktop/Exports/"
# Get a list of all visible objects in the scene
visible_objects = [obj for obj in bpy.context.scene.objects if obj.visible_get()]
# Iterate over each visible object and export it along with its parent hierarchy as a glTF binary file
for obj in visible_objects:
print(f"Processing object: {obj.name}")
# Check if the object is a mesh
if obj.type != 'MESH':
print(f"Object '{obj.name}' is not a mesh. Skipping...")
continue
# Get the mesh object name
mesh_name = obj.name
# Create a list to store the parent hierarchy
parent_hierarchy = []
current_obj = obj
# Traverse up the parent hierarchy until the root object or armature
while current_obj.parent:
parent_hierarchy.insert(0, current_obj.parent)
current_obj = current_obj.parent
if current_obj.type == 'ARMATURE':
break
# Export the object along with its parent hierarchy
for i, parent_obj in enumerate(parent_hierarchy):
# Set the filename for the exported glTF file based on the mesh name
filename = mesh_name + ".glb"
filepath = os.path.join(export_path, filename)
# Select the object and its parent hierarchy
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
parent_obj.select_set(True)
# Export the selected objects as a glTF binary file
bpy.ops.export_scene.gltf(filepath=filepath, export_format='GLB', use_selection=True)
print(f"Exported object: {obj.name} with parent hierarchy: {'/'.join([parent.name for parent in parent_hierarchy[:i+1]])} as {filename}")
# Deselect all objects
bpy.ops.object.select_all(action='DESELECT')
print("Deselected all objects.")
```
## Export VRM with Armature
### Old Script
```python!
import bpy
import os
import sys
# Check if a blend file argument is provided
if len(sys.argv) < 2:
print("Usage: blender -b -P script.py -- [blend_file]")
sys.exit(1)
# Set the export path
export_path = "/home/jin/Desktop/Exports/"
# Get the path to the blend file from the command line argument
blend_file = sys.argv[-1]
# Open the specified blend file
bpy.ops.wm.open_mainfile(filepath=blend_file)
# Get the correct view layer (replace 'ViewLayer' with the actual view layer name)
view_layer_name = 'ViewLayer'
view_layer = bpy.context.scene.view_layers.get(view_layer_name)
if view_layer is None:
print(f"View Layer '{view_layer_name}' not found.")
sys.exit(1)
# Set the active view layer
bpy.context.window.view_layer = view_layer
# Get a list of all visible objects in the scene
visible_objects = [obj for obj in bpy.context.scene.objects if obj.parent is None]
# Iterate over each visible object and export it as a separate VRM file
for obj in visible_objects:
# Search for an armature in the hierarchy of children
mesh = None
for child in obj.children_recursive:
if child.type == 'MESH':
mesh = child
break
# If a mesh is found, select it for export
if mesh:
print("--------------------------------------------------------------")
print()
print(mesh)
print()
# Set the filename for the exported VRM file
armature = mesh.parent
armature.data.vrm_addon_extension.spec_version = "0.0"
filename = mesh.name + ".vrm"
filepath = os.path.join(export_path, filename)
# Select the mesh for export
bpy.ops.object.select_all(action='DESELECT')
mesh.select_set(True)
# Export the mesh (VRM)
bpy.ops.export_scene.vrm(
filepath=filepath,
export_invisibles=False,
enable_advanced_preferences=False,
export_fb_ngon_encoding=False,
export_only_selections=True,
armature_object_name=obj.name
)
```
### New Script
```python!
import bpy
import os
import sys
def export_vrm(input_blend):
# Set the path to the input blend file
bpy.ops.wm.open_mainfile(filepath=os.path.abspath(input_blend))
# REMEMBER TO SET THE VIEW LAYER NAME
view_layer_name = 'ViewLayer'
view_layer = bpy.context.scene.view_layers.get(view_layer_name)
if view_layer is None:
print(f"View Layer '{view_layer_name}' not found.")
sys.exit(1)
bpy.context.window.view_layer = view_layer
# Get a list of all visible objects in the scene
visible_objects = [obj for obj in bpy.context.scene.objects if obj.parent is None]
# Iterate over each visible object and export it as a separate VRM file
for obj in visible_objects:
# Skip objects not in the specified view layer
if obj.name not in view_layer.objects:
print(f"Object '{obj.name}' is not in view layer '{view_layer_name}'. Skipping.")
continue
# Search for a mesh in the hierarchy of children
mesh = None
for child in obj.children_recursive:
if child.type == 'MESH':
mesh = child
# If a mesh is found and it's in the view layer, select it for export
if mesh and mesh.name in view_layer.objects:
# Set the filename for the exported VRM file
armature = mesh.parent
armature.data.vrm_addon_extension.spec_version = "0.0"
filename = mesh.name + ".vrm"
# Select the mesh for export
bpy.context.view_layer.objects.active = mesh
mesh.select_set(True)
# Export the mesh (VRM)
bpy.ops.export_scene.vrm(
filepath=os.path.join(export_path, filename), # Corrected line
export_invisibles=False,
enable_advanced_preferences=True,
export_fb_ngon_encoding=False,
export_only_selections=True,
armature_object_name=obj.name
)
if __name__ == "__main__":
# Check if the command line arguments are provided
if "--" in sys.argv:
argv = sys.argv[sys.argv.index("--") + 1:] # Get arguments after "--"
else:
argv = []
# Default export path
export_path = "/home/jin/Desktop/Exports"
# Ensure the export folder exists; create it if it doesn't
os.makedirs(export_path, exist_ok=True)
# Set the path to the input blend file
input_blend = os.path.abspath(argv[0]) if argv else None
if not input_blend:
print("Error: Input .blend file not provided.")
sys.exit(1)
export_vrm(input_blend)
```