OgreXML importer - new features

I recently made several feature additions, improvements and bugfixes to the OgreXML importer in jME2.

Specifically


  • Animation Blending - I claimed recently that this was available in the trunk. I lied, but now it is really available.  ;)

  • Import/Export - using jME's binary import/export system. Example: the ninja model takes 10 MB in OgreXML format, in jME binary, it takes 65 KB, in jME XML, it takes 700 KB.

  • Multiple root bones - now you can import models with more than one root bone where's before the importer would just crash

  • New tests:

      [li]TestInstancing - which shows the ninja instanced 20 times.
    • TestOgreImpExp - tests the import/export functionality.

    • TestWeightedBones - tests a model with multiple root bones and vertecies with more than 1 weight.


    [/li]
SomethingNew said:

I
Momoko_Fan said:

By the way, does anyone have a use for a feature where you can play two animations on the same model at the same time? For example, play "run" on the feet and "attack" on the torso for example.


I do, but I'm pretty sure you know that by now.  If it's not too much trouble, it would be awesome if you could create the feature.  I'm sure anybody making a multiplayer FPS or Third Person Shooter would find it very useful.   :D


1+ for this I use the old md5 and might be able to devise a compromise for this, but at present it means duplicating movement anims for each aiming trajectory, not hard(settled on 15 degree intervals) but its going to be tedious..........................um does this support exporting animation separately, my idea depends on using animation libraries to randomly build  animation profiles, I want each instance of the same model to sometimes fight or handle weapons differently

By the way, does anyone have a use for a feature where you can play two animations on the same model at the same time? For example, play "run" on the feet and "attack" on the torso for example.



Are there any other features you would like to see? I read a bit about HottBJ, but a lot of the features it has have weird names and there are not enough examples of where they can be used. So, I don't know what other features to add or what people might need.

Momoko_Fan said:

By the way, does anyone have a use for a feature where you can play two animations on the same model at the same time? For example, play "run" on the feet and "attack" on the torso for example.


I do, but I'm pretty sure you know that by now.  If it's not too much trouble, it would be awesome if you could create the feature.  I'm sure anybody making a multiplayer FPS or Third Person Shooter would find it very useful.   :D

I don't think it would be too hard to make "animation libraries" work. The main requirement is that the skeleton-structure must be identical between models that use these animation libraries otherwise "issues" may happen…

It might also be possible to map animations to a slightly different skeleton, as long as the bone names are the same. The only requirement for this is a few things in code.


but at present it means duplicating movement anims for each aiming trajectory, not hard(settled on 15 degree intervals) but its going to be tedious

This is not needed with OgreXML. You can change the facing of the torso bone to look where you're aiming, using the "user control" feature.

thanks for the info, I am well aware of the skeleton requirements for the libraries md5 have the same restrictions re: bone count.



some things though does this have "Listeners" /interfaces for getting specific conditions, the md5 IAnimationListener for instance allows me to easily "get" an animation at the end of a cycle and other methods "in the animation package" that allow me to control when a blend happen, in short, could u point me to the methods that will allow me similar control



also does this have a way to "subset" animations i.e. make new animation from pieces of existing ones…haven't tested it extensively in md5 reader yet but it seems useful for manipulating "multi-fightmove" animation sequences to make new ones in realtime

control when a blend happen

You can, with the current OgreXML version, control how long a blend is going to be when you set an animation, is that what you're talking about?

IAnimationListener for instance allows me to easily "get" an animation at the end of a cycle

This is a useful feature, so you can for example play "stand" animation after using a spell without having to wait until the animation actually finishes. Is there other events that should notify the listener?

also does this have a way to "subset" animations i.e. make new animation from pieces of existing ones

This sounds a bit complicated.. Multi-fightmove can be implemented without it, with something like animation queuing for example. Is there any other use cases for this?


You can, with the current OgreXML version, control how long a blend is going to be when you set an animation, is that what you're talking about?


I mean blending at or after a given frame


This is a useful feature, so you can for example play "stand" animation after using a spell without having to wait until the animation actually finishes. Is there other events that should notify the listener?


write now I only use "ANIMATION_CYCLE_ENDED" but there's the code u can decide :)

package model.animation;


public interface IAnimationListener {
    public int ANIMATION_ADDED        = 1;
    public int ANIMATION_REMOVED      = 2;
    public int ANIMATION_REMOVED_ALL  = 3;
    public int ANIMATION_CYCLE_ENDED  = 4;
    public int ANIMATION_TIME_RESET   = 5;
    
    public void notify( Animator animator, int type, Object userObject );
}





This sounds a bit complicated.. Multi-fightmove can be implemented without it, with something like animation queuing for example. Is there any other use cases for this?


direct from the horses mouth and in case u misunderstood i would "string" the created subsets together my self
I mean blending at or after a given frame

