Making better use of Ogre's capbilities?

Everything about development and the OpenMW source code.
Post Reply
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Making better use of Ogre's capbilities?

Post by Chris »

Something I've noticing is that many of Ogre's existing systems aren't being utilized where they probably could be. For instance, the animations don't seem to be using Ogre::AnimationTrack, which automatically applies time-based transformations to an Animation, which in turn can affect a set of vertices, nodes (eg, bones), or numbers. Currently it looks like the transformations are done by manually poking at the bones or vertex data based directly on the Nif data. Perhaps it would be more efficient to build an animation track based on the Nif data, and let Ogre worry about the nitty-gritty details? I'd actually be very surprised if Morrowind did not take advantage of hardware skinning, and Ogre would probably be in the best position to do that with its own meshes.

OpenMW would just need an animation manager, to make sure the various animations are put into the proper animation time, the proper sounds are triggered (which likely need to be positioned on specific nodes, not objects), and so on. This should even extend to particle animations simply enough, because particles are just animated nodes that display billboard sprites.

Another thing is that some of Nif's node types seem to have very close (if not exact) analogues in Ogre. NiUVController -> Ogre::TexCoordModifierControllerValue and NiTimeController -> Ogre::WaveformControllerFunction for instance. It would take a lot of work off OpenMW's shoulders if we only need to worry about translating the Nif data into their respective Ogre/Bullet components, for those that exist anyway, then all we have to do is make sure it all runs correctly. Ogre will worry about whether it's hardware of software skinning, Ogre will take care of keyframe blending, Ogre will take care of controlling and morphing nodes and vertices given a time index, Ogre will make sure textures properly scroll, etc.

