Page 1 of 1

Manual skeletal mesh + skeleton creation with manual animation

Posted: Tue Sep 10, 2019 5:29 am
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.

Re: Manual skeletal mesh + skeleton creation with manual animation

Posted: Tue Sep 10, 2019 6:55 am
by hedphelym
Try and set the bones to :

Code: Select all

bone->setManuallyControlled(true)

Re: Manual skeletal mesh + skeleton creation with manual animation

Posted: Tue Sep 10, 2019 10:28 am
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.

Re: Manual skeletal mesh + skeleton creation with manual animation

Posted: Tue Sep 10, 2019 2:02 pm
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!

Re: Manual skeletal mesh + skeleton creation with manual animation

Posted: Tue Sep 10, 2019 3:36 pm
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.

Re: Manual skeletal mesh + skeleton creation with manual animation

Posted: Wed Sep 11, 2019 1:01 pm
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.

Re: Manual skeletal mesh + skeleton creation with manual animation

Posted: Thu Sep 12, 2019 4:20 am
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.