I’ve found a couple of things that explain something similar but can’t quite work it out.
Basically I want to have a procedural mesh that is an exact copy of the skeletal mesh, including animations and morphs, and have it updating at runtime.
It should also have collision.
I don’t mind if this will be expensive, it will only be used for one or 2 meshes.
Hi, tofmedPOST:
thank you so much for your greatest work done here, but there is a little problem in your code: error C2065: ‘SkinWeights’: undeclared identifier, how can I get the value of the SkinWeights variable?
Oh, I figure it out now:
add FSkinWeightVertexBuffer* SkinWeights = SkeletalMeshComponent->GetSkinWeightBuffer(LODIndex); before line 21 and it works fine. thanks a lot for your amazing work!
This is cool! How would I go about implementing this code? I’m not very keen on C++ just yet. Would I make a Blueprint Function Library ? What would I include ? Thanks!
Hello!
Thanks for the excellent solution; it helped me a lot!
A small addition: if the mesh has multiple render sections, this code will copy only the first one. It is easily solved by adding a loop and iterating through all DataArray.RenderSections.
And then offset the vertex indexes by DataArray.RenderSections[SectionCount].BaseVertexIndex.
But I have a different but related question: does anybody know how to pick only the vertexes, which have weights associated with some particular bone?
I try to create a dynamic dismemberment system, which would work on with “solid” skeletal meshes without any pre-cutting.
It already works, but it is not very efficient because each time, I have to copy a lot of “unused” vertices and slice them afterwards, but I don’t like this.
FSkinWeightVertexBuffer’s method GetBoneIndex(VertexIndex, InfluenceIndex) seems to be the solution. However, due to a lack of documentation, I am not sure that I use it properly (e.g. I still do not completely get what InfluenceIndex is).
Any ideas?
Hello dear anonymous user:) It’s great that you help people so much! You write “This should help, however it doesn’t work with morph targets.” I want to ask you if it’s possible to make it work with morph targets? Or should I not try?
I had some problems with a skeletal mesh that contain multiple RenderSections and also different vector types in UE5 (i guess?)
here’s updated example code that accounts for multiple render section and properly copies all render sections
To make different section with different materials to work properly you also need to fill in “triangles” array properly accounting for each section BaseIndex and keeping in mind that index buffer array is multiple of 3 respective to “triangle index” of a section
Here is updated code that work for me.
void CopySkeletalMeshToProcedural(USkeletalMeshComponent* SkeletalMeshComponent, int32 LODIndex, UProceduralMeshComponent* ProcMeshComponent)
{
FSkeletalMeshRenderData* SkMeshRenderData = SkeletalMeshComponent->GetSkeletalMeshRenderData();
const FSkeletalMeshLODRenderData& DataArray = SkMeshRenderData->LODRenderData[LODIndex];
FSkinWeightVertexBuffer& SkinWeights = *SkeletalMeshComponent->GetSkinWeightBuffer(LODIndex);
TArray<FVector> VerticesArray;
TArray<FVector> Normals;
TArray<FVector2D> UV;
TArray<FColor> Colors;
TArray<FProcMeshTangent> Tangents;
for (int32 j = 0; j < DataArray.RenderSections.Num(); j++)
{
//get num vertices and offset
const int32 NumSourceVertices = DataArray.RenderSections[j].NumVertices;
const int32 BaseVertexIndex = DataArray.RenderSections[j].BaseVertexIndex;
for (int32 i = 0; i < NumSourceVertices; i++)
{
const int32 VertexIndex = i + BaseVertexIndex;
//get skinned vector positions
const FVector3f SkinnedVectorPos = USkeletalMeshComponent::GetSkinnedVertexPosition(
SkeletalMeshComponent, VertexIndex, DataArray, SkinWeights);
VerticesArray.Add(fromFVector3f(SkinnedVectorPos));
//Calc normals and tangents from the static version instead of the skeletal one
const FVector3f ZTangentStatic = DataArray.StaticVertexBuffers.StaticMeshVertexBuffer.VertexTangentZ(
VertexIndex);
const FVector3f XTangentStatic = DataArray.StaticVertexBuffers.StaticMeshVertexBuffer.VertexTangentX(
VertexIndex);
//add normals from the static mesh version instead because using the skeletal one doesnt work right.
Normals.Add(fromFVector3f(ZTangentStatic));
//add tangents
Tangents.Add(FProcMeshTangent(fromFVector3f(XTangentStatic), false));
//get UVs
const FVector2f SourceUVs = DataArray.StaticVertexBuffers.StaticMeshVertexBuffer.
GetVertexUV(VertexIndex, 0);
FVector2d ResUVs;
ResUVs.X = SourceUVs.X;
ResUVs.Y = SourceUVs.Y;
UV.Add(ResUVs);
//dummy vertex colors
Colors.Add(FColor(0.0, 0.0, 0.0, 255));
}
}
//get index buffer
FMultiSizeIndexContainerData IndicesData;
DataArray.MultiSizeIndexContainer.GetIndexBuffer(IndicesData.Indices);
for (int32 j = 0; j < DataArray.RenderSections.Num(); j++)
{
TArray<int32> Tris;
// get number triangles and offset
const int32 SectionNumTriangles = DataArray.RenderSections[j].NumTriangles;
const int32 SectionBaseIndex = DataArray.RenderSections[j].BaseIndex;
//iterate over num indices and add traingles
for (int32 i = 0; i < SectionNumTriangles; i++)
{
int32 TriVertexIndex = i*3 + SectionBaseIndex;
Tris.Add(IndicesData.Indices[TriVertexIndex]);
Tris.Add(IndicesData.Indices[TriVertexIndex + 1]);
Tris.Add(IndicesData.Indices[TriVertexIndex + 2]);
}
//Create the procedural mesh section
ProcMeshComponent->CreateMeshSection(j, VerticesArray, Tris, Normals, UV, Colors, Tangents, true);
}
}
Seems that the code causes a crash with Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Containers\Array.h] [Line: 758] error. Did anybody experience this and knows what could be the cause?