One Minute Game Review by The Happy Friar:
Also on Rumble:

idTech 4 (aka Doom 3 tech) Discord Server!

Main Menu

Taking content requests!

Started by Zombie, October 10, 2014, 01:39:34 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

The Happy Friar

I use Blender 2.49b a lot.  Once you put the script in the proper folder it should either be "file import md5 (or similar) or you might need to load the script in the script window.  What script did you get?  I only know where to get the ones that load the released D3 models.


I did a bit of digging to find some of the older importers for Blender.

Here they are:

However, I can't get any of them to work, I get a weird error, don't know why though.

Edit: It seems even these are meant for MD5 version 10, and not MD5 version 6

After a bit of digging, all I found about MD5 version 6 is the following ===================================================
Unofficial DoomIII model specs v0.1

Trevor Wilkin -

The md5mesh and md5anim files are in plain text and so fairly little
explanation is needed as to how to load them. The trickiest part is probably
the binding of the mesh to the skeleton itself.

Here is a quick rundown of the file.


MD5Version 6
commandline "mesh maps/fred/bathroom/SCENE1.mb -dest maps/fred/bathroom/scene1fatmesh.md5mesh -game Doom -prefix FATTY_ -range 1 2"

Is an example of what you will see at the top of every model file. The version
number is useful for a sanity check since I imagine the files wont be in
plain text come the release, and the commandline is useless to us, but it
looks like the parameters used to convert the maya binaries into md5meshs.


This is the start of the useful data. First you can expect to read
"numbones %i" where the integer or dword read is the number of bones of the
following format...

bone %i {
name "%s"
bindpos %f %f %f
bindmat %f %f %f %f %f %f %f %f %f
[parent "%s"]

The first integer read should match with the bone number, this is just another
sanity check since the bones should all be in order. The first string is the
name of this bone/joint and the last string (which doesn't always exist in the
bone) is the parents name. The [ ] brackets are just there to show that line
is optional and they don't exist in the file.

The bindpos and bindmat are the initial matrix values for the bone. These
values are useful for getting the model into the bind pose, but will be pretty
much ignored once you move onto animations because the new matrices will be
built from that data. I found it best to keep the bindpos and bindmat in
separate matrices and vectors rather than building a single matrix.


After reading "nummeshes %i" you can expect to read that many mesh chunks
which should be laid out as follows:

mesh %i { // Integer should be mesh number and in order
shader "%s" // String represents the base texture for this
// mesh.

numverts %i // The number of vertices to follow
vert %i %f %f %i %i // There should be one of these lines for every
// vert. The parameters are vert number,
// texture U, texture V, blend index, blend
// count

numtris %i // The number of triangles to follow
tri %i %i %i %i // There should be one of these lines for every
// triangle. The parameters are triangle number
// and then the three vertex offsets forming the
// triangle. There are indices into the verts.

numweights %i // The number of weights to follow
weight %i %i %f %f %f %f // There should be one of these lines for every
// weight. The parameters are weight number, the
// bone this weight is for, the bias factor and
// the X,Y,Z weights.

And that's pretty much it.


Below is a snip of code you could use to skin DoomIII models, it assumes some
basic math classes and so on... but that shouldn't be too hard to pickup.

void Bind()
Vector3 pos;
for (DWORD i=0; i<m_Header.NumberOfMeshes; i++)
MD5Mesh& mesh = m_Meshes[i]; // Get the current mesh
MD5Vert* vertices = mesh.Vertices; // Get the vertices

for (DWORD j=0; j<mesh.NumberOfVerts; j++) // For every vert in the mesh
MD5Vert& v = vertices[j];
MD5VertWeight& vw = mesh.VertexWeights[j]; // Find the vert and the weight

v.Pos = Vector3::Zero;
for (DWORD k=0; k<vw.WeightCount; k++) // For all the weights
MD5Weight& w = mesh.Weights[vw.WeightIndex+k];
MD5Bone& b = m_Bones[w.Bone];

pos = w.Pos * b.BindMatrix; // Transform the position by the matrix
v.Pos += (pos + b.BindPos) * w.T; // Combine the weights


The base texture name can be found by reading the shader string in the mesh
structure. This can sometimes be the absolute texture name, but more often you
need to append certain letters to get all the useful textures. Here is an

shader "P:/Doom/base/models/monsters/zombie/fatty/fatty.tga"

If you check this directory, you'll find there are no textures with that name,
however there are 4 textures with very similar names:


The two most important textures for now are the _d and _local textures that
encode the detail and normal information. Just using the detail texture alone
will look very ugly because DoomIII uses a very clever technique by which a
high polygon count model can be approximated to a low polygon model and
a normal map. The simplest way to use this texture is to perform a dot product
in your pixel shaders (or set the texture stage states to do so).

This is an example pixel shader to do just that... Note that c0 is a light
vector set using d3ddevice->SetPixelShaderConstant(F).



;Use Two textures
tex t0 ; Diffuse map
tex t1 ; Normal map

;Dot product of c0 with normal map to get light amount, modulate with diffuse
dp3_sat r0.rgb, t1_bx2, c0
mul r0.rgb, t0, r0



Assuming all has gone well, you should have an ugly looking zombie or fatguy
standing with his arms stretched out. Now it's time to animate the model.

For every model with animation there should be a .md5anim file. Chances are
there are a bunch of them in a directory with the same name as your model.

The format of that file is as follows:


This is the same as the model header, check for version 6 and ignore the
command line.


After reading "numchannels %i" you can expect to read that many of the
following chunks:

channel %i {
joint "%s" // What joint to animate
attribute "%s" // What animation this channel encodes
starttime %f
endtime %f
framerate %f // The FPS of this animation. Usually 24

strings 0 // Number of strings, unknown use and always zero

range %i %i
keys %i // The number of keys (the number of floats to follow)
%f ..... // A float for every key

The most important information here is the attribute, key data and joint
name. When you read this data in, it is a good idea to search for the joint
and store a pointer to it. You will probably find 2 joints that don't exist
in the channels, boundsMin and boundsMax... either create these joints or
ignore the first 2 channels. Joints and bones are the same.

Now for your update and this is the tricky bit. For every channel you have
read in, using the start and end time (and your internal animation counter)
decide on which key in the range of keys for that channel you should use.
For example, if you are half way between the start and end time, you are also
half way through the keys.

After you have the key, using the attribute, which will be one of the
following: x,y,z,yaw,pitch,roll, store the key in the bone. I found it useful
to have an array of 6 floats per bone for just this purpose. In the code
sample below, you'll see it's called Attrib. The first three parameters are
x,y,z and the last are the rotations.

After you have been through all channels and set all attributes for all bones,
you can loop through the bones and do something similar to this...


Matrix mat,matX,matY,matZ;
for (DWORD i=0; i<m_Header.NumberOfBones; i++)
mat = matZ * matX * matY;
if (m_Bones[i].Parent)
m_Bones[i].BindMatrix = mat * m_Bones[i].Parent->BindMatrix;
m_Bones[i].BindPos += m_Bones[i].Parent->BindPos;
mat = mat * matX;
mat._33 = -mat._33;
m_Bones[i].BindMatrix = mat;


This code basically transforms a bone by it's parent if there is one. If there
isn't, it assumes the joint is the origin and does some conversions to get the
joint into the D3D coordinate system.


I hope this doc and code proves useful, if so just mention my name somewhere
and we'll call it quits k? If not, or you see something wrong... feel free to
give me a shout.




GodOfGaming from has managed to convert the DOOM 3 Alpha Shotgun to the retail DOOM 3.

Quote from: GodOfGamingI kind of managed to get it working, though it's not perfect. While the file format is very different, it's still saved in plain text. I couldn't do anything about the animations, they were too different, but the mesh code was fairly similar, so I went ahead and replaced it onto the final D3 shotgun's skeleton and animations. The end result is not perfect because the final shotty skeleton doesn't have bones for the shell eject thingy, so it ended up missing. Anyways, here's some screenies of the result


Quote from: GodOfGamingI'd like to have the shell eject port intact even if it's not animated too, it looks pretty ugly without it, but it's not as simple as it sounds. The shell eject port is made up from 2 parts, and these 2 parts have their own bones in the original skeleton, and those bones are missing in the final skeleton. I tried attaching them to different bones, but the 2 parts ended up sticking out of the gun in various different places. Here's how it looked when I tried to attach them to the shotty body's main bone:

you can see them sticking out below the place where they should be. I'm not even sure if they're scaled correctly :D Someone will need to open this in external modeling software and reposition them into place. I tried doing it in 3ds max real quick, but I only ended up breaking it even more, so I gave up.

I can't share it right now, my system drive died recently so my desktop PC is unusable, give me a few days to buy a new system drive. The files are safe on the storage drive. I only bothered fixing the 1st person view model, haven't touched the 3rd person / world model, though I could try, if you guys help me out to finish it properly.

Here's the link to the alpha shotgun:


I am sure you guys can fix this now?


Hey Fellas, guess what, the alpha shotgun finally works as intended.

Here's a screenshot of me using it on RBDOOM3BFG.

The Happy Friar