IMO, it may be worth looking at Niflib, which is more mature at handling and parsing the Nif data structures. It may also be worth considering to consolidate all the Nif loading code into a single place, and which is triggered by the mechanism that loads objects into cells (when an object comes in that references a Nif, all the components of the Nif (meshes, animations, collision, etc) are loaded manually into Ogre right then. That will help keep the Nif handling synchronized between components and subsystems, since it will all be together and happen at once.

I'd love to try doing something like this myself, but unfortunately the Nif format really does a number on me. I once started a project where I tried to load a Nif model into Ogre and display it... and I got a number of meshes looking close, but there were almost always a few things wrong with them (detached limbs, bad orientation, etc). Trying to load and apply the skeletons to the meshes just kicked my a**, and that was the last I touched of the project. But that was also me trying to tie the nif loading into Ogre's automatic resource management, which given various assessments (Nifs contain many types of resources that are interdependent), was probably the thing that was hampering me most.
Tarius
Posts: 574
Joined: 24 Oct 2011, 19:29

Re: Making better use of Ogre's capbilities?

Post by Tarius »

(detached limbs, bad orientation, etc)
While I am not an expert and dont know the details here of what you did, this really sounds at least in part like a bone naming problem. I have messed around with loading animations into a specific program and the bone naming structure was not an exact match. I ended up with the legs being switched and such as the program tried to figure out where the different bones went.
jhooks1
Posts: 780
Joined: 06 Aug 2011, 21:34

Re: Making better use of Ogre's capbilities?

Post by jhooks1 »

Tried using Ogre's animation system before, it wouldn't work for us. Have discussed this in length before.
You are welcome to try it yourself.
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Making better use of Ogre's capbilities?

Post by Chris »

I've been working on this, and I almost have Nifs working with Ogre's skeletal animation system. I've got the skeleton loading into Ogre correctly using niflib:
http://ompldr.org/vZDlnaw/OP_Screenshot ... 301990.png
(those blue/green/red speckles are the bones as Ogre sees them; they're rotated back 90 degrees because they're not directly connected to the scene graph).

I've also got the mesh loading and taking on the skeleton's pose:
http://ompldr.org/vZDlnbA/OP_Screenshot ... 820149.png
(yes, the mesh is offset from the skeleton; that's on purpose).

However, once I try loading the animation, it goes out of whack:
http://ompldr.org/vZDlnbg/OP_Screenshot ... 637802.png

Note that it doesn't seem to be a problem with the vertex weights because the skeleton itself is warped. It's also not an animation problem on Ogre's side because those first two shots are technically animating as well (they just had all the keyframe transforms/translations left at identity so the bones simply didn't move from their initial position).

I've poked and proded with the Nif data, but I don't quite understand what's going wrong. The code I'm working with is here:
http://ompldr.org/vZDlnbw/ogre-proj.zip

Note that you need niflib for it to build. I'm using the Git version, which you can get by running:
git clone --recursive git://niftools.git.sourceforge.net/gitroot/niftools/niflib

Note that niflib doesn't install. In the root ogre-proj directory, you need to create a symlink called 'niflib' and have it point to niflib's base directory. It also needs a symlink called 'data' that points to your Morrowind Data Files directory (you can optionally modify resources.cfg instead). If you don't have KDE4, you need to edit CMakeLists.txt and comment out the line ADD_DEFINITIONS(-DHAVE_KDE4).

By default, it uses "meshes/wolf/xskinnpc.nif" and "meshes/wolf/xskinnpc.kf", which requires Bloodmoon. You can change this by editing main.cpp, lines 436 and 447. The animation loading code is at the bottom of nif_loader.cpp (the mesh/skeleton loading code is in that file as well). Any help with this would be greatly appreciated.
User avatar
ElderTroll
Posts: 499
Joined: 25 Jan 2012, 07:01

Re: Making better use of Ogre's capbilities?

Post by ElderTroll »

Awesome work Chris. Have you tried asking on the Ogre help forums or a Bethesda or NIF help board? Maybe someone can explain how NIF works a little more accurately. Maybe Mark knows. I don't know if he got animations working through Crystal Space or outside of it like Jhooks1.
jhooks1
Posts: 780
Joined: 06 Aug 2011, 21:34

Re: Making better use of Ogre's capbilities?

Post by jhooks1 »

I am just now getting a chance to reply to this. It looks like you are on the right track.

The original openmw creature rendering in the NIFLoader actually modified the vertices/position buffers to get everything in the right position. It manually made calculations using the bone positions and orientations. This was fine for rendering - you write out the buffers once and you are done. For animation though, you have to update the buffers every frame and it can really hog cpu time, especially with creatures with many vertices.

I have only glanced at your code, so I could be wrong. It looks like you are not doing what I described in the above paragraph, but got the ogre vertex bone assignments working correctly. If so bravo, they never seemed to affect anything correctly for me (which is why I thought I should resort to updating the vertices myself).

Anyways, with ogre animation objects you provide a translation (Vector3) and a rotation (Quaternion) for each keyframe. If we are at (5, 0, 0) position and provide (10, 0, 0) as a translation input it would result in (15, 0, 0). This is different from what morrowind/NIF does, in nifs the inputs are absolute. If we are at (5, 0, 0) and provide (10, 0, 0) we would get (10, 0, 0), previous inputs would not matter.

For now I would suggest instead of using the ogre animation system, just try the handleAnimationTransforms() function to place the bones/animate. If you can get that to work then you are definitely on the right track. Do not call handleShapes(), if you did everything like I think you did you won't need it. If you can get this to work without handleShapes() you will be a Morrowind god :D Would save so much performance wise.
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Making better use of Ogre's capbilities?

Post by Chris »

jhooks1 wrote:Anyways, with ogre animation objects you provide a translation (Vector3) and a rotation (Quaternion) for each keyframe. If we are at (5, 0, 0) position and provide (10, 0, 0) as a translation input it would result in (15, 0, 0). This is different from what morrowind/NIF does, in nifs the inputs are absolute. If we are at (5, 0, 0) and provide (10, 0, 0) we would get (10, 0, 0), previous inputs would not matter.
Does that mean the inputs are absolute with respect to the skeleton's root, or to the bone's parent?

According to my understanding, Ogre's keyframe inputs are relative to the bone's "initial" state (set by Ogre::Bone::setInitialState). That is, if the bone's initial state is at (5,0,0) and a keyframe transform is (5,0,0), it will come out to (10,0,0). If the next keyframe transform is (2,0,0), it will move to (7,0,0). Isn't that the case?
For now I would suggest instead of using the ogre animation system, just try the handleAnimationTransforms() function to place the bones/animate. If you can get that to work then you are definitely on the right track. Do not call handleShapes(), if you did everything like I think you did you won't need it. If you can get this to work without handleShapes() you will be a Morrowind god :D Would save so much performance wise.
I'll see what I can do. The nif code seems to be a bit difficult to read through, and as I've been working with a .kf animation file, it doesn't seem to work quite the same as an animation in a nif.
jhooks1
Posts: 780
Joined: 06 Aug 2011, 21:34

Re: Making better use of Ogre's capbilities?

Post by jhooks1 »

Chris wrote:
jhooks1 wrote:Anyways, with ogre animation objects you provide a translation (Vector3) and a rotation (Quaternion) for each keyframe. If we are at (5, 0, 0) position and provide (10, 0, 0) as a translation input it would result in (15, 0, 0). This is different from what morrowind/NIF does, in nifs the inputs are absolute. If we are at (5, 0, 0) and provide (10, 0, 0) we would get (10, 0, 0), previous inputs would not matter.
Does that mean the inputs are absolute with respect to the skeleton's root, or to the bone's parent?

According to my understanding, Ogre's keyframe inputs are relative to the bone's "initial" state (set by Ogre::Bone::setInitialState). That is, if the bone's initial state is at (5,0,0) and a keyframe transform is (5,0,0), it will come out to (10,0,0). If the next keyframe transform is (2,0,0), it will move to (7,0,0). Isn't that the case?
I think the bone's parent, but then again I couldn't really get ogre's animation system to do anything right for me. Your explanation seems correct.

Haven't looked at .kf animation files yet
jhooks1
Posts: 780
Joined: 06 Aug 2011, 21:34

Re: Making better use of Ogre's capbilities?

Post by jhooks1 »

I read in all the NiKeyFrameData near the end of loadResource() in the NIFLoader. It is enclosed by if(addAnim). It is not very much code.

To use this data on your creatures, you access it by NIFLoader::getAnim(). Pass the data into NPCAnimation::handleAnimationTransforms()
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Making better use of Ogre's capbilities?

Post by Chris »

I've done a bit more digging, and it appears the wrong nodes are getting animated. If I leave all the animation transformations/translations at identity, and cause a time-based sine wave scaling to the "Bip01 L Toe0" target, then it's actually the right index finger (Bip01 R Finger11) that scales... both the actual bone that Ogre shows and the finger's mesh. If I apply the scaling to "Bip01 R Finger11", then the right shoulder is affected instead.

I've double-checked and Ogre is being given the correct node. Both on creation and when creating the track, "Bip01 L Toe0" has the same pointer value, the same handle ID, and the same derived position (Vector3(-15.1297, 15.0569, -0.085099), which is lower-left). Checking the node track's associated node shows the correct one.

EDIT:
Seems there's a slight bug in Ogre there. If I pre-create the animation tracks by doing

Code: Select all

for(size_t i = 0;i < bonecount;i++)
    (*anim)->createNodeTrack(i, skel->getBone(i));
then later retrieve it when actually building the animation using

Code: Select all

Ogre::NodeAnimationTrack *nodetrack = (*anim)->getNodeTrack(skel->getBone(target)->getHandle());
then it will animate the correct nodes. Now I'm back to figuring out what the keyframe transformations are relative to..
Post Reply