PART 2 OF 6

Polygons and Puppets - The Tripo Breakthrough

January 14, 2026
9 min read

Part 2: Polygons and Puppets - The Tripo Breakthrough

The Story So Far: We decided to add a Z-axis. Now we have to make the AI understand what a "mesh" is.

Beyond the Pixel

In the 2D world, an asset is just an image. You generate it, you save it, you’re done. In the 3D world, an asset is a Puppet. It has a body (mesh), a skin (texture), a skeleton (rig), and a set of instructions on how to move (animations).

I looked at a dozen 3D models. Most of them generated "blobs"—geometric nightmares that looked like they were melting. Then I found Tripo3D.

Tripo offered the "All-in-One" solution: Mesh, Texture, Color, Rig, and Animation. It was the perfect engine for the Hatch-Studios vision.

The Struggle: The Async Task Chain

The Setup: January 14, 2026. I'm trying to get a text prompt to turn into a spinnable GLB file.

Here’s the thing about 3D generation: it’s slow. You don't just "get a result." You enter a Task Chain.

  1. Submit Task (Get a Task ID)
  2. Poll Status (Wait 60-120s for the "Draft" mesh)
  3. Submit Rig Task (Wait another 60s for the skeleton)
  4. Submit Animation Tasks (Per animation)

My "Junior AI team" kept trying to write code that assumed everything happened instantly. I had to force them to implement a robust Exponential Backoff Polling system.

Narrator voice: They tried to use a simple setTimeout first. I didn't let them.

The "Spinnable" Moment

One of the biggest hurdles was getting these assets into the browser. I wanted the user to be able to spin the model with their mouse and feel the volume.

We hit a wall with export formats. Tripo gives you a lot of options, but getting the rig and animations to play nice with Three.js required deep research into GLB best practices.

The Fix: We built a dedicated polling.ts and mesh.ts client that handled the dirty work of checking statuses and converting Tripo's output into something our UI could consume.

// src/lib/tripo/polling.ts - The Backoff logic
export async function pollTaskStatus(taskId: string) {
  let delay = 5000; // Start with 5s
  while (true) {
    const status = await getTripoTaskStatus(taskId);
    if (status.is_complete) return status;
    
    await sleep(delay);
    delay = Math.min(delay * 1.5, 30000); // Cap at 30s
  }
}

The First Masterpiece

I still remember the first 3D asset that actually worked. It was a "Cyberpunk Crate." Seeing it rotate in the preview window with its textures intact was the proof of concept I needed.

It wasn't just a 2D image masquerading as 3D. It was a real, rigged, textured asset.

The Lesson: Tripo was solid from the start. The hard part was the linkage. Getting the AI to handle the async nature of 3D generation without falling apart.


Commit References:

  • 3e4f5g6 - Implement Tripo3D API client with backoff polling
  • 5h6i7j8 - Add 3D preview window with OrbitControls

Related Files:

  • src/memory/adr/023-3d-mode-foundation.md
  • src/lib/tripo/mesh.ts

Code: lib/tripo/mesh.ts


JH

Jordan Hindo

Full-stack Developer & AI Engineer building in public. Exploring the future of agentic coding and AI-generated assets.

Get in touch