Manual skeletal mesh + skeleton creation with manual animation

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Post Reply
rujialiu
Goblin
Posts: 296
Joined: Mon May 09, 2016 8:21 am
x 35

Manual skeletal mesh + skeleton creation with manual animation

Post by rujialiu »

Hi!

I'm trying to create a procedural skeletal mesh with a procedural skeleton and manual animation. I think I've successfully created the mesh and skeleton but I'm unable to translate/rotate individual bones.

This is how I created the skeletal mesh (only difference from regular mesh is shown)

Code: Select all

...
            auto weightsElemType = Ogre::v1::VertexElement::multiplyTypeCount(Ogre::VET_FLOAT1, num_joints_per_vertex);
            vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_UBYTE4, Ogre::VES_BLEND_INDICES));
            vertexElements.push_back(Ogre::VertexElement2(weightsElemType, Ogre::VES_BLEND_WEIGHTS));
...
            Ogre::uint8* dstData = reinterpret_cast<Ogre::uint8*>(vcursor);
            for (int i = 0; i < 4; i++) {
                Ogre::uint8 idx = 0;
                if (i < data.joint_indices.size()) idx = data.joint_indices[i];
                *dstData++ = idx;
            }
            vcursor = reinterpret_cast<Ogre::Real*>(dstData);
            for (int i = 0; i < data.joint_weights.size(); i++) {
                *vcursor++ = data.joint_weights[i];
            }
This is how I created the skeleton. Note that we cannot use root_bone->createChild as suggested by Ogre doc, because we can't set name so we can only create empty-named bones and get assertion failed (duplicated name) in Skeleton::createBone(unsigned short handle). Is this intended or a bug?

Code: Select all

        auto skeleton = Ogre::v1::OldSkeletonManager::getSingleton().create(skeleton_name,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);

        auto root_bone = skeleton->createBone("bone0", 0);
        auto bone1 = skeleton->createBone("bone1", 1);
        auto bone2 = skeleton->createBone("bone2", 2);
        root_bone->addChild(bone1);
        root_bone->addChild(bone2);
        skeleton->setBindingPose();
And this is how I try to change the orientation of a bone:

Code: Select all

        auto ski = ent->getSkeletonInstance();
        if (ski) {
            int bone_count = ski->getNumBones(); // returns 3, as intended
            auto bone0 = ski->getBone(0);
            auto bone1 = ski->getBone(1);
            auto bone2 = ski->getBone(2);
            bone1->setOrientation(...);
        }
Note that skeleton instance's getNumBones() returns the inteded value 3, and bone1->setOrientation() doesn't throw any error, but it has no effect.

PS: I'm not going to use Ogre's built-in animation classes (won't import from file and won't create them procedurally). I just want to change bones' position/translation/scale each frame manually.
hedphelym
Gremlin
Posts: 180
Joined: Tue Nov 25, 2008 10:58 am
Location: Kristiansand, Norway
x 23
Contact:

Re: Manual skeletal mesh + skeleton creation with manual animation

Post by hedphelym »

Try and set the bones to :

Code: Select all

bone->setManuallyControlled(true)
Hrenli
Halfling
Posts: 73
Joined: Tue Jun 14, 2016 12:26 pm
x 19

Re: Manual skeletal mesh + skeleton creation with manual animation

Post by Hrenli »

I've checked my old code where I was manually moving Ogre's bones and it seems all I did was:

Code: Select all

SkeletonInstance->setManualBone(Bone, true);
during setup and

Code: Select all

Bone->setOrientation()
later, was working. :)

But skeleton itself was loaded from a .skeleton file.
rujialiu
Goblin
Posts: 296
Joined: Mon May 09, 2016 8:21 am
x 35

Re: Manual skeletal mesh + skeleton creation with manual animation

Post by rujialiu »

Thanks, hedphelym and Hrenli! I've tried to sett oldbone like hedphelym mentioned:

Code: Select all

bone->setManuallyControlled(true)
But it looks like the information is lost when converted to v2 skeleton? Because i'm creating v1 skeleton first, and THEN create the v2 mesh, which automatically loads a v2 skeleton (honest I don't know what's going on but it looks to me that Ogre::Item must use v2 skeleton?)

Anyway, I also tried Hrenli's way

Code: Select all

SkeletonInstance->setManualBone(Bone, true);


(BTW: I'm checked that all getManualBone(Bone) returned false, that's why I think the information is lost when converting to v2 skeleton)

And then use

Code: Select all

Bone->setOrientation()


later. However, it's still not working.

I even tried to manually created an animation (a single track, only 3 keyframes) procedurally, which is a lot simpler than I thought, but still not working... Now I think I should've made a mistake when creating the mesh. I've already made quite a few mistakes when creating the the mesh, for example messed up vertex layout or filled the vertex data in a wrong way, but all those mistakes lead to very obvious visual problem (distorted/completely trash-like entity). But now the entity looks perfect... :(

I'll investigate more. Thank you both!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Manual skeletal mesh + skeleton creation with manual animation

Post by dark_sylinc »

Because you're creating everything by scratch, there's many points of failure.

I suggest you export a simple model like the following:
  • One mesh, two cubes. One centered at origin, another at Y = 2.0f
  • Two bones, root and child. Root controls the cube at origin, child the one at y = 2
Then attempt to control these bones. If you succeed, then you're doing something wrong with bone index assignment.
(BTW: I'm checked that all getManualBone(Bone) returned false, that's why I think the information is lost when converting to v2 skeleton)
Yeah, that property is transient, per instance.
I don't know what's going on but it looks to me that Ogre::Item must use v2 skeleton?
Yes, Items must use v2 skeletons.
Regarding v1 skeletons, see Longevity of the v1 objects and deprecation.
v2 skeletons are "optimized for performance", but admitedly cramming SIMD into it ended up being a bad idea(tm). It made things much more complex, and for full editing it's much easier to do it in v1 skeletons.
Simply modifying a transform by setting the bone as manual is fine though.
But trying to construct a v2 skeleton from scratch (instead of converting a v1 -> v2) or edit its bone hierarchy directly is nuts even by my standards, and I am the one who wrote the code.
rujialiu
Goblin
Posts: 296
Joined: Mon May 09, 2016 8:21 am
x 35

Re: Manual skeletal mesh + skeleton creation with manual animation

Post by rujialiu »

Thank you all! Now everything works. I didn't call addBoneAssignment + _compileBoneAssignments because I thought it's enough to manually add vertex declarations. But later after I saw the code, it turns out that there are some internal data to be updated (blendToBone map etc). After using addBoneAssignment + _compileBoneAssignments, both key frame animation and manual manipulation works!

There is one catch that took me a few minutes to solve: after playing a key frame skeelton animation, it does not automatically stop. Even if I use setManualBone after that, the animation still affects the bones. I must set animation->setEnabled(false) to get rid of the animation.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Manual skeletal mesh + skeleton creation with manual animation

Post by dark_sylinc »

rujialiu wrote: Wed Sep 11, 2019 1:01 pm Even if I use setManualBone after that, the animation still affects the bones. I must set animation->setEnabled(false) to get rid of the animation.
Yes, setManualBone simply tells us to not reset the bone to its bind pose every frame (which basically overrides whatever you set), however animations may still attempt to layer their animations on top of it (which in some cases can be desired but will modify whatever transform you set).

If you want animations to not affect the bone at all, you'll have to set per-bone weight via SkeletonAnimation::setBoneWeight so that the animation leaves that bone alone.
Post Reply