Hey all, I’m having trouble getting the skinned position of vertex in a USkeletalMeshComponent from a UBlueprintFunctionLibrary subclass (bit of a mouth full).
This is a function I’ve written which I’m calling from a Blueprint:
Initially I thought I was just getting garbage but I think actually whats happening is I’m getting correct positions returned for the ‘soft’ skinned vertices and the ‘rigid’ points (with skin weight 1) are just not getting correct positions returned. In the image above you can see clusters of correctly positioned verts along the soft boundaries between joints.
So, I flooded the root weight with 0.1 to pull weights off the other ‘rigid’ verts and turn them into ‘soft’ ones. And that does seem to prove the point:
I’m downloading the engine source now to put some debug statements inside USkeletalMeshComponent::GetSkinnedVertexPosition but figured I’d ask here in the mean time incase anyone has any bright ideas as to how I can get this to work for ‘rigid’ vertices?
void AVictoryPlayerCharacterBase::GetAnimatedVertexLocationsAndNormals(
TArray<FVector>& Locations,
TArray<FVector>& Normals
)
{
if(!Mesh) return;
if(!Mesh->SkeletalMesh) return;
//~~~~~~~~~
Locations.Empty();
Normals.Empty();
//~~~~~~~~~~~~~~~~~~~
// Get the Verticies For Each Bone, Most Influenced by That Bone!
// Vertices are in Bone space.
RV_BoneVertexInfos.Empty();
GetVertexBone(Mesh->SkeletalMesh,RV_BoneVertexInfos,true); //true = only dominant influence
//~~~~~~~~~~~~~~~~~~~~~
int32 VertItr = 0;
FBoneVertInfo* EachBoneVertInfo;
FVector BoneWorldPos;
int32 NumOfVerticies;
for(int32 Itr=0; Itr < RV_BoneVertexInfos.Num() ; Itr++)
{
EachBoneVertInfo = &RV_BoneVertexInfos[Itr];
//~~~~~~~~~~~~~~~~~~~~~~~~
//Bone Transform To World Space, and Location
RV_Transform = Mesh->GetBoneTransform(Itr);
BoneWorldPos = RV_Transform.GetLocation();
//How many verts is this bone influencing?
NumOfVerticies = EachBoneVertInfo->Positions.Num();
for(VertItr=0; VertItr < NumOfVerticies ; VertItr++)
{
//Animated Vertex Location!
Locations.Add( BoneWorldPos + RV_Transform.TransformVector(EachBoneVertInfo->Positions[VertItr]) );
//Animated Vertex Normal for rotating the emitter!!!!!
Normals.Add( RV_Transform.TransformVector(EachBoneVertInfo->Normals[VertItr]) );
}
}
//~~~ Cleanup ~~~
RV_BoneVertexInfos.Empty();
}
#My Analysis
You are transforming the position but you are not adding the initial world space location of the bone like this:
//Bone World Space Center //each vertex that is most-influenced by this bone
BoneWorldPos + RV_Transform.TransformVector(EachBoneVertInfo->Positions[VertItr])
Hey Rama, Cheers for the help! I thought for sure my question was way too obscure to get a response
So I got the Engine code checked out and it did look like USkeletalMeshComponent::GetSkinnedVertexPosition should already return positions post-deformed by the bones into ‘component space’ (as it says in the docs) and the internals did look like they should do this for rigid skinned vertices aswell.
Anywhoo, whilst in the code I spotted a potential bug where bExtraBoneInfluencesT wasn’t getting passed through to VertexBufferGPUSkin.GetVertexPtr for rigid skinned vertices like it was for ‘soft’ vertices and passing this through has fixed my issue!
Am going to look up submission guidelines now to submit back a patch.
1 - what is the type of RV_BoneVertexInfos
2 - did you write “GetVertexBone” function ? because I cannot find such
the issue is that I want to get access to the position of the vertices of an skeletal position. exactly what you did in your video. can you share more information with me how can I do it with 4.3 or 4.4 ? because you mentioned you did it with beta version