Update app.py
Browse files
app.py
CHANGED
|
@@ -275,7 +275,8 @@ def generate_3d(
|
|
| 275 |
# 2. Process Mesh
|
| 276 |
progress(0.7, desc="Processing Mesh...")
|
| 277 |
mesh = outputs[0]
|
| 278 |
-
# Aggressive simplification to prevent CUDA errors during post-processing
|
|
|
|
| 279 |
mesh.simplify(1000000)
|
| 280 |
|
| 281 |
# 3. Export to GLB
|
|
@@ -283,7 +284,7 @@ def generate_3d(
|
|
| 283 |
|
| 284 |
grid_size = latents[2]
|
| 285 |
|
| 286 |
-
#
|
| 287 |
try:
|
| 288 |
glb = o_voxel.postprocess.to_glb(
|
| 289 |
vertices=mesh.vertices,
|
|
@@ -302,7 +303,7 @@ def generate_3d(
|
|
| 302 |
)
|
| 303 |
except RuntimeError as e:
|
| 304 |
print(f"Warning: Post-processing failed with remesh=True. Error: {e}")
|
| 305 |
-
print("Retrying with remesh=False...")
|
| 306 |
glb = o_voxel.postprocess.to_glb(
|
| 307 |
vertices=mesh.vertices,
|
| 308 |
faces=mesh.faces,
|
|
@@ -323,7 +324,8 @@ def generate_3d(
|
|
| 323 |
timestamp = now.strftime("%Y-%m-%dT%H%M%S")
|
| 324 |
glb_path = os.path.join(user_dir, f'trellis_output_{timestamp}.glb')
|
| 325 |
|
| 326 |
-
# extension_webp=False ensures compatibility with Rerun/Standard Viewers
|
|
|
|
| 327 |
glb.export(glb_path, extension_webp=False)
|
| 328 |
|
| 329 |
# --- Rerun Visualization Logic ---
|
|
@@ -341,10 +343,15 @@ def generate_3d(
|
|
| 341 |
rr.init("TRELLIS-3D-Viewer", recording_id=run_id, spawn=False)
|
| 342 |
rec = rr
|
| 343 |
|
| 344 |
-
# 1.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 345 |
rec.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True)
|
| 346 |
-
|
| 347 |
-
#
|
|
|
|
| 348 |
try:
|
| 349 |
rec.log("world/axes/x", rr.Arrows3D(vectors=[[0.5, 0, 0]], colors=[[255, 0, 0]]), static=True)
|
| 350 |
rec.log("world/axes/y", rr.Arrows3D(vectors=[[0, 0.5, 0]], colors=[[0, 255, 0]]), static=True)
|
|
@@ -352,31 +359,10 @@ def generate_3d(
|
|
| 352 |
except Exception:
|
| 353 |
pass
|
| 354 |
|
| 355 |
-
#
|
| 356 |
-
#
|
| 357 |
-
rec.log("world/
|
| 358 |
|
| 359 |
-
# 3. CREATE ROTATION ANIMATION (Auto-Rotate)
|
| 360 |
-
# We animate the 'anchor' transform over a timeline
|
| 361 |
-
progress(0.98, desc="Generating Rotation Animation...")
|
| 362 |
-
|
| 363 |
-
num_frames = 240 # 240 frames for one full loop
|
| 364 |
-
for i in range(num_frames):
|
| 365 |
-
# Set the time cursor
|
| 366 |
-
rec.set_time_sequence("frame", i)
|
| 367 |
-
|
| 368 |
-
# Calculate rotation angle (0 to 360 degrees)
|
| 369 |
-
angle_rad = (i / num_frames) * 2 * np.pi
|
| 370 |
-
|
| 371 |
-
# Log the rotation transform for the anchor
|
| 372 |
-
# This rotates the model around the Y-axis
|
| 373 |
-
rec.log(
|
| 374 |
-
"world/anchor",
|
| 375 |
-
rr.Transform3D(
|
| 376 |
-
rotation=rr.RotationAxisAngle(axis=[0, 1, 0], radians=angle_rad)
|
| 377 |
-
)
|
| 378 |
-
)
|
| 379 |
-
|
| 380 |
# Save the Rerun recording (.rrd)
|
| 381 |
rrd_path = os.path.join(user_dir, f'trellis_output_{timestamp}.rrd')
|
| 382 |
rec.save(rrd_path)
|
|
|
|
| 275 |
# 2. Process Mesh
|
| 276 |
progress(0.7, desc="Processing Mesh...")
|
| 277 |
mesh = outputs[0]
|
| 278 |
+
# FIX: Aggressive simplification to prevent CUDA errors during post-processing
|
| 279 |
+
# This keeps the mesh manageable for the fill_holes kernel
|
| 280 |
mesh.simplify(1000000)
|
| 281 |
|
| 282 |
# 3. Export to GLB
|
|
|
|
| 284 |
|
| 285 |
grid_size = latents[2]
|
| 286 |
|
| 287 |
+
# Safe export with fallback if high-quality hole filling fails
|
| 288 |
try:
|
| 289 |
glb = o_voxel.postprocess.to_glb(
|
| 290 |
vertices=mesh.vertices,
|
|
|
|
| 303 |
)
|
| 304 |
except RuntimeError as e:
|
| 305 |
print(f"Warning: Post-processing failed with remesh=True. Error: {e}")
|
| 306 |
+
print("Retrying with remesh=False (Standard mesh generation)...")
|
| 307 |
glb = o_voxel.postprocess.to_glb(
|
| 308 |
vertices=mesh.vertices,
|
| 309 |
faces=mesh.faces,
|
|
|
|
| 324 |
timestamp = now.strftime("%Y-%m-%dT%H%M%S")
|
| 325 |
glb_path = os.path.join(user_dir, f'trellis_output_{timestamp}.glb')
|
| 326 |
|
| 327 |
+
# FIX: extension_webp=False ensures compatibility with Rerun/Standard Viewers
|
| 328 |
+
# This solves the "Missing data" and "Unsupported extension" errors.
|
| 329 |
glb.export(glb_path, extension_webp=False)
|
| 330 |
|
| 331 |
# --- Rerun Visualization Logic ---
|
|
|
|
| 343 |
rr.init("TRELLIS-3D-Viewer", recording_id=run_id, spawn=False)
|
| 344 |
rec = rr
|
| 345 |
|
| 346 |
+
# 1. OPTIMIZATION: Clear the view to avoid ghosting
|
| 347 |
+
rec.log("world", rr.Clear(recursive=True), static=True)
|
| 348 |
+
|
| 349 |
+
# 2. OPTIMIZATION: Set View Coordinates
|
| 350 |
+
# GLB files are commonly Right-Hand, Y-Up. This ensures the model stands up.
|
| 351 |
rec.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True)
|
| 352 |
+
|
| 353 |
+
# 3. OPTIMIZATION: Add Axes Helpers
|
| 354 |
+
# Visual cues for orientation (X=Red, Y=Green, Z=Blue)
|
| 355 |
try:
|
| 356 |
rec.log("world/axes/x", rr.Arrows3D(vectors=[[0.5, 0, 0]], colors=[[255, 0, 0]]), static=True)
|
| 357 |
rec.log("world/axes/y", rr.Arrows3D(vectors=[[0, 0.5, 0]], colors=[[0, 255, 0]]), static=True)
|
|
|
|
| 359 |
except Exception:
|
| 360 |
pass
|
| 361 |
|
| 362 |
+
# 4. Log the 3D Model
|
| 363 |
+
# Use Asset3D with 'path' to embed the GLB efficiently
|
| 364 |
+
rec.log("world/model", rr.Asset3D(path=glb_path), static=True)
|
| 365 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
# Save the Rerun recording (.rrd)
|
| 367 |
rrd_path = os.path.join(user_dir, f'trellis_output_{timestamp}.rrd')
|
| 368 |
rec.save(rrd_path)
|