feat: add batch 3D generation script with VRAM optimization
- Add batch_generate.py: two-phase pipeline (shape→texture) that loads models sequentially to avoid OOM on RTX 3080 - Fix mesh_utils.py: make bpy import lazy so load_mesh/save_mesh work without Blender installed - Phase 1: shape generation for all images, then unload - Phase 2: texture generation for all meshes, then unload - Skip already-generated outputs for resumability - Tested: 9/9 images successfully generated textured GLB models Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -14,7 +14,6 @@
|
||||
|
||||
import os
|
||||
import cv2
|
||||
import bpy
|
||||
import math
|
||||
import numpy as np
|
||||
from io import StringIO
|
||||
@@ -197,8 +196,15 @@ def save_mesh(mesh_path, vtx_pos, pos_idx, vtx_uv, uv_idx, texture, metallic=Non
|
||||
)
|
||||
|
||||
|
||||
def _get_bpy():
|
||||
"""Lazy import of bpy (Blender Python API)."""
|
||||
import bpy
|
||||
return bpy
|
||||
|
||||
|
||||
def _setup_blender_scene():
|
||||
"""Setup Blender scene for conversion."""
|
||||
bpy = _get_bpy()
|
||||
if "convert" not in bpy.data.scenes:
|
||||
bpy.data.scenes.new("convert")
|
||||
bpy.context.window.scene = bpy.data.scenes["convert"]
|
||||
@@ -206,6 +212,7 @@ def _setup_blender_scene():
|
||||
|
||||
def _clear_scene_objects():
|
||||
"""Clear all objects from current Blender scene."""
|
||||
bpy = _get_bpy()
|
||||
for obj in bpy.context.scene.objects:
|
||||
obj.select_set(True)
|
||||
bpy.data.objects.remove(obj, do_unlink=True)
|
||||
@@ -213,6 +220,7 @@ def _clear_scene_objects():
|
||||
|
||||
def _select_mesh_objects():
|
||||
"""Select all mesh objects in scene."""
|
||||
bpy = _get_bpy()
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == "MESH":
|
||||
@@ -224,6 +232,7 @@ def _merge_vertices_if_needed(merge_vertices: bool):
|
||||
if not merge_vertices:
|
||||
return
|
||||
|
||||
bpy = _get_bpy()
|
||||
for obj in bpy.context.selected_objects:
|
||||
if obj.type == "MESH":
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
@@ -235,6 +244,7 @@ def _merge_vertices_if_needed(merge_vertices: bool):
|
||||
|
||||
def _apply_shading(shade_type: str, auto_smooth_angle: float):
|
||||
"""Apply shading to selected objects."""
|
||||
bpy = _get_bpy()
|
||||
shading_ops = {
|
||||
"SMOOTH": lambda: bpy.ops.object.shade_smooth(),
|
||||
"FLAT": lambda: bpy.ops.object.shade_flat(),
|
||||
@@ -247,6 +257,7 @@ def _apply_shading(shade_type: str, auto_smooth_angle: float):
|
||||
|
||||
def _apply_auto_smooth(auto_smooth_angle: float):
|
||||
"""Apply auto smooth based on Blender version."""
|
||||
bpy = _get_bpy()
|
||||
angle_rad = math.radians(auto_smooth_angle)
|
||||
|
||||
if bpy.app.version < (4, 1, 0):
|
||||
@@ -266,6 +277,7 @@ def convert_obj_to_glb(
|
||||
) -> bool:
|
||||
"""Convert OBJ file to GLB format using Blender."""
|
||||
try:
|
||||
bpy = _get_bpy()
|
||||
_setup_blender_scene()
|
||||
_clear_scene_objects()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user