[2.1] v2 Item's manual bone transfrom doesn't apply to mesh Topic is solved

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


Post Reply
Spectre
Gnoblar
Posts: 16
Joined: Mon May 04, 2015 4:45 pm
x 2

[2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by Spectre »

I'm trying to manually animate a skinned mesh via:

Code: Select all

Ogre::SkeletonInstance* s = item->getSkeletonInstance();
Ogre::Bone* b = s->getBone("body");
s->setManualBone( b, true );
b->setOrientation( Ogre::Quaternion(Ogre::Radian(1), Ogre::Vector3::UNIT_Y) );
b->setPosition( Ogre::Vector3(1,2,3) );
But in the render window the pose and orientation doesn't change, all the while a few frames later I check if it was reset and the debugger says it wasn't:

Code: Select all

Ogre::Quaternion ror = b->getOrientation();
//w=0.87758255 x=0.00000000 y=0.47942555 z=0.00000000
Ogre::Vector3 pop = b->getPosition();
//x=1.0000000 y=2.0000000 z=3.0000000
The mesh is created from v1 mesh, which in turn is created from manual vertex and skin binding data via code battle tested in ogre 1.* - the v1 mesh and its skeleton are created properly. //Skeleton is converted to v2 via SkeletonManager::getSingleton().getSkeletonDef(Ogre::v1::SkeletonPtr.get());

I thought v2 mesh fails to import the vertex binding, but following the code in debugger I see vertex bindings properly deshared into submeshes and compiled, so I am at complete loss why doesn't mesh animate - Sample_AnimationTagPoint.exe shows properly animated model, so it's not like my driver doesn't support hardware skin binding.
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: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by dark_sylinc »

I don't find anything wrong with what you posted.

Usually these types of errors end up being something silly like:
  1. It is working, but the effect was for some reason much more subtle than you expect
  2. The bone you grab isn't affecting geometry (you grabbed the wrong bone)
  3. The mesh was not exported properly (e.g. all geometry is just bound to one bone)
  4. Some other setting is overriding your behavior (e.g. like inherit orientation). For example if the parent bone is forcing a scale of 0.01f, then moving your bone by z += 3 will actually move it by +0.03 in world space.
  5. You have an animation enabled. Animations will add on top of the setting you set (if the bone is set to manual, like you did) or reset your setting to binding pose every frame (if the bone is not set to manual). If you want to completely override the bone so that no animation even touches the bone you want, for each animation do skeletonAnimation->setBoneWeight( "boneName", 0.0f ) or if you're in Ogre 2.3 use setOverrideBoneWeightsOnActiveAnimations/setOverrideBoneWeightsOnAllAnimations
I'd open the mesh in OgreMeshy (OgreMeshy is old and only supports v1 meshes, but it does the trick) and see its bone hierarchy to see if it's correct.

If the skeleton has no animation, I'd also add one (even if simple) to check in OgreMeshy that playing the animation does indeed animate the way you are expecting. It would reveal if the bone weights are improperly exported.

Cheers
Spectre
Gnoblar
Posts: 16
Joined: Mon May 04, 2015 4:45 pm
x 2

Re: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by Spectre »

I'm certain that the silly reasons are not the case, though I did a quick check to move every single bone randomly just to see if any part of the model would get affected, but to no avail. Debugger still reports that the bones were moved, just that the mesh doesn't care. I don't have animations on this mesh, and I'm not sure how to create one runtime, but I'll try to see if moving a bone with animation somehow makes a difference.

I'm loading from a custom file format, so I'd have to serialize it from ogre to an ogremesh file first, but since the tool doesn't work with v2 meshes it's no use. The v1 mesh I create from did work properly in older ogre, so I would expect it would just show me a working v1 mesh and that won't tell me what is wrong with the v2 mesh.

Some info about the skeleton creation process:

Code: Select all

v1::OldBone* AddBone( v1::SkeletonPtr& skeleton, const std::string& name,
	int parentId, const Vector3& pos, const Quaternion& rot )
{
	v1::OldBone* skelBone = skeleton->createBone( name );

	if( parentId == -1 )
	{
		skelBone->setPosition( pos );
		skelBone->setOrientation( rot );
	}
	else
	{
		skeleton->getBone( parentId )->addChild( skelBone );
		skelBone->_setDerivedPosition( pos );
		skelBone->_setDerivedOrientation( rot );
	}
	skelBone->setInitialState();

	return skelBone;
}

...

v1::SkeletonPtr skeleton = v1::OldSkeletonManager::getSingleton()
	.create( skeletonName, resgroupName, true );
v1mesh->setSkeletonName( skeletonName );

...

for( int i = 0, e = /*bonesAmount*/; i < e; ++i )
{
	int parentBoneId =
		AddBone( skeleton, /*names[i]*/, /*parentIds[i]*/,
		/*restPose[i]*/, /*restOrient[i]*/ )->getHandle();

	...

	v1::SubMesh* sub = v1mesh->createSubMesh( /*names[i]*/ );

	...

	v1::VertexBoneAssignment vba;
	for( int v = /*verticesBegin*/, k = /*verticesEnd*/; v < k; ++v )
	{
		vba.vertexIndex = v;
		vba.boneIndex = parentBoneId;
		vba.weight = 1;
		v1mesh->addBoneAssignment( vba );
	}
}

...

Ogre::SkeletonManager::getSingleton().getSkeletonDef( skeleton.get() );
// output is somewhere between 25-40 bones per mesh, every submesh is bound to a bone with the same index, hierarchy is rather flat - most bones do not have a root bone, and only a few are children of first order, with even less - children of second order, v1 mesh worked fine with this code, I guess I'll try to just fallback to v1 mesh if everything else fails, but I can't find peace in not knowing what is wrong, can you hint me where else can I hunt with the debugger for signs that vertices are either moved or not by the bones, or codepaths that decide if skeleton position should be updated/applied to mesh vertices?
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: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by dark_sylinc »

Spectre wrote: Sun May 30, 2021 11:42 pm I'm loading from a custom file format, so I'd have to serialize it from ogre to an ogremesh file first, but since the tool doesn't work with v2 meshes it's no use. The v1 mesh I create from did work properly in older ogre, so I would expect it would just show me a working v1 mesh and that won't tell me what is wrong with the v2 mesh.
Ok that is key.
It sounds like you're missing a call to _compileBoneAssignments while importing.

I suggest you use RenderDoc and check the vertex stream when rendered, to see that the weight indices and weights are what you expect in the 'Mesh Output' pane.
Spectre
Gnoblar
Posts: 16
Joined: Mon May 04, 2015 4:45 pm
x 2

Re: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by Spectre »

Pardon, forgot to include "v1mesh->_compileBoneAssignments();" bit into the previous message. That is done after all the vertex bone assignments, and as I debugged v2 mesh import, is too properly copied and recompiled in v2 mesh.
Will report on renderdoc results a bit later.
Last edited by Spectre on Mon May 31, 2021 4:51 am, edited 1 time in total.
Spectre
Gnoblar
Posts: 16
Joined: Mon May 04, 2015 4:45 pm
x 2

Re: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by Spectre »

I'm afraid I don't know how to use renderdoc, or at least I couldn't find any skin data. Mesh is supposed to be exploded, but it renders intact.
// for reference, mesh dimensions are around 5x5x7 units, plus minus one

Code: Select all

SkeletonInstance* s = item->getSkeletonInstance();
for( int i = 0, e = s->getNumBones(); i < e; ++i )
{
	Bone* b = s->getBone( i );
	s->setManualBone( b, true );
	b->setOrientation(
		Quaternion( Radian(Math::Sin(i)), Vector3::UNIT_Y )
		);
	b->setPosition( Vector3(
		Math::Sin( Radian(i) ),
		Math::Cos( Radian(i) ),
		Math::Sin( Radian(-i) )
		) );
}
Image Image
I saved the capture, if you would want to look at it (renderdoc v1.14 - 28 May, 2021).
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: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by dark_sylinc »

EDIT: I just noticed you're using Unlit! Unlit will ignore skeletal animation!!!
It's really late so I can't think much right now. I would try of using Pbs and try to see if you can workaround the lighting problem by ramping up emissive lighting in the material to 1.0. Or perhaps in the ambient.
For best results perhaps you should add normals to the mesh to fool HlmsPbs, and set these normals to 0 0 0 or maybe 0.0001.

EDIT 2: I remembered user xrgo managed to trick HlmsPbs to work like Unlit so he uses HlmsPbs for both PBS and Unlit-like materials. I think he posted some code in the forum on how to do that, or you could try contacting him directly.


Original post:
Hi. I took a look.

Where you had to look was in the attributes of the input mesh (black rectangle):


In a properly skeletal animated mesh, there would be blendWeights and blendIndices alongside the position, normals and UVs. There aren't any, which means the mesh was incorrectly imported to v2 and Ogre thinks it's not skeletally animated at all.

My best guess is that when Mesh::importV1 gets called, one of these lines fails:

Code: Select all

mSkeletonName = mesh->getSkeletonName();
v1::SkeletonPtr v1Skeleton = mesh->getOldSkeleton();
if( !v1Skeleton.isNull() )
    mSkeleton = SkeletonManager::getSingleton().getSkeletonDef( v1Skeleton.get() );
Maybe the skeleton name is empty, or v1Skeleton is a nullptr.

Another possibility is that SubMesh::_arrangeEfficient did not fill VES_BLEND_WEIGHTS and VES_BLEND_INDICES into vertexElements.

v1::Mesh::compileBoneAssignments should've added VES_BLEND_* stuff to the v1 mesh:

Code: Select all

const VertexElement& idxElem =
    decl->addElement(bindIndex, 0, VET_UBYTE4, VES_BLEND_INDICES);
const VertexElement& wtElem =
    decl->addElement(bindIndex, sizeof(unsigned char)*4,
    VertexElement::multiplyTypeCount(VET_FLOAT1, numBlendWeightsPerVertex),
    VES_BLEND_WEIGHTS);
but I guess this function is either getting called too late (i.e. should be called before importing to v2) or something else unknown is stripping these elements from the declaration.

Please note that by the time importV1 is called, you should've fully set both the Mesh and the Skeleton up. If you set the Mesh first, then call importV1, then the Skeleton, it won't be imported correctly.

Cheers
Matias
Spectre
Gnoblar
Posts: 16
Joined: Mon May 04, 2015 4:45 pm
x 2

Re: [2.1] v2 Item's manual bone transfrom doesn't apply to mesh

Post by Spectre »

// material decides if my mesh should move? ffs
Quick test shows that it truly was unlit that is to blame, damn. I did not expect that.
Image
Post Reply