explainx.ainewsletter3.5k
TrendingNewsPathwaysSkills
Pricing
explainx.ai

Upskill in AI — 16 free pathways, live workshops & bootcamps, and 50+ courses from practitioners. Plus the skills, tools, and MCP servers to practice on.

follow us

follow on google

Add explainx.ai as a preferred source

corporate training

support@explainx.ai

get started

Find your pathTake Free Evaluation

learn

mind: share how you thinkpathways — start freeworkshopsbootcampscoursescertificationsmock testsexplainx universitycorporate traininglearn skills & mcp

discover

skillsmcp serversexplainx mcptoolsagentsllmsdesignsdictionaryagi trackerranks

company

aboutvisionmissionteaminstructorsteach on explainxpartnershipscommunityhackathonscareers

content

daily AI newsstate of AI — live resultsblogreleasespromptsgeneratorsresource libraryfor LLMsexplainx.ai kids

solutions

all solutionsdeveloper upskillingmarketing upskillingproduct manager upskillingleadership upskilling

newsletter · weekly

Get AI news, tools, and insights in your inbox.

supportcontactprivacytermsdata rightshow we create contentsubmission guidelines

© 2026 AISOLO Technologies Pvt Ltd

On this page

  • TL;DR
  • The setup
  • Inspect the mesh before you write any rigging code
  • Why "593 disconnected parts" makes auto-riggers refuse
  • Four ways we tore his arms off
  • The one step: merge by distance
  • Then stop hand-writing weights and use bone heat
  • The headless Blender bug that ate the afternoon
  • Removing the ground without removing the shoes
  • The final pipeline
  • We decided arms should not move
  • What people are asking
  • Honest limitations
  • Where this leaves the pipeline
  • Related on explainx.ai
← Back to blog

explainx / blog

Rigging an AI Image-to-3D Character: The One Blender Step That Makes It Work

Image to 3D, Game Development, Blender, Rigging, Godot, bunpav

An AI-generated GLB reported 593 disconnected shells and refused to rig. One merge-by-distance pass collapsed it to 4 and everything worked. The full Blender pipeline, with numbers.

Sep 3, 2026·10 min read·Yash Thakker
add explainx.ai
go deep
Rigging an AI Image-to-3D Character: The One Blender Step That Makes It Work

We generated a character from one concept image, dropped the GLB into a Godot game, and had him standing on a railway platform in about ten minutes. Making him walk took the rest of the day, four failed approaches, and one Blender operation we should have run first.

This post is that day, in order, with the numbers. If you are wiring AI 3D generation into a real game pipeline — the neural counterpart to the code-first lane img2threejs and bunpav work in — the short version is: the mesh is riggable, and it does not look riggable, and one line separates those two facts.

Weekly digest3.5k readers

Catch up on AI

Curated AI updates on agents, skills, and MCP — delivered to your inbox. Unsubscribe anytime.

TL;DR

table · 2 cols
QuestionAnswer
Is an AI image-to-3D mesh riggable?Yes — after one merge-by-distance pass. Not before.
Why does it report 593 disconnected parts?Unwelded coincident vertices, one pair per UV seam. Not real disconnection.
The one commandbpy.ops.mesh.remove_doubles(threshold=0.0001) → 593 islands became 4
Then what?Bone-heat weighting (ARMATURE_AUTO). It needs the welded surface to diffuse across.
Do hand-written vertex weights work?No. Four segmentation strategies, four shears. Stop writing your own.
Does the ground come with it?Yes. Detect flat and wide and at-the-floor — all three, or you delete the shoes.
Biggest time sinkobject.transform_apply silently doing nothing in headless Blender.
Do arms need to swing?We decided no. Legs walk, torso leans, hands hold the tea.

The setup

The game is Mumbai Local, a first-person courier game on Mumbai's suburban railway. NPCs are normally procedural — shared rig, primitive parts, palette colours. Cheap and a bit anonymous.

