asset handling library / engine?

Started by
13 comments, last by RobM 11 years, 11 months ago
Okay, I've been trying to handle the loading of models and animations myself but its just not working and I'm wasting my time on it when I want to get into graphics programming rather than screw around for weeks trying to get animations working!
All I want is something to load a model and then by simply passing a time delta will return an array of transforms (cubic (or similarly) interpolated), then I can pass the transforms to my shaders and render the model.

I've tried doing this with the assistance of Assimp and I've had so many problems its ridiculous. Model loading was simple, loading weights I had a bit of trouble but I THINK I have that done, but I can't be sure until animations load, which I've tried many different ways to no avail, in fact the closest I've got to it transforms the model into a mutilated mess.

I've (and I'm not joking) spent weeks trying to get it working but I just can't and its driven me nuts, all I want to do is handle logic and the rendering process.
I would go back to using XNA, but the power loss in using a managed language takes away too much of the freedom I want while building up the rendering process.

Any and all help would be greatly appreciated,
Thanks in advanced,
Bombshell
Advertisement

transforms the model into a mutilated mess

Are you concatenating transforms up the hierarchy? If not, try that, and if you are, try not doing that.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
tried them both, I've tried hierarchy, non-hierarchy, oddly with same results, so them I started looking at changing the shader, I used several examples and references to put the shader together in different ways to no avail.
I've copied the nodes directly from assimp no modifying, bar the name which was linked to an ID during loading and referenced when specifying bone indices and weights, and then again when processing the animations, so I'm certain their loaded right.
I've tried making matrices with linear and cubic interpolation as well as trying directly out of the key frames with no interpolation, its always the same mangled mess, I can't figure out why, but even best case scenario I'm willing to bet I'd need to tear everything down to the processing of per vertex bone indices and weights, of which I've done on 2 occasions before this.

So long story short, I'm fed up of doing the loading, its just a cluster---k and 4th times a charm just seems irritating to me.
I'd much rather get a library or engine made by people who know how to handle loading of game assets, then I can worry about what I've been trying to get to all along, logic and graphics.
Don't give up - it's hard work and determination like this that make us great programmers over great copy/pasters.

I considered using some 3rd party asset loading code but then I realised I'd really benefit from doing I myself and I'm glad I did - it took a while but it's worth it.

My approach was to use the COLLADA DOM and parse the XML myself, there are two great articles on this that cover animation and skeletons (google 'collada animation' and check out the top few links).

The process is fairly straight forward If you read the docs thoroughly and use your own code. I just wrote a converter that parses the collada document and builds mesh data, skeleton data and animation data, then spurts all three out into 3 separate binary files for quick loading into the engine. Works a treat and I've certainly learnt a heap about animation and skeletons, etc.

