Hello:
I’m copying procedural mesh from skeletal mesh by getting the information of FSoftSkinVertex.
Everything works fine on PC, but looks terrible on android.
It looks like I didn’t get the normal, so I print out TangentZ.
It did have values on PC, but didn’t on device.
Wondering why this is happening. Is it because the setting of build to android device? (using arm64)
Here’s my code to copy the mesh and my project settings.
ProcMeshComponent->SetWorldTransform(GetMesh()->GetComponentTransform());
int32 LODIndex = 0;
FSkeletalMeshLODInfo& SrcLODInfo = GetMesh()->SkeletalMesh->LODInfo[LODIndex];
// Get the Vertices for this LOD
TArray<FVector> Vertices;
GetMesh()->ComputeSkinnedPositions(Vertices);
FSkeletalMeshResource& SkeletalMeshResource = GetMesh()->MeshObject->GetSkeletalMeshResource();
FStaticLODModel& StaticLODModel = SkeletalMeshResource.LODModels[LODIndex];
TArray<FSoftSkinVertex> SoftVertices;
StaticLODModel.GetVertices(SoftVertices);
const int32 NumSections = StaticLODModel.Sections.Num();
FRawStaticIndexBuffer16or32Interface& IndexBuffer = *StaticLODModel.MultiSizeIndexContainer.GetIndexBuffer();
//MyVertices as Vertices
TArray<FVector> MyVertices;
//WedgeIndices as Triangles?
TArray<int32>MyTriangles;
//WedgeTangetX as Tangent?
TArray<FProcMeshTangent>MyTangent;
//WedgeTangetZ as Normal?
TArray<FVector>MyNormal;
//WedgeTexCoords as UV?
TArray<FVector2D> MyUV;
TArray<FColor> Colors;
float MaxUpLength = 0;
float MaxForwardLength = 0;
float MaxRightLength = 0;
// Map from vert buffer for whole mesh to vert buffer for section of interest
TMap<int32, int32> MeshToSectionVertMap;
FMatrix WorldToRoot = GetMesh()->GetComponentTransform().ToMatrixWithScale().Inverse();
FMatrix ComponentToWorld = GetMesh()->GetComponentTransform().ToMatrixWithScale() * WorldToRoot;
for (int32 SectionIndex = 0; SectionIndex < NumSections; SectionIndex++) {
MyVertices.Reset();
MyTriangles.Reset();
MyTangent.Reset();
MyNormal.Reset();
MyUV.Reset();
Colors.Reset();
const FSkelMeshSection& SkelMeshSection = StaticLODModel.Sections[SectionIndex];
if (!SkelMeshSection.bDisabled) {
// Build 'wedge' info
const int32 NumWedges = SkelMeshSection.NumTriangles * 3;
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; WedgeIndex++) {
const int32 VertexIndexForWedge = IndexBuffer.Get(SkelMeshSection.BaseIndex + WedgeIndex);
int32* NewIndexPtr = MeshToSectionVertMap.Find(VertexIndexForWedge);
if (NewIndexPtr != nullptr) {
//Copy Triangles
MyTriangles.Add(*NewIndexPtr);
}
else {
// Copy position
int32 SectionVertIndex = MyVertices.Add(Vertices[VertexIndexForWedge]);
const FSoftSkinVertex SoftSkinnedVertex = SoftVertices[VertexIndexForWedge];
const FVector TangentX = ComponentToWorld.TransformVector(SoftSkinnedVertex.TangentX);
FProcMeshTangent NewTangent(TangentX, 0);
// Copy tangents
MyTangent.Add(NewTangent);
check(MyTangent.Num() == MyVertices.Num());
// Copy normal
const FVector TangentZ = ComponentToWorld.TransformVector(SoftSkinnedVertex.TangentZ);
MyNormal.Add(TangentZ);
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, SoftVertices[VertexIndexForWedge].TangentZ.ToString());
check(MyNormal.Num() == MyVertices.Num());
// Copy UVs
MyUV.Add(StaticLODModel.VertexBufferGPUSkin.GetVertexUV(VertexIndexForWedge, 0));
check(MyUV.Num() == MyVertices.Num());
MeshToSectionVertMap.Add(VertexIndexForWedge, SectionVertIndex);
//Copy Triangles
MyTriangles.Add(SectionVertIndex);
SetMaxLength(MyVertices.Top(), MaxUpLength, MaxRightLength, MaxForwardLength);
//Copy Colors
if (StaticLODModel.ColorVertexBuffer.IsInitialized()) {
Colors.Add(StaticLODModel.ColorVertexBuffer.VertexColor(VertexIndexForWedge));
}
else {
Colors.Add(FColor::White);
}
}
}
}
ProcMeshComponent->CreateMeshSection(SectionIndex, MyVertices, MyTriangles, MyNormal, MyUV, Colors, MyTangent, false);
}
//Set collision box by length to each edge
CreateCollisionBox(MaxUpLength, MaxRightLength, MaxForwardLength);
//// MATERIALS
for (int32 MatIndex = 0; MatIndex < GetMesh()->GetNumMaterials(); MatIndex++)
{
ProcMeshComponent->SetMaterial(MatIndex, GetMesh()->GetMaterial(MatIndex));
}