We wanted one named character to read as somebody: Havaldar Gadbad, the railway police constable who takes your report and then tells you it is not his station. The plan was: generate a concept in the game's own art style, run image-to-3D, auto-rig onto the game's existing skeleton, let the animation code drive it.

Generation was excellent. Rigging is where this post lives.

Concept art and T-pose reference for a low-poly Indian railway police constable

Inspect the mesh before you write any rigging code

We did this too late. A headless Blender script over the GLB reported:

snippet
OBJECTS 1 ['textured_mesh.obj']
BBOX x -0.889..0.881  y -0.332..0.340  z -0.998..0.989
PARTS 593
  verts= 1198  dx=0.831 dy=0.215 dz=0.590  base_z=0.019
  verts= 1187  dx=0.713 dy=0.672 dz=0.110  base_z=-0.963
  verts= 1122  dx=0.169 dy=0.478 dz=0.968  base_z=-0.948
  verts= 1115  dx=0.717 dy=0.672 dz=0.035  base_z=-0.998

Three things in that dump:

  • 593 loose parts. This is the number that sent us down the wrong road for six hours.
  • Rows 2 and 4 are the ground. Wide (0.71 × 0.67), flat (dz 0.11 and 0.035), at the very bottom (base_z ≈ -0.98). The generator posed him on a plinth and welded it in.
  • 40,000 triangles, against roughly 25 primitives for the game's procedural crowd bodies.

Why "593 disconnected parts" makes auto-riggers refuse

Adobe publishes Mixamo's auto-rigger requirements, and the raw export violates most of them:

table · 2 cols
Mixamo requiresRaw export
Single mesh, no spaces between parts593 reported islands
No floating parts disjoined from the bodyground slab, fragments
No other content in the fileplinth included
No large propstea glass and clipboard
Clean, error-free meshopen shells, split seams

These are not arbitrary. Every skinning algorithm assumes neighbouring vertices are connected so a weight can propagate between them. Break connectivity and the assumption dies — which is what happens on the raw import, and exactly why the fix below works.

Four ways we tore his arms off

We wrote our own Blender rigger, because the game's rig is unusual: rigid parts on bone attachments, not smooth skinning. So we started the same way — every vertex weighted 1.0 to exactly one bone.

  1. Plane cuts. Classify each vertex by bounding-box fractions. Legs walked; the arms smeared, because he holds tea and his forearm sits inside the body's own width.
  2. Fold the arms into the spine. Weight them to the torso so the upper body moves as one. This worked and looked fine — but it is a workaround, not a rig.
  3. T-pose source. We regenerated the concept in a strict T-pose with empty hands. Segmentation improved; the arms still fanned into flat sheets.
  4. Cylinder around the arm axis. A plane is the wrong shape for a limb. Arm vertex counts doubled from 358 to 802 — the whole sleeve was finally included — and it still fanned.

At this point we concluded the mesh was unriggable and started writing that up. That conclusion was wrong.

The one step: merge by distance

The 593 shells were never disconnected. They were coincident vertices that had never been welded — every UV and normal seam is two or more vertices at one position, and a loose-parts count reads each side as its own island.

One Blender operation, measured across thresholds:

snippet
as imported            islands=593   verts=26843   tris=40000
merge dist 0.0001      islands=4     verts=19963   tris=39980
merge dist 0.0010      islands=4     verts=19862   tris=39776
merge dist 0.0050      islands=3     verts=19073   tris=38239

593 islands to 4, at a threshold of a tenth of a millimetre, for a 25% drop in vertex count and 20 triangles. Not a single surface moved. In script form:

python
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="SELECT")
bpy.ops.mesh.remove_doubles(threshold=0.0001)
bpy.ops.object.mode_set(mode="OBJECT")

Run this before anything else. It is the difference between a mesh that cannot be rigged and one that rigs itself.

Then stop hand-writing weights and use bone heat

With a connected surface, Blender's own bone-heat diffusion works — and it is the right algorithm:

python
bpy.ops.object.select_all(action="DESELECT")
body.select_set(True)
rig.select_set(True)
bpy.context.view_layer.objects.active = rig
bpy.ops.object.parent_set(type="ARMATURE_AUTO")

The difference is categorical. A hard one-bone-per-vertex assignment shears at every boundary, and smoothing afterwards cannot recover a gradient that was never computed. Bone heat diffuses a weight across the surface, so a hip bends instead of tearing. It had been failing for us not because it is a bad algorithm but because it had nothing to diffuse across.

Four frames of a low-poly police constable walking in-engine, legs alternating, tea held steady

The headless Blender bug that ate the afternoon

Worth its own section, because it will happen to you.

In a blender -b -P script, bpy.ops.object.transform_apply() can silently do nothing. It reads the evaluated dependency graph; in a script where nothing has evaluated, it returns without error and changes nothing. No exception, no warning.

A --yaw 180 flag to turn a backwards model appeared to work and did not. Adding bpy.context.view_layer.update() did not help. The diagnostic that caught it was measuring an asymmetric feature before and after — the cap peak juts forward, so the mean Y of the top 15% of vertices should flip sign:

snippet
BEFORE head_mean_y 0.0099  n=3068
AFTER  head_mean_y 0.0099  n=3068     # unchanged: the rotation never applied

Skip the operator and transform the data:

python
from mathutils import Matrix

def bake_transform(obj):
    """Fold the object transform into its vertices and reset it to identity."""
    obj.data.transform(obj.matrix_world)
    obj.data.update()
    obj.matrix_world = Matrix.Identity(4)

obj.data.transform(Matrix.Rotation(math.radians(180), 4, "Z"))
obj.data.update()

Mesh.transform() needs no operator context, no selection, and no depsgraph. In headless Blender, prefer data manipulation over bpy.ops for anything you cannot visually verify.

Removing the ground without removing the shoes

The plinth is recognised by three conditions together:

python
flat     = dz < 0.16 * height
wide     = max(dx, dy) > 0.45 * width
grounded = base_z < floor + 0.06 * height
if flat and wide and grounded:
    drop(part)

Our first version compared each part's height against the tallest part's and used a 3% threshold. It threw away 434 harmless fragments and left the slab exactly where it was. A later version added "flat and grounded and small" to catch crumbs — and deleted the character's shoes, which are flat, grounded, and small after decimation. All three conditions, no looser.

Run the ground removal before the weld, while the slab is still its own island. Welding joins it to the shoes and there is nothing left to drop.

The final pipeline

bash
tools/blender/rig_npc.sh character.glb \
  --tris 14000 --arms none --yaw 180

In order:

  1. Import and join into one object; bake the transform into the mesh data
  2. Drop the ground (flat + wide + grounded), while it is still separate
  3. Merge by distance at 0.0001 — the step everything depends on
  4. Decimate to a triangle budget (40,000 → 14,000 was visually identical; 6,000 showed faceting)
  5. Scale to character height and stand on the floor
  6. Build the armature with your engine's bone names
  7. Bone-heat weight via ARMATURE_AUTO
  8. Export GLB with skins

We decided arms should not move

Even with a welded mesh and heat weights, auto-segmenting an arm stayed unreliable — the shoulder fans whichever way the blend is shaped, because "where does the arm stop and the sleeve start" has no clean answer on a generated mesh.

So we stopped trying. Concepts are generated in a natural standing pose holding their props, and rigged with arms fixed. Legs walk, the torso leans, the head moves, and the constable strolls the platform with his tea held steady. It reads correctly and cost nothing — and for a character seen at platform distance, arm swing was never the thing carrying the performance.

That is a genuine finding, not a consolation prize: decide which limbs need to move before you rig, and rig only those.

What people are asking

"Is the raw mesh useless without rigging?" Not at all. Our static modelled constable looked dramatically better than the eight procedural NPCs beside him. Most named background characters barely move — ship them static and spend the rigging budget elsewhere.

"Does this apply to props and environment art?" Barely. Props have no skeleton, so none of this matters. Image-to-3D for a crate, a signboard, or a bench is production-ready today. Rigging is where the constraint bites, which is why the code-first procedural lane stays attractive for objects needing pivots and sockets.

"Should I just use the generator's own auto-rig?" If it has one, yes — Meshy and Tripo both ship retopology and auto-rigging. Our route matters when you need your engine's exact skeleton, which is the case here.

"How does this compare to procedural 3D generation?" Different jobs. Procedural code gives diffable, parameterised geometry with named sockets — see bunpav's procedural 3D and game audio lab and the Hop Earth-style driving game guide. Neural image-to-3D gives a characterful one-off you could not hand-author in the time. Characters lean neural; systems lean procedural.

Honest limitations

  • Arm segmentation is still unsolved here. We chose not to need it. If your character must gesture, budget for manual weight painting or a purpose-built auto-rigger.
  • Merging by distance averages split UVs. At 0.0001 the visual cost was nil for us, but a mesh with hard texture seams at those vertices may show smearing.
  • Rigid vs smooth skinning is a style choice. Our engine uses bone attachments, so seams are acceptable.
  • Triangle budgets are art-direction-specific. 14,000 suits a chunky low-poly style at close range.

Where this leaves the pipeline

AI image-to-3D is production-ready for game characters today — but the first thing you do to the mesh decides whether anything after it works. Inspect the loose-part count, weld, then rig. One line of Blender Python would have told us on minute one what four rigging attempts took six hours to say.

Related on explainx.ai

  • img2threejs: Photo-to-Procedural Three.js — and bunpav's Code-First Lane — the procedural counterpart to this neural lane
  • bunpav: Procedural 3D and Game Audio Lab — where the code-first 3D tooling lives
  • How to Build a Hop Earth-Style AI Driving Game — a full game build with AI-assisted assets
  • Tencent Hunyuan HY-World 2 and World Mirror 3D World Model — where generative 3D goes beyond single objects
  • What Are Agent Skills? Complete Guide — packaging a pipeline like this as a reusable skill
  • Claude Opus 5: Top 10 Game Prompts — prompting patterns for game work
  • WebGPU Complete Guide — the rendering side of browser 3D

Official documentation

  • Mixamo auto-rigger requirements — Adobe
  • Blender Mesh.transform() API
  • Meshy AI retopology guide
  • Tripo: rigging an AI-generated character for Mixamo
  • Mumbai Local — the game this pipeline was built for

Vertex counts, island counts, and tool behaviour here were measured on Blender 5.2.1 LTS and Godot 4.7.2 in September 2026. Image-to-3D generators iterate quickly — re-measure against your own export before committing to thresholds.

Spotted something out of date? Let us know.
Yash Thakker

Written by

Yash Thakker

Yash is an AI expert with over 300K learners. Join his workshops →

Related posts

Jul 20, 2026

img2threejs: Photo-to-Procedural Three.js Skill — and How bunpav Uses the Code-First Lane

img2threejs is an MIT agent skill that turns a single product photo into diffable Three.js factory code with pivots, sockets, and colliders — not a multi-MB GLB. explainx.ai explains the staged pipeline, token economics, and how bunpav's browser studio uses the procedural lane alongside credit-based neural photo-to-3D.

Aug 31, 2026

img2threejs v1.5.1: One Photo to a Rigged, Animated Three.js Fighter

img2threejs v1.5.1 ships the Character Update: a 2D reference image becomes a rigged, animated Three.js fighter with measured punch VFX, sweat particles, and 19 combat clips — pure TypeScript in the browser, no Blender workflow. explainx.ai breaks down the GLB-measurement pipeline, how it differs from neural mesh tools, and what web-game builders should steal.

Sep 2, 2026

Top 10 Neural Rendering Use Cases Beyond DLSS 5's Beauty Filter

The leaked DLSS 5 library turned Cyberpunk, GTA 5 and Dark Souls 3 into uncanny valley clips, and the discourse collapsed into "AI slop or not." That framing buries the actual question: what is a learned post-render stage genuinely good at? Ten use cases, ranked by how well the technique's strengths match the job.