Different from the other tutorials I found in the web, this one is very light weight ( < 800 lines for the main mesh & animation code ) and works well with most modeling environments.
DOWNLOAD SOURCE + DATA
Summary
It has the following properties / features:
- GPU Skinning / Matrix Palette Skinning
- Bump Mapping (automatic normal map generation)
- Spheric environment mapping
- Ogre XML Based
- Shaders in GLSL
- Visual Studio 2010
- Select LOD level with F1..F5
static Mesh halo("halo.material",// required material file) "halo.mesh.xml", // required mesh file "halo.skeleton.xml"); // optional skeleton file int idle = halo.animation.GetAnimationIndexOf("idle"); halo.animation.SetPose(idle, // animation id (2 animations are available) time_elapsed); // time in seconds halo.Draw( vec3f(0,0,0), // position vec3f(0,0,0), // rotation 0); // LOD level
Also getting a bone matrix to put a weapon in the hand of the player e.g. is very simple:
int index = halo.animation.GetBoneIndexOf("joint1"); matrix44 m = halo.animation.bones[ index ].matrix;
Setting the arm joint individually for shooting a weapon e.g. works as follows:( press F6 in the demo )
// get the index int index = halo.animation.GetBoneIndexOf("joint2"); // get / modify / set the matrix matrix44 m = halo.animation.bones[ index ].matrix; m.x_component()=vec3f(1,0,0); m.y_component()=vec3f(0,1,0); // set the rotation to identity m.z_component()=vec3f(0,0,1); halo.animation.bones[ index ].matrix=m; // re-evaluate the child bones loopi(0,halo.animation.bones[ index ].childs.size()) { halo.animation.EvalSubtree( halo.animation.bones[ index ].childs[i], // bone id halo.animation.animations[0], // animation -1); // key frame -1 means not use the animation }
The workflow is as follows:
- Design the Model in Maya/MAX/Blender/etc.
- Export the model using the OgreExporter
- Convert the model from Ogre binary to Ogre XML (batch file is included)
- Load the model in the tutorial code
The Main Skinning in GLSL:
The main skinning is done in the vertex shader and only requires a few lines.
For the shader, the skinning weights are stored in the color information as 3 floats.
The bone IDs are unpacked from the w coordinate of the position information.
The bone matrixes are stored as simple matrix array..uniform mat4 bones[100]; uniform int use_skinning; void main(void) { mat4 mfinal = gl_ModelViewMatrix ; // skinning if(use_skinning==1) { vec3 weights= gl_Color.xyz; vec3 boneid = gl_Vertex.w * vec3( 1.0/128.0 , 1.0 , 128.0 ); boneid = (boneid - floor(boneid))*128.0; mat4 mskin = bones[int(boneid.x)]*weights.x+ bones[int(boneid.y)]*weights.y+ bones[int(boneid.z)]*weights.z; mfinal = mfinal * mskin; } gl_Position = gl_ProjectionMatrix * mfinal * vec4(gl_Vertex.xyz,1.0); }
Note:
Animating Notes for Maya
For Maya, put all animations in one time-line and export them as separate animations.
Ogre Export
Tangents need to be exported as 4D, to include the handedness. The tutorial version does not generate the tangents in the shader as it is faster to read them from the memory.
Bump Mapping
For the Ogre Material file, the bump map needs to be added manually by hand using the texture_bump parameter as follows:
texture Texture\masterchief_base.tif
texture_bump Texture\masterchief_bump_DISPLACEMENT.bmp
Ambient Texture Map
Same here. For the Ogre Material file, the ambient map needs to be added manually by hand using the texture_ambient parameter.
Environment Mapping
Environment mapping can be switched on in the material file using the following parameter:
env_map spherical
Screenshot of the settings in the OGRE exporter for Maya:
Commands to convert the OGRE binary to XML with 5 LODs
..\ogre_xml_converter\OgreXMLConverter.exe halo.mesh tmp\tmp.xml
..\ogre_xml_converter\OgreXMLConverter.exe -l 5 tmp\tmp.xml tmp\tmp.mesh
..\ogre_xml_converter\OgreXMLConverter.exe tmp\tmp.mesh halo.mesh.xml
..\ogre_xml_converter\OgreXMLConverter.exe halo.skeleton halo.skeleton.xml
Screenshot of the settings in the OGRE exporter for Maya:
Commands to convert the OGRE binary to XML with 5 LODs
..\ogre_xml_converter\OgreXMLConverter.exe halo.mesh tmp\tmp.xml
..\ogre_xml_converter\OgreXMLConverter.exe -l 5 tmp\tmp.xml tmp\tmp.mesh
..\ogre_xml_converter\OgreXMLConverter.exe tmp\tmp.mesh halo.mesh.xml
..\ogre_xml_converter\OgreXMLConverter.exe halo.skeleton halo.skeleton.xml
Summary of the Code Structure:
Main.h :
Main.h :
- Main code
- Reads .mesh.xml & .material files
- Animation is optional
- If an animation is present, it is stored in the animation variable
- Per vertex, the following parameters are stored: position xyz, normal, texture UV, tangent, tangent handedness, 3x skin weight and 3x bone index.
- Bones are stored in the vertex shader as matrix palette (100 bones max)
MeshAnimation.h :
- Reads .skeleton.xml
- Bones are stored in the bones array
- Animations are stored as tracks of keyframes for each animated bone
- After reading the animation, it is resampled to 20 frames per second
- To set an animation, the skeleton matrices are computed by traversing the structure
- Afterwards, they are multiplied with the inverse skinning matrix before passing to the shader (could be precalculated)
- Interpolation is linear so far - slerp could be added for better transitions.
Download
Get the ZIP here [ Download Source & Binary Files ] .
The skinned character is included as rigged Maya binary file & obj file.
You can find more free characters for example here.
Great stuff! Thank you! :)
AntwortenLöschenSuper cool :d Thanks a bunch
AntwortenLöschenGreat, glad to hear that !
AntwortenLöschenIf you find any bugs/issues let me know.
Could you please be a little more specific? Thanks!
AntwortenLöschenIn which sense?
AntwortenLöschenThis looks really fantastic. Trying to run the solution file using VS 2010 under Windows 7. Getting "Unhandled exception at 0x00000000 in Animation.exe: 0xC0000005: Access violation reading location 0x00000000" at wglSwapIntervalEXT(0);
AntwortenLöschenI commented it out for debugging purposes and then got another Access violation like the first one at: glCreateShader(type); -- returns a handle of 0. Any suggestions appreciated.
David
Does the compiled executable that is included work without problems ? Further, can you check if the shader text file is read properly ? Havent had this bug yet. You can also email me in case of further problems.
AntwortenLöschenI uninstalled and re-installed the display driver (where I believe all of the shader stuff happens in the OpenGL display driver) and that fixed it!
LöschenI agree: Great stuff! Thank you! :)
Can someone explain me what is the max boneId that could be stored this way? And how does it relate to 128.0 constant?
AntwortenLöschenIn the code, three bone id's are encoded as one float. They are unpacked in the line
AntwortenLöschenvec3 boneid = gl_Vertex.w * vec3( 1.0/128.0 , 1.0 , 128.0 );
The maximum is currently 100 bones. Using quaternions you could get 256 I guess
Hi friend, thanks for yor working.
AntwortenLöschenNow, I cant using other character from: http://tf3dm.com. I download http://tf3dm.com/3d-model/boletus-47276.html (have mesh) then using OgreXMLConverter to chage to xml.
Then import mesh.xml and material to Project.
But program error: out of vector
I try something but get nothing.
Cam you help me.
If you can send me the converted file (xml+texture files), I can take a look
AntwortenLöschenHere is my mesh.xml is converted from OgreXMLConverter tools
Löschenhttps://www.dropbox.com/s/5gsd5dvajroahjf/BoBoletus.rar?dl=0
The reason is that the xml has 2 sets of UV coordinates. The loader only supports one UV set. If you remove the second set in Maya it should work.
AntwortenLöschenVery helpful. I won't pretend I understand all of it yet, though. I was looking at Ogre to use the Keyframe and Skeletal animation parts but it appeared I had to use the rendering system as well. Your sample is much more simple to where the rendering is straight OpenGL.
AntwortenLöschenIs there a performance increase if using OGL 3+ dumping the immediate mode calls (glBegin/glEnd)?
Sure, if you apply batch rendering of the entire mesh it will definitely be faster. Since its a tutorial i tried to keep it simple however.
AntwortenLöschen"Since its a tutorial i tried to keep it simple however."
AntwortenLöschenNo problem, I totally understand. I appreciate the simplicity. I think much of my problem is in understand how skeletal animation works in general. Any resources would be helpful. Ogre docs are a bit thin on the subject. I found a few things on the web but I am looking for "plain English" writeups. (Sorry nothing against German! :) )
Dieser Kommentar wurde vom Autor entfernt.
AntwortenLöschenAwesome tutorial..thanks.
AntwortenLöschenI'm building my own animation and i can't understand how you use gl functions in "mesh.h",when I try to do the same in my program, i get an error about all the gl functions in "mesh.h".
AntwortenLöschenHello, this tutorial is great, I have ported it to linux.
AntwortenLöschenI am at my next step: exporting my blender character to ogre. However, I there is no LOD data in exported file, allthough I've set LOD to 5...
I am using latest ogre exporter and blender 2.7.7
I'm currently struggling porting it to Linux...
LöschenCan you share your source code or at least indications?
The Ogre exporter should generate the LOD. There is a batch file included to achieve this
AntwortenLöschenI'm having a issue with an assert error from vertex similar but I'm not finding what is wrong in my vertex data other then the 3d tangents instead of 4d which I just force the w to be 1. I've been unable to load any model other then the ones you supplied. http://pastebin.com/4t0EBkKg this is the vertex data of a cube that i'm trying to load
AntwortenLöschenif (sscanf(line, " <tangent x=\"%f\" y=\"%f\" z=\"%f\"", &v.x, &v.y, &v.z) == 3) {
Löschenvertices[tangent_id++].tangent = vec4f(v.x, v.y, v.z, 1);
cout << line << endl;
}
I didn't realize the order that the converter batch file was different from the output you got, must be because I used blender. Since the faces were at the bottom and not the top it was causing the issue so I figured this out finally....spent all night toying with it now the only issue is the texture isn't showing, only the bumpmap but I'll try to sort that myself. thanks for the great tutorial.
Löscheni need the source so badly for reference can you update the link please ?
AntwortenLöschenThe code is also on my github https://github.com/sp4cerat/Skinned-Skeletal-Animation-in-OpenGL
Löschenhi guys, orge use column major matrix, so why the matrix here use like row major matrix, for example:
AntwortenLöschen/////////////////////////////////////
inline void _matrix44::translate(const _vector3& t) {
M41 += t.x;
M42 += t.y;
M43 += t.z;}
/////////////////////////
as i understand, column major matrix should like below:
inline
void _matrix44::translate(const _vector3& t) {
M14 += t.x;
M24 += t.y;
M34 += t.z;
}
ok, my mistake, row major, column major, both type matrix in memory layout is same. and c++ is row major, so the M41, M42, M43 should translate.
AntwortenLöschenin the matrix multi, row major is like : vector * matrix; column major is like: matrix * vector.
impossible to get the donwload ?
AntwortenLöschen