I don't really understand this. So you can "queue" an animation to be blended in after a certain frame of the currently playing animation? With the current system, you can already blend a new animation at any time you want, and also set the time it takes to fully blend it in.

write now I only use "ANIMATION_CYCLE_ENDED" but there's the code u can decide smiley

This doesn't tell me much though.. What is TIME_RESET for example? And I see there are events for when animations are added or removed, does this mean added/removed to the current playing list of animations? Is there a particular case where these events would be useful? I mean, usually it's programmatically when you change the animation or remove it, so you already know you did that and no event listeners required.. CYCLE_ENDED is particularly useful since without it you would have to check every frame if the animation has finished playing or not.

Easy animation subsets - use animation.subset( name, firstFrame, lastFrame ) where firstFrame is inclusive and lastFrame is exclusive. This creates a new animation from a subset of an existing animation

I understand the concept, what I am asking is, what can you use this for? Why would you want to take bits and pieces of existing animations and string them together? Usually the artist creates the animations so they represent a discrete action which doesn't need to be broken apart by the game.
By the way, this doesn't really effect much, but OgreXML doesn't have a concept of "frames", the animation has keyframes and these are blended between each over based on the current animation time, this might make it easier or harder to implement this feature, who knows..

Blender's Ogre-Export has the capability to export userdefined variables. I find it quite useful to give metadata in the modeller that can be used in the game-engine. I once posted a first approach in contrib but didn't commit. I was unsure because it is a blender-exporter-feature and it seems meta-data is a bit different for OgreMax etc.



http://www.jmonkeyengine.com/forum/index.php?topic=11310.0


I don't really understand this. So you can "queue" an animation to be blended in after a certain frame of the currently playing animation? With the current system, you can already blend a new animation at any time you want, and also set the time it takes to fully blend it in.


cool then,

This doesn't tell me much though.. What is TIME_RESET for example? And I see there are events for when animations are added or removed, does this mean added/removed to the current playing list of animations? Is there a particular case where these events would be useful? I mean, usually it's programmatically when you change the animation or remove it, so you already know you did that and no event listeners required.. CYCLE_ENDED is particularly useful since without it you would have to check every frame if the animation has finished playing or not.


as I said cycle_ended is the only one I really use now, I simply posted the rest as a reference, however, I can check out how they used......if they are used and get back to u later, but cycle ended is good for me

I understand the concept, what I am asking is, what can you use this for? Why would you want to take bits and pieces of existing animations and string them together? Usually the artist creates the animations so they represent a discrete action which doesn't need to be broken apart by the game.
By the way, this doesn't really effect much, but OgreXML doesn't have a concept of "frames", the animation has keyframes and these are blended between each over based on the current animation time, this might make it easier or harder to implement this feature, who knows..



for these characters I have animated sequences comprising 3-5 moves per sequence each "move" has defined common start/end frames i.e a sequence is group of animated loops, so that a subset for me will be a complete animation in its self, being able to define these chunks will pretty much allow me to "shuffle the deck every now an then".....................but I guess I can split them up in blender and use cycle ended, (provided u implement it) to rebuild them into sequences................it will mean more files to manipulate, but beggars can't be choosers



[/quote]
for these characters I have animated sequences comprising 3-5 moves per sequence each "move" has defined common start/end frames , so that a subset for me is a complete animation in its self, being able to define these chunks will pretty much allow me to "shuffle the deck every now an then".....................but I guess I can split them up in blender and use cycle ended, (provided u implement it) to rebuild them into sequences................it will mean more files to manipulate, but beggars can't be choosers

It doesn't mean more files to manipulate.. In OgreXML, a skeleton file can contain many animations. So, ideally, you should combine the animations rather than use subsets. Another problem with subsets is that you have to know the animation start and end frames in order to use them, it's not user-friendly at all to use frame numbers. This kind of feature might be implemented more easily if you can create a larger  animation from existing animations, e.g


Anim a = control.getAnim("attack1");
Anim b = control.getAnim("attack2");
Anim c = control.getAnim("attack3");

// create sequence of animations
Anim combined = control.combineAnims(a, b, c);


Would that work for you?

yeah that could work :slight_smile:

Here's what I was thinking for Multiple Animations on a Single Model.  The Ogre Exporter (at least for Blender) writes only the bones that are changed in an animation.  So if I have a skeleton like with a bone hierarchy like this:

<bonehierarchy>

  <boneparent bone="Hip_R" parent="Hips" />

  <boneparent bone="Hip_L" parent="Hips" />

  <boneparent bone="Chest" parent="Spine" />

  <boneparent bone="Thigh_R" parent="Hip_R" />

  <boneparent bone="Thigh_L" parent="Hip_L" />

  <boneparent bone="Neck" parent="Chest" />

  <boneparent bone="Shoulder_R" parent="Chest" />

  <boneparent bone="Shoulder_L" parent="Chest" />

  <boneparent bone="Shin_R" parent="Thigh_R" />

  <boneparent bone="Shin_L" parent="Thigh_L" />

  <boneparent bone="Head" parent="Neck" />

  <boneparent bone="Bicep_R" parent="Shoulder_R" />

  <boneparent bone="Bicep_L" parent="Shoulder_L" />

  <boneparent bone="FootBase_R" parent="Shin_R" />

  <boneparent bone="FootBase_L" parent="Shin_L" />

  <boneparent bone="Jaw" parent="Head" />

  <boneparent bone="ForeArm_R" parent="Bicep_R" />

  <boneparent bone="ForeArm_L" parent="Bicep_L" />

  <boneparent bone="Toe_R" parent="FootBase_R" />

  <boneparent bone="Toe_L" parent="FootBase_L" />

  <boneparent bone="Hand2_R" parent="ForeArm_R" />

  <boneparent bone="Hand0_R" parent="ForeArm_R" />

  <boneparent bone="Hand0_L" parent="ForeArm_L" />

  <boneparent bone="Hand2_L" parent="ForeArm_L" />

  <boneparent bone="Fin2-1_R" parent="Hand2_R" />

  <boneparent bone="Thumb1_R" parent="Hand0_R" />

  <boneparent bone="Thumb1_L" parent="Hand0_L" />

  <boneparent bone="Fin2-1_L" parent="Hand2_L" />

  <boneparent bone="Fin2-2_R" parent="Fin2-1_R" />

  <boneparent bone="Thumb2_R" parent="Thumb1_R" />

  <boneparent bone="Thumb2_L" parent="Thumb1_L" />

  <boneparent bone="Fin2-2_L" parent="Fin2-1_L" />

  <boneparent bone="Fin2-3_R" parent="Fin2-2_R" />

  <boneparent bone="Fin2-3_L" parent="Fin2-2_L" />

  </bonehierarchy>





And I'm doing a running animation that only affects the legs, then the exporter only exports animations with the bone it affects:

<animations>

<animation name="RunForward" length="0.640000">

<tracks>

 <track bone="Hips">

<keyframes>

<keyframe time="0.000000">

<translate x="0.366474" y="-0.000000" z="1.050500" />

<rotate angle="0.273869">

<axis x="-0.000001" y="0.317320" z="0.948318" />

</rotate>

<scale x="1.000000" y="1.000000" z="1.000000" />

</keyframe>

<keyframe time="0.040000">

<translate x="0.271614" y="0.000006" z="0.713493" />

<rotate angle="0.201833">

<axis x="-0.000001" y="0.317522" z="0.948251" />

</rotate>

<scale x="1.000000" y="1.000000" z="1.000000" />

</keyframe>

More Keyframes…

</keyframes>

</track>

 <track bone="Spine">

Blah blah blah…

</track>

 <track bone="Thigh_R">

 <track bone="Thigh_L">

 <track bone="Shoulder_L">

 <track bone="Shin_L">

 <track bone="FootBase_R">

 <track bone="FootBase_L">

 <track bone="Toe_R">

 <track bone="Toe_L">

</tracks>

</animation>

</animations>



Same for firing a gun, or throwing a grenade.



Then you set multiple animations that only animate specific bones by calling MeshAnimationController.setAnimation(); for each animation, like so:

animControl.setAnimation("RunForward");
animControl.setAnimation("ThrowGrenade");



If multiple animations transform a bone, say the root bone, interpolate the locations and rotations of the bones.  The only problem with making multiple calls to MeshAnimationController.setAnimation(); is what if you want to cycle one animation, but not the other?  Or if you want that IAnimationListener foreach animation you can't get it on a specific call to an animation.  My suggestion is the setAnimation() method should return a new Animation object, such as:

Animation runForward = animControl.setAnimation("RunForward");
Animation throwGrenade = animControl.setAnimation("ThrowGrenade");



This way you could have callbacks for IAnimationListener, also set whether the animation should cycle or not, etc.  It would be relatively easy to combine animations with code like:

Animation punchAndThrow = new Animation();
punchAndThrow.combineAnimations(punchLeft, throwGrenade); // Or maybe even put it in the constructor!



This is how I envision it.  I sorta understand the basics of OgreXML importer and am guessing it really similar to other animation importers.  What do you guys think?


I don't think it's a good requirement that animations must effect a certain set of bones to be combined. What if the artist chooses to make a keyframe for all bones? The best way is to have each "instance" of an animation updated separately, it can be encapsulated in e.g AnimationState class. You then create these AnimationStates from an Animation prototype and you'll be able to combine them inside the control class. Or a simpler interface can use integers or enums while the AnimationState abstraction only exists in the control class. Usage example:


MeshAnimationController control = ...

// assign bone_torso and all its children bones to the animation channel "Torso".
control.setBoneMask(AnimChannel.Torso, new BoneMask("bone_torso/*");

// play attack1 animation on the torso bones, blend in the animation over 150 milliseconds,
// after it finishes, play stand animation loop
control.setAnimation(AnimChannel.Torso, "attack1", 0.15f, "stand");

// play run animation on pelvis bones, blend in over 100 milliseconds,
// keep playing it over and over (loop)
control.setAnimation(AnimChannel.Pelvis, "run", 0.10f);

Momoko_Fan said:

I don't think it's a good requirement that animations must effect a certain set of bones to be combined. What if the artist chooses to make a keyframe for all bones?


My point was they don't have to be required, such as:
SomethingNew said:

Animation punchAndThrow = new Animation();
punchAndThrow.combineAnimations(punchLeft, throwGrenade); // Or maybe even put it in the constructor!




The animations can be keyframed for all bones or only a set of bones, and then combined.  When they're combined and one bone is affected by separate animations, then the combined animation should be interpolated between the two keyframes.  This is only my two cents, and this is your animation system Momoko_Fan.  You're way of doing it makes sense too.  :)

So I'm just wondering Momoko_Fan do you plan on implementing these features for the OgreXML importer?  I understand that you're rather hung-up on JME3 development though, so no rush.

Sorry for the triple post, but these are rather far apart and different.



So I have some code for what I think an AnimationChannel should be for multiple animations on a single model:

package com.jmex.model.ogrexml.anim;

import java.util.ArrayList;

public class AnimationChannel {
   
   private Skeleton skeleton;
   private ArrayList<Bone> affectedBones;
   
   public ArrayList<Bone> getAffectedBones() {
      return affectedBones;
   }
   
   public Skeleton getSkeleton() {
      return skeleton;
   }

   public AnimationChannel(Skeleton skeleton) {
      this.skeleton = skeleton;
   }
   
   /**
    * Add a single Bone to the Channel,
    * and don't have multiple instances of the same in the list.
    */
   public void addBone(String name) {
      addBone(skeleton.getBone(name));
   }
   
   /**
    * Add a single Bone to the Channel,
    * and don't have multiple instances of the same in the list.
    */
   public void addBone(Bone bone) {
      if(!affectedBones.contains(bone)) {
         affectedBones.add(bone);
      }
   }
   
   /**
    * Add Bones to the Channel going toward the root bone. (i.e. parents)
    */
   public void addToRootBone(String name) {      
      addToRootBone(skeleton.getBone(name));
   }
   
   /**
    * Add Bones to the Channel going toward the root bone. (i.e. parents)
    */
   public void addToRootBone(Bone bone) {
      addBone(bone);
      while (bone.parent != null) {
         bone = bone.parent;
         addBone(bone);
      }   
   }
      
   /**
    * Add Bones to the Channel going away from the root bone. (i.e. children)
    */
   public void addFromRootBone(String name) {
      addFromRootBone(skeleton.getBone(name));
   }
   
   /**
    * Add Bones to the Channel going away from the root bone. (i.e. children)
    */
   public void addFromRootBone(Bone bone) {
      addBone(bone);
      if (bone.children == null)
         return;      
      for (Bone childBone : bone.children) {
         addBone(childBone);
         addFromRootBone(childBone);
      }
      
   }
   


}



Still needs some testing, but I think it should work.  Now I just need to integrate this sort of idea into MeshAnimationController.  More to come, feel free to comment...

EDIT: If you would like to see more results, hop on over to this thread: http://www.jmonkeyengine.com/forum/index.php?topic=12701

hey guys,



I have tested and tested many formats including .dae and .md5 all without success. So I decided to use ogrexml and i have enhanced the importer by the following features:

  • integration of morph animation (as apposed to poses) using KeyFrameController
  • integration of (multi) camera loading and camera management
  • integration of Node animations (for animated cameras, lights, and animated nodes in general)
  • all new stuff is savable (jme serializable and works like a charm)



    Heres the Question: is anyone interested in this being integrated and committed into the jme2 ogrexml source? If so, i need someone to help me test if these changes have bad influence on Bone and KeyFrameAnimations. Also I noticed that some xml element names changed from the ogre version jme2 uses and the the ogre version that is most recent. 1.7 i think

Um maybe could you post the diffs or something?



I don't think I really need of the features, but maybe I'll try them out.  If you want to test to see if it breaks Bones and KeyFrameAnimations (as I'm sure you already know), check to make sure jmetest.ogrexml tests still run properly.  I'm working on adding multiple animations for a single model to OgreXML, and possibly animation status callbacks.