Keep going and good luck, Rome wasn't built in a day...
If you have the money then I think something like Granny may do what you want (but I've never had a chance to use it myself). Otherwise you're left with existing engines, UDK/Source/etc. This side of things tends to be very game specific and studios that aren't licensing an engine generally roll their own.

If you'd like to post your code then maybe one of us can have a look at it. Getting skeletal animation going the first time can be tricky; there are quite a few things going on from model import to vertex shader and a single little mistake can totally fubar the end result.

A good way to start debugging this yourself is to get the simplest model that you can working. Export a cylinder skinned to three animated joints and get that working. Also add in some sort of way to visualise your skeletons (render lines from parent to all child joints), this may help you figure out where things are going wrong ie. root joint might look good but children get worse down the hierarchy; you're likely doing something wrong when concatenating matrices. Having some way to visualise your skeletons also takes the skinning code in your vertex shader out of the equation, which should help you hone in on the problem.
I've tried all I can and this is all I have at the moment. I really, really wish I could do it myself, I figured it'd be important should I want to try some stuff out (not sure what but there's bound to be something come to mind)
But I keep failing, its very very irritating to waste so much time, all I have to say for it is, I've learned a lot of what NOT to do.

for those interested, the P2PLib.h has some naming and syntax conventions I use near the beginning, to help readability.

EDIT: forgot to hit the upload button, hang on a few minutes while I upload it.

EDITEDIT: here it is with the assimp library and linked directories done via macro so you shouldn't need to do much messing around to get it compiling.
Your code's looking for assets in:
C:/Users/Bombshell/Documents/Visual Studio 2010/Projects/P2PENGINE/Debug/
and said assets don't exist in the .rar that you uploaded.
*facepalm* sorry about that, completely forgot.
Got a chance to give your code a quick look today and got skeletal animation working with my own test model. The issues I found:

1. You are concatenating the transforms in your joint hierarchy (ie. generating model space transforms for your joints) correctly. But you are not then transforming them into bind space (the pose your joint hierarchy/skeleton was in when mesh was bound to it). This is where skinning happens. To do this you want to save the inverse bind transform for each of your joints and use this to transform your joints into bind space. Another way to think of it is 'getting the difference between the bind pose and the current pose'. Applying this to the mesh transforms it from the bind pose to your current pose.

Using Assimp you can get the bind transforms for your joints from aiBone::mOffsetMatrix. Invert this transform to use it as below:
D3DXMATRIX* ::AnimationClass::GetTransforms(...)
{
...

D3DXMATRIX inverse_bind_transform = i->second.GetInverseBindTransform();
_result[(*i).first] = inverse_bind_transform * (*i).second.GetCompleteTransform();
..
}

2. Your skinning function is only ever using the first joint index for each weight:
skinning += Bones[input.Indices[0]] * input.Weights[0];
skinning += Bones[input.Indices[0]] * input.Weights[1];
skinning += Bones[input.Indices[0]] * input.Weights[2];
skinning += Bones[input.Indices[0]] * (1 - input.Weights[0] - input.Weights[1] - input.Weights[2]);

should probably be:
skinning += Bones[input.Indices[0]] * input.Weights[0];
skinning += Bones[input.Indices[1]] * input.Weights[1];
skinning += Bones[input.Indices[2]] * input.Weights[2];
skinning += Bones[input.Indices[3]] * (1 - input.Weights[0] - input.Weights[1] - input.Weights[2]);

3. In NodeClass::CalculateTransform, you're calling D3DXMatrixScaling rather than D3DXMatrixTranslation to apply translation (near the end of the function).

4. Your vertex declaration does not match the vertex structure being used. You're using a D3DXCOLOR for your joint indices, but declaring it as a D3DCOLOR in your vertex declaration.
D3DXCOLOR = float4
D3DCOLOR = DWORD

5. Only animated joints are being sent to your vertex shader. If there's an animated joint in your hierarchy that has a parent which isn't animated then it's going to be wrong. Any vertex that is weighted to a joint which is not animated is going to be wrong. I didn't fix this as it would take a bit of time, so I just used a test model with animation on every joint. I've attached it to this post in case you want to use it.

Also I think there's a divide by zero in your animation interpolation code, you'll notice things going a bit wacky when the animation loops around.
thanks a massive amount,
I've fixed 4. at which point the vertices started moving, I fixed 3. and 2. silly mistakes from when I was panicking on why it wasn't working.
5. I'm not sure what you mean, I assume you mean ALL inverse bind matrices need to be passed to the shader (animated once being multiplied by the transform), either that or you mean I need to generate key frames for every single bone animated or not.
1. I think I've got... I'm not sure though because the whole thing is still a mess of vertices, this may be 5.s problem though

unsigned short _currentIndex = _nodeIndices[_i].first;
_tempMatrix = _currentBone->mOffsetMatrix.Inverse();
_inverseBindTransforms[_currentIndex] = D3DXMATRIX(_tempMatrix.a1, _tempMatrix.a2, _tempMatrix.a3, _tempMatrix.a4,
_tempMatrix.b1, _tempMatrix.b2, _tempMatrix.b3, _tempMatrix.b4,
_tempMatrix.c1, _tempMatrix.c2, _tempMatrix.c3, _tempMatrix.c4,
_tempMatrix.d1, _tempMatrix.d2, _tempMatrix.d3, _tempMatrix.d4);

Does this seem about right? this is in the for loop for bones, the transforms are sent to the animation class where this happnes:

D3DXMATRIX* ::AnimationClass::GetTransforms(double p_time)
{
D3DXMATRIX* _result = new D3DXMATRIX[64];
for (unsigned short i = 0; i < 64; i++)
{
if (i > m_owner->GetBoneCount())
{ break; }
else
{ _result = m_inverseBindTransforms; }
}
for (map<unsigned short, NodeClass>::iterator i = m_nodes->begin(); i != m_nodes->end(); i++)
{
(*i).second.CalculateTransform(p_time);
_result[(*i).first] = m_inverseBindTransforms[(*i).first] * (*i).second.GetCompleteTransform();
}
return _result;
}

This topic is closed to new replies.

Advertisement