@MaxPower42 @anonymous_user_80eda73a Have an idea why the crash at runtime?
1)Build succeed;
2)Works at runtime (packaged build);
3)In editor, crash as usual:
Fatal error: [File:D:\Build++UE4+Release-4.19+Compile\Sync\Engine\Source\Runtime\RenderCore\Private\RenderingThread.cpp] [Line: 819]
Rendering thread exception:
Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\Build++UE4+Release 4.19+Compile\Sync\Engine\Source\Runtime\Core\Public\Containers/Array.h] [Line: 610]
Error: Array index out of bounds: 1 from an array of size 1
header file #include:
#include “GameFramework/Pawn.h”
#include “OVR_Avatar.h”
#include “Set.h”
#include “OVR_Plugin.h”
#include “OVR_Microphone.h”
#include “Engine/SkeletalMesh.h”
#include “Components/MeshComponent.h”
#include “Components/ActorComponent.h”
#include “OvrAvatar.generated.h”
.cpp file #include:
#include “OvrAvatar.h”
#include “OvrAvatarPCH.h”
#include “OvrAvatarManager.h”
#include “Private/OvrAvatarHelpers.h”
#include “Components/PoseableMeshComponent.h”
#include “IOculusHMDModule.h”
#include “IOculusInputModule.h”
#include “OVR_Voip_LowLevel.h”
#include “Rendering/SkeletalMeshLODModel.h”
#include “Engine/SkeletalMesh.h”
#include “SkeletalMeshModel.h”
#include “SkeletalMeshRenderData.h”
#include “SkeletalMeshLODRenderData.h”
The function of interest:
void UOvrAvatar::LoadMesh(USkeletalMesh* SkeletalMesh, const ovrAvatarMeshAssetData* data)
{
UE_LOG(LogAvatars, Warning, TEXT("[Avatars] Loaded Mesh."));
#if WITH_EDITOR
FSkeletalMeshLODModel* LodModel = new FSkeletalMeshLODModel();
SkeletalMesh->GetImportedModel()->LODModels.Add(LodModel);
#else
FSkeletalMeshLODRenderData* LodRenderData = new FSkeletalMeshLODRenderData();
SkeletalMesh->AllocateResourceForRendering();
SkeletalMesh->GetResourceForRendering()->LODRenderData.Add(LodRenderData);
#endif
#if WITH_EDITOR
new(LodModel->Sections) FSkelMeshSection();
LodModel->Sections[0].MaterialIndex = 0;
LodModel->Sections[0].BaseIndex = 0;
LodModel->Sections[0].NumTriangles = 0;
#else
new(LodRenderData->RenderSections) FSkelMeshRenderSection();
LodRenderData->RenderSections[0].MaterialIndex = 0;
LodRenderData->RenderSections[0].BaseIndex = 0;
LodRenderData->RenderSections[0].NumTriangles = 0;
#endif
SkeletalMesh->LODInfo.Add(FSkeletalMeshLODInfo());
FSkeletalMeshLODInfo& LodInfo = SkeletalMesh->LODInfo[0];
LodInfo.ScreenSize = 0.3f;
LodInfo.LODHysteresis = 0.2f;
//LodInfo.TriangleSortSettings.Add(FTriangleSortSettings());
LodInfo.LODMaterialMap.Add(0);
SkeletalMesh->Materials.Add(UMaterial::GetDefaultMaterial(MD_Surface));
//SkeletalMesh->RefSkeleton.Allocate(data->skinnedBindPose.jointCount);
SkeletalMesh->bUseFullPrecisionUVs = true;
SkeletalMesh->bHasBeenSimplified = false;
SkeletalMesh->bHasVertexColors = false;
SkeletalMesh->Materials[0].UVChannelData.bInitialized = true;
for (int BoneIndex = 0; BoneIndex < (int)data->skinnedBindPose.jointCount; BoneIndex++)
{
#if WITH_EDITOR
LodModel->RequiredBones.Add(BoneIndex);
LodModel->ActiveBoneIndices.Add(BoneIndex);
LodModel->Sections[0].BoneMap.Add(BoneIndex);
#else
LodRenderData->RequiredBones.Add(BoneIndex);
LodRenderData->ActiveBoneIndices.Add(BoneIndex);
LodRenderData->RenderSections[0].BoneMap.Add(BoneIndex);
#endif
FString BoneString = data->skinnedBindPose.jointNames[BoneIndex];
FName BoneName = FName(*BoneString);
FTransform Transform = FTransform::Identity;
OvrAvatarHelpers::ConvertTransform(data->skinnedBindPose.jointTransform[BoneIndex], Transform);
FReferenceSkeletonModifier Modifier = FReferenceSkeletonModifier(SkeletalMesh->RefSkeleton, nullptr);
Modifier.Add(FMeshBoneInfo(BoneName, BoneString, data->skinnedBindPose.jointParents[BoneIndex]), Transform);
}
check(data->indexCount % 3 == 0);
check(data->vertexCount > 0);
#if WITH_EDITOR
auto& MeshSection = LodModel->Sections[0];
MeshSection.BaseIndex = 0;
MeshSection.NumTriangles = data->indexCount / 3;
MeshSection.BaseVertexIndex = 0;
MeshSection.NumVertices = data->vertexCount;
MeshSection.MaxBoneInfluences = 4;
#else
auto& RenderMeshSection = LodRenderData->RenderSections[0];
RenderMeshSection.BaseIndex = 0;
RenderMeshSection.NumTriangles = data->indexCount / 3;
RenderMeshSection.BaseVertexIndex = 0;
RenderMeshSection.NumVertices = data->vertexCount;
RenderMeshSection.MaxBoneInfluences = 4;
#endif
const ovrAvatarMeshVertex* SourceVertex = data->vertexBuffer;
const uint32_t NumBlendWeights = 4;
FBox BoundBox = FBox();
BoundBox.Init();
#if WITH_EDITOR
MeshSection.SoftVertices.SetNumUninitialized(data->vertexCount);
FSoftSkinVertex* DestVertex = MeshSection.SoftVertices.GetData();
for (uint32_t VertIndex = 0; VertIndex < data->vertexCount; VertIndex++, SourceVertex++, DestVertex++)
{
DestVertex->Position = 100.0f * FVector(-SourceVertex->z, SourceVertex->x, SourceVertex->y);
BoundBox += DestVertex->Position;
FVector n = FVector(-SourceVertex->nz, SourceVertex->nx, SourceVertex->ny);
FVector t = FVector(-SourceVertex->tz, SourceVertex->tx, SourceVertex->ty);
FVector bt = FVector::CrossProduct(t, n) * FMath::Sign(SourceVertex->tw);
DestVertex->TangentX = FPackedNormal(t);
DestVertex->TangentY = FPackedNormal(bt);
DestVertex->TangentZ = FPackedNormal(n);
DestVertex->UVs[0] = FVector2D(SourceVertex->u, SourceVertex->v);
for (uint32_t BlendIndex = 0; BlendIndex < MAX_TOTAL_INFLUENCES; BlendIndex++)
{
DestVertex->InfluenceWeights[BlendIndex] = BlendIndex < NumBlendWeights ? (uint8_t)(255.0f*SourceVertex->blendWeights[BlendIndex]) : 0;
DestVertex->InfluenceBones[BlendIndex] = BlendIndex < NumBlendWeights ? SourceVertex->blendIndices[BlendIndex] : 0;
}
}
#else
LodRenderData->StaticVertexBuffers.PositionVertexBuffer.Init(data->vertexCount);
LodRenderData->StaticVertexBuffers.ColorVertexBuffer.Init(data->vertexCount);
LodRenderData->StaticVertexBuffers.StaticMeshVertexBuffer.Init(data->vertexCount, 1);
TArray<TSkinWeightInfo<true>> InWeights;
InWeights.AddUninitialized(data->vertexCount);
TMap<int32, TArray<int32>> OverlappingVertices;
for (uint32_t VertIndex = 0; VertIndex < data->vertexCount; VertIndex++, SourceVertex++)
{
FModelVertex ModelVertex;
ModelVertex.Position = 100.0f * FVector(-SourceVertex->z, SourceVertex->x, SourceVertex->y);
BoundBox += ModelVertex.Position;
FVector n = FVector(-SourceVertex->nz, SourceVertex->nx, SourceVertex->ny);
FVector t = FVector(-SourceVertex->tz, SourceVertex->tx, SourceVertex->ty);
FVector bt = FVector::CrossProduct(t, n) * FMath::Sign(SourceVertex->tw);
ModelVertex.TangentX = FPackedNormal(t);
ModelVertex.TangentZ = FPackedNormal(n);
ModelVertex.TexCoord = FVector2D(SourceVertex->u, SourceVertex->v);
LodRenderData->StaticVertexBuffers.PositionVertexBuffer.VertexPosition(VertIndex) = ModelVertex.Position;
LodRenderData->StaticVertexBuffers.StaticMeshVertexBuffer.SetVertexTangents(VertIndex, ModelVertex.TangentX, ModelVertex.GetTangentY(), ModelVertex.TangentZ);
LodRenderData->StaticVertexBuffers.StaticMeshVertexBuffer.SetVertexUV(VertIndex, 0, ModelVertex.TexCoord);
TArray<int32> Vertices;
for (uint32_t BlendIndex = 0; BlendIndex < MAX_TOTAL_INFLUENCES; BlendIndex++)
{
InWeights[VertIndex].InfluenceWeights[BlendIndex] = BlendIndex < NumBlendWeights ? (uint8_t)(255.0f*SourceVertex->blendWeights[BlendIndex]) : 0;
InWeights[VertIndex].InfluenceBones[BlendIndex] = BlendIndex < NumBlendWeights ? SourceVertex->blendIndices[BlendIndex] : 0;
Vertices.Add(BlendIndex < NumBlendWeights ? SourceVertex->blendIndices[BlendIndex] : 0);
}
OverlappingVertices.Add(VertIndex, Vertices);
}
// LodRenderData->SkinWeightVertexBuffer.SetNeedsCPUAccess(true);
LodRenderData->SkinWeightVertexBuffer.SetHasExtraBoneInfluences(true);
LodRenderData->SkinWeightVertexBuffer = InWeights;
RenderMeshSection.DuplicatedVerticesBuffer.Init(data->vertexCount, OverlappingVertices);
LodRenderData->StaticVertexBuffers.ColorVertexBuffer.InitFromSingleColor(FColor::Blue, data->vertexCount);
#endif
#if WITH_EDITOR
LodModel->NumVertices = data->vertexCount;
LodModel->NumTexCoords = 1;
#else
LodRenderData->MultiSizeIndexContainer.CreateIndexBuffer(sizeof(uint16_t));
#endif
for (uint32_t index = 0; index < data->indexCount; index++)
{
#if WITH_EDITOR
LodModel->IndexBuffer.Add(data->indexBuffer[index]);
#else
LodRenderData->MultiSizeIndexContainer.GetIndexBuffer()->AddItem(data->indexBuffer[index]);
#endif
}
FBoxSphereBounds Bounds(BoundBox);
Bounds = Bounds.ExpandBy(100000.0f);
SkeletalMesh->SetImportedBounds(Bounds);
//const uint32 vert_flags = ESkeletalMeshVertexFlags::None | ESkeletalMeshVertexFlags::UseFullPrecisionUVs;
//LodModel->BuildVertexBuffers(vert_flags);
SkeletalMesh->ReleaseResources();
SkeletalMesh->InitResources();
SkeletalMesh->Skeleton = NewObject<USkeleton>();
SkeletalMesh->Skeleton->MergeAllBonesToBoneTree(SkeletalMesh);
SkeletalMesh->PostLoad();
}