Now you see, issue occuring if someone write a general vertex program which dealing with four weights per vertex, but the supplied mesh numBlendWeightsPerVertex < 4. Because the lastest blend weight is 1 (hardware expanded describing above), and the lastest blend index is 0 (It's zero filled? may be, dependence by hardware vertex buffer implementation), all vertices will full weighted by first bone delta transform.
Yes, I known, this issues can be resolved by supply special case version vertex program for each mesh. But I want the computer do it for me, and if the suggestion below can be implement inside the Ogre core, why not?
This issues unnotice if someone write vertex program like this (copy from Ogre "Example_Basic.cg" routine hardwareSkinningFourWeights_vp):
Code: Select all
// transform by indexed matrix
float4 blendPos = float4(0,0,0,0);
int i;
for (i = 0; i < 4; ++i)
{
blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
}
// view / projection
oPosition = mul(viewProjectionMatrix, blendPos);
I come up against this issues because I want optimise the code above, like:
Code: Select all
// transform by indexed matrix
float3 blendPos = float3(0,0,0);
int i;
for (i = 0; i < 4; ++i)
{
blendPos += mul(worldMatrix3x4Array[blendIdx[i]], position) * blendWgt[i];
}
// view / projection
oPosition = mul(viewProjectionMatrix, float4(blendPos, 1.0));
Suggestion below:
Extend vertex program attribute includes_skeletal_animation <bool> to includes_skeletal_animation <numBonesPerVertex> <maxBones>, <numBonesPerVertex> means how much bones-per-vertex this vertext program can dealing with, <maxBones> means how many world matrices can set to world_matrix_array_3x4. <maxBones> is need to improve vs_1_1 24 bones limitation support mention later.
Entity::reevaluateVertexProcessing will take care with <numBonesPerVertex> and <maxBones>, find the best fit (or anyone) technique to process skinning mesh, or auto fallback software skinning if any sub-entity except the vertex program capability for all techniques for it.
Furthermore, for each sub-entity, sorting out the bones that never used by the sub-entity, reorganise blend indices to "packed" form, so the <maxBones> for each individual sub-entity will drop down, make hardware skinning more usable. Some code to explain what I means:
SubEntity::getWorldTransforms will work like this:
Code: Select all
for (i = 0; i < this->mNumActualUsedBones; ++i)
{
*xform = mParentEntity->mBoneMatrices[this->mBlendIndexToBoneIndexMap[i]];
++xform;
}
Sorry for my ugly English