Reads Diablo II: Resurrected's .model files and exports them to glTF — skinned and animated, not
just a posed mesh — and to .m3 for the StarCraft II editor.
The .m3 exporter is the part nothing else does. It is the same one that ships in
D3ModelViewer, re-typed against a game-neutral scene model:
MD34 sections, named sequences with automatic SC2 sequence-name mapping, the alpha-mask cutout layer,
and physics.
Early days. This is a command-line tool and a library; the viewer application comes later. See the roadmap for what is built, what is next, and why.
Read .model / .gr2 |
Granny container, type tree, meshes, skeletons, vertex layouts, bone bindings |
| Assemble pieces | Pick heads/torsos/legs by name and combine several models onto one skeleton |
Read .glb / .gltf |
Anything Noesis or a DCC tool exports — including skeletons and animation clips |
Write .glb / .gltf |
Skinned, animated, with a correct bind pose |
Write .m3 |
StarCraft II, with sequences named from Diablo II's own animation modes |
| Read animations | Clips, track groups and transform tracks; 6 of Granny's 21 curve encodings |
| Inspect and scan | Answer, from a real install, the questions the roadmap depends on |
Not yet: fifteen of Granny's quantised curve encodings, .texture decoding, CASC reading, the
viewer UI. Run d2rmv curves to see how much of your install that affects; take the Noesis route for
anything it cannot decode — see below.
Needs the .NET 8 SDK or newer.
dotnet build -c Release
The tool is src/D2RModelViewer.Cli/bin/Release/net8.0/d2rmv.
Point it at your own Diablo II: Resurrected install, extracted to loose files (with D2RExtractor or CascView).
# What does this file actually contain?
d2rmv inspect Data/hd/monsters/skeleton/skeleton.model
d2rmv info Data/hd/monsters/skeleton/skeleton.model
# What does the whole install use? Versions, compression codecs, failures, bone counts.
d2rmv scan "C:/Diablo II Resurrected"
# Which animation curve encodings does it use, and how much would each one buy?
d2rmv curves "C:/Diablo II Resurrected"
# Export
d2rmv gltf skeleton.model -o skeleton.glb
d2rmv m3 skeleton.model -o skeleton.m3 --scale 0.02Diablo II builds a character out of named component pieces — head, torso, legs, arms, hands, shield —
and Resurrected's HD art keeps that structure. So a character is usually several meshes, often across
several .model files, and exporting one alone gives you a floating head.
d2rmv parts lists what you have:
$ d2rmv parts barb_HD.model barb_TR.model barb_LG.model barb_SH.model
4 piece(s) across 4 file(s), 5 bones on the merged skeleton
# slot piece verts tris source
1 head head_mesh 4 2 barb_HD.model
2 torso chest_mesh 4 2 barb_TR.model
3 legs leg_mesh 4 2 barb_LG.model
4 shield shield_mesh 4 2 barb_SH.model
Then pass the files you want to gltf or m3 and they are merged onto one skeleton — bones are
unified by name, and each piece's vertex weights are remapped onto the result:
d2rmv m3 barb_*.model -o barbarian.m3 --exclude shield --scale 0.02
d2rmv gltf barb_*.model -o bust.glb --parts head,torso--parts and --exclude match a piece by:
| Example | |
|---|---|
number, as listed by parts |
--parts 1,3 |
| exact mesh name | --parts head_mesh |
| glob | --parts "chest*" |
| Diablo II component code | --parts HD,TR,LG |
| slot name | --parts head,torso,legs,arms,hands,shield,weapon |
| the file it came from | --parts barb_HD |
Each piece stays a separately named mesh in the export, so it is still a distinct object in Blender and still identifiable if you re-import it. If two pieces disagree about a shared bone — one puts the spine somewhere else — the export says so rather than quietly picking one.
Granny has 21 animation curve encodings and this reads six of them; the rest quantise their data in ways
that need confirming against real files before they can be implemented safely (see
GR2-FORMAT.md). d2rmv curves reports what your install uses.
Where a clip will not decode, Noesis already reads it, so let Noesis do the reading:
# In Noesis: export the .model to .gltf/.glb with its animations.
d2rmv m3 skeleton.glb -o skeleton.m3 --scale 0.02d2rmv maps each clip onto a StarCraft II sequence name using Diablo II's own animation modes —
NU becomes Stand, WL becomes Walk, A1 becomes Attack, DT becomes Death, and so on —
so the sequences arrive in the SC2 editor already named the way the editor expects.
--scale 0.02 is the D3 tool's default and a reasonable starting point for StarCraft II character
heights. d2rmv info prints the model's declared units per metre, which Granny records, so the right
number is a division rather than a guess.
This reads your own installed copy of Diablo II: Resurrected. It ships no game assets and cannot download any. Do not redistribute exported assets.
Granny is RAD Game Tools / Epic middleware. This project contains a clean-room managed reader and does
not use or redistribute granny2.dll.
Diablo and StarCraft are trademarks of Blizzard Entertainment, Inc. This project is not affiliated with or endorsed by Blizzard.
MIT — see LICENSE. Covers this project's code only, not any game content.