UStaticMeshComponent::SetStaticMesh() crash; how to create a static mesh from raw mesh data in UE5?

huangapple go评论57阅读模式
英文:

UStaticMeshComponent::SetStaticMesh() crash; how to create a static mesh from raw mesh data in UE5?

问题

I am trying to create a static mesh from a raw mesh data (vertex + index buffer) at runtime. First, I was able to successfully create a static sphere mesh (using StaticLoadObject to load "/Engine/BasicShapes/Sphere") and to assign the same material (as returned by AMyActor::CreateMaterial below). Then, instead of the sphere mesh, I want to create my vertex and index data at runtime. With information I found around, I wrote the following code:

UStaticMeshComponent* AMyActor::CreateMesh(AActor* ActorOwner, FLinearColor Color)
{
    UStaticMesh* StaticMesh = NewObject<UStaticMesh>();
    StaticMesh->AddSourceModel();
    FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(0);
    //SourceModel.RawMeshBulkData->SaveRawMesh(RawMesh);

    StaticMesh->Build(false);

    UStaticMeshComponent* Mesh = NewObject<UStaticMeshComponent>(ActorOwner);
    UE_LOG(LogTemp, Warning, TEXT("Calling Mesh->SetStaticMesh(%x)..."), (void*)StaticMesh);
    // crashes here:
    Mesh->SetStaticMesh(StaticMesh);
    Mesh->SetMaterial(0, CreateMaterial(Color));
    Mesh->SetCollisionProfileName(TEXT("Pawn"));
    Mesh->SetHiddenInGame(false);
    Mesh->RegisterComponent();
    return Mesh;
}

UMaterialInstanceDynamic* AMyActor::CreateMaterial(FLinearColor Color)
{
    FStringAssetReference MaterialRef(TEXT("/Game/SimBlank/Materials/GlossyRedMaterial"));
    UMaterialInterface* LoadedMaterial = Cast<UMaterialInterface>(StaticLoadObject(UMaterialInterface::StaticClass(), nullptr, *MaterialRef.ToString()));
    UMaterialInstanceDynamic* NewMaterial = UMaterialInstanceDynamic::Create(LoadedMaterial, this);
    NewMaterial->SetVectorParameterValue("BaseColor", Color);
    return NewMaterial;
}

The above code crashes at Mesh->SetStaticMesh(StaticMesh);. Before crashing it prints:

Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\build++UE5\Sync\Engine\Source\Runtime\Core\Public\Containers\Array.h] [Line: 752] Array index out of bounds: 0 from an array of size 0

To make a simpler test, I removed the part where I create the FRawMesh and also the call to SourceModel.RawMeshBulkData->SaveRawMesh(RawMesh), however, it crashes in the same way, with the same assertion failed message. Code:

UStaticMeshComponent* AMyActor::CreateMesh(AActor* ActorOwner, FLinearColor Color)
{
    UStaticMesh* StaticMesh = NewObject<UStaticMesh>();
    StaticMesh->AddSourceModel();
    FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(0);
    //SourceModel.RawMeshBulkData->SaveRawMesh(RawMesh);

    StaticMesh->Build(false);

    UStaticMeshComponent* Mesh = NewObject<UStaticMeshComponent>(ActorOwner);
    UE_LOG(LogTemp, Warning, TEXT("Calling Mesh->SetStaticMesh(%x)..."), (void*)StaticMesh);
    // crashes here:
    Mesh->SetStaticMesh(StaticMesh);
    Mesh->SetMaterial(0, CreateMaterial(Color));
    Mesh->SetCollisionProfileName(TEXT("Pawn"));
    Mesh->SetHiddenInGame(false);
    Mesh->RegisterComponent();
    return Mesh;
}

What's the correct way to create a static mesh from raw mesh data?

英文:

I am trying to create a static mesh from a raw mesh data (vertex + index buffer) at runtime.

First, I was able to successfully create a static sphere mesh (using StaticLoadObject to load "/Engine/BasicShapes/Sphere") and to assign the same material (as returned by AMyActor::CreateMaterial below).

Then, instead of the sphere mesh, I want to create my vertex and index data at runtime.

With information I found around, I wrote the following code:

UStaticMeshComponent* AMyActor::CreateMesh(AActor* ActorOwner, FLinearColor Color)
{
	FRawMesh RawMesh;
	RawMesh.VertexPositions.Emplace(FVector(0.f, 0.f, 0.f));
	RawMesh.VertexPositions.Emplace(FVector(100.f, 0.f, 0.f));
	RawMesh.VertexPositions.Emplace(FVector(100.f, 100.f, 0.f));
	RawMesh.VertexPositions.Emplace(FVector(0.f, 100.f, 0.f));

	RawMesh.WedgeIndices.Emplace(0);
	RawMesh.WedgeIndices.Emplace(1);
	RawMesh.WedgeIndices.Emplace(2);

	RawMesh.WedgeIndices.Emplace(0);
	RawMesh.WedgeIndices.Emplace(2);
	RawMesh.WedgeIndices.Emplace(3);

	RawMesh.WedgeIndices.Emplace(1);
	RawMesh.WedgeIndices.Emplace(0);
	RawMesh.WedgeIndices.Emplace(3);

	RawMesh.WedgeIndices.Emplace(1);
	RawMesh.WedgeIndices.Emplace(3);
	RawMesh.WedgeIndices.Emplace(2);

	// Create a static mesh from the FRawMesh
	UStaticMesh* StaticMesh = NewObject&lt;UStaticMesh&gt;();
	StaticMesh-&gt;AddSourceModel();
	FStaticMeshSourceModel&amp; SourceModel = StaticMesh-&gt;GetSourceModel(0);
	SourceModel.RawMeshBulkData-&gt;SaveRawMesh(RawMesh);

	StaticMesh-&gt;Build(false);

	UStaticMeshComponent* Mesh = NewObject&lt;UStaticMeshComponent&gt;(ActorOwner);
	UE_LOG(LogTemp, Warning, TEXT(&quot;Calling Mesh-&gt;SetStaticMesh(%x)...&quot;), (void*)StaticMesh);
	// crashes here:
	Mesh-&gt;SetStaticMesh(StaticMesh);
	Mesh-&gt;SetMaterial(0, CreateMaterial(Color));
	Mesh-&gt;SetCollisionProfileName(TEXT(&quot;Pawn&quot;));
	Mesh-&gt;SetHiddenInGame(false);
	Mesh-&gt;RegisterComponent();
	return Mesh;
}

UMaterialInstanceDynamic* AMyActor::CreateMaterial(FLinearColor Color)
{
	FStringAssetReference MaterialRef(TEXT(&quot;/Game/SimBlank/Materials/GlossyRedMaterial&quot;));
	UMaterialInterface* LoadedMaterial = Cast&lt;UMaterialInterface&gt;(StaticLoadObject(UMaterialInterface::StaticClass(), nullptr, *MaterialRef.ToString()));
	UMaterialInstanceDynamic* NewMaterial = UMaterialInstanceDynamic::Create(LoadedMaterial, this);
	NewMaterial-&gt;SetVectorParameterValue(&quot;BaseColor&quot;, Color);
	return NewMaterial;
}

which I call in the first tick of my plugin, with:

MeshActor = World-&gt;SpawnActor&lt;AActor&gt;();
MeshActor-&gt;SetRootComponent(CreateMesh(MeshActor, FLinearColor::Gray));
MeshActor-&gt;SetActorLocation(GetActorLocation() + FVector(100.0f, 0.0f, 40.0f));

but the above code crashes at Mesh-&gt;SetStaticMesh(StaticMesh);.

Before crashing it prints:

Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\build++UE5\Sync\Engine\Source\Runtime\Core\Public\Containers\Array.h] [Line: 752] Array index out of bounds: 0 from an array of size 0

To make a simpler test, I removed the part where I create the FRawMesh and also the call to SourceModel.RawMeshBulkData-&gt;SaveRawMesh(RawMesh), however it crashes in the same way, with the same assertion failed message. Code:

UStaticMeshComponent* AMyActor::CreateMesh(AActor* ActorOwner, FLinearColor Color)
{
	UStaticMesh* StaticMesh = NewObject&lt;UStaticMesh&gt;();
	StaticMesh-&gt;AddSourceModel();
	FStaticMeshSourceModel&amp; SourceModel = StaticMesh-&gt;GetSourceModel(0);
	//SourceModel.RawMeshBulkData-&gt;SaveRawMesh(RawMesh);

	StaticMesh-&gt;Build(false);

	UStaticMeshComponent* Mesh = NewObject&lt;UStaticMeshComponent&gt;(ActorOwner);
	UE_LOG(LogTemp, Warning, TEXT(&quot;Calling Mesh-&gt;SetStaticMesh(%x)...&quot;), (void*)StaticMesh);
	// crashes here:
	Mesh-&gt;SetStaticMesh(StaticMesh);
	Mesh-&gt;SetMaterial(0, CreateMaterial(Color));
	Mesh-&gt;SetCollisionProfileName(TEXT(&quot;Pawn&quot;));
	Mesh-&gt;SetHiddenInGame(false);
	Mesh-&gt;RegisterComponent();
	return Mesh;
}

What's the correct way to create a static mesh from raw mesh data?

答案1

得分: 1

I think your RawMesh is missing additional information. 我认为你的RawMesh缺少额外的信息。

I haven't tested your code but creating RawMesh and saving it to the StaticMesh works on my end by adding values in WedgeColors, WedgeTangent, WedgeTexCoords, FaceMaterialIndices, and FaceSmoothingMasks. 我尚未测试过你的代码,但通过在WedgeColorsWedgeTangentWedgeTexCoordsFaceMaterialIndicesFaceSmoothingMasks中添加值,我成功创建了RawMesh并保存到StaticMesh中。

As an example: 作为示例:

FRawMesh CreateQuadRawMesh()
{
FVector3f EmptyVector = FVector3f(0, 0, 0);
FColor WhiteVertex = FColor(255, 255, 255, 255);

FRawMesh QuadRawMesh;
QuadRawMesh.VertexPositions.Emplace(FVector3f(0.f, 0.f, 0.f));
QuadRawMesh.VertexPositions.Emplace(FVector3f(100.f, 0.f, 0.f));
QuadRawMesh.VertexPositions.Emplace(FVector3f(100.f, 100.f, 0.f));
QuadRawMesh.VertexPositions.Emplace(FVector3f(0.f, 100.f, 0.f));

QuadRawMesh.WedgeIndices.Emplace(0);
QuadRawMesh.WedgeIndices.Emplace(1);
QuadRawMesh.WedgeIndices.Emplace(2);

QuadRawMesh.WedgeIndices.Emplace(0);
QuadRawMesh.WedgeIndices.Emplace(2);
QuadRawMesh.WedgeIndices.Emplace(3);

QuadRawMesh.WedgeIndices.Emplace(1);
QuadRawMesh.WedgeIndices.Emplace(0);
QuadRawMesh.WedgeIndices.Emplace(3);

QuadRawMesh.WedgeIndices.Emplace(1);
QuadRawMesh.WedgeIndices.Emplace(3);
QuadRawMesh.WedgeIndices.Emplace(2);

for (int i = 0; i &lt; 4; ++i)
{
    QuadRawMesh.WedgeColors.Add(WhiteVertex);
    QuadRawMesh.WedgeColors.Add(WhiteVertex);
    QuadRawMesh.WedgeColors.Add(WhiteVertex);

    QuadRawMesh.WedgeTangentX.Add(EmptyVector);
    QuadRawMesh.WedgeTangentX.Add(EmptyVector);
    QuadRawMesh.WedgeTangentX.Add(EmptyVector);

    QuadRawMesh.WedgeTangentY.Add(EmptyVector);
    QuadRawMesh.WedgeTangentY.Add(EmptyVector);
    QuadRawMesh.WedgeTangentY.Add(EmptyVector);

    QuadRawMesh.WedgeTangentZ.Add(EmptyVector);
    QuadRawMesh.WedgeTangentZ.Add(EmptyVector);
    QuadRawMesh.WedgeTangentZ.Add(EmptyVector);

    for (int UVIndex = 0; UVIndex &lt; MAX_MESH_TEXTURE_COORDS; UVIndex++)
    {
        QuadRawMesh.WedgeTexCoords[UVIndex].Add(FVector2f(0.0f, 0.0f));
        QuadRawMesh.WedgeTexCoords[UVIndex].Add(FVector2f(0.0f, 0.0f));
        QuadRawMesh.WedgeTexCoords[UVIndex].Add(FVector2f(0.0f, 0.0f));
    }

    QuadRawMesh.FaceMaterialIndices.Add(0);
    QuadRawMesh.FaceSmoothingMasks.Add(0xFFFFFFFF); // Phong ?
}

return QuadRawMesh;

}

英文:

I think your RawMesh is missing additional information. I haven't tested your code but creating RawMesh and saving it to the StaticMesh works on my end by adding values in WedgeColors, WedgeTangent, WedgeTexCoords, FaceMaterialIndices and FaceSmoothingMasks.

As an example:

FRawMesh CreateQuadRawMesh()
{
    FVector3f EmptyVector = FVector3f(0, 0, 0);
    FColor WhiteVertex = FColor(255, 255, 255, 255);

    FRawMesh QuadRawMesh;
    QuadRawMesh.VertexPositions.Emplace(FVector3f(0.f, 0.f, 0.f));
    QuadRawMesh.VertexPositions.Emplace(FVector3f(100.f, 0.f, 0.f));
    QuadRawMesh.VertexPositions.Emplace(FVector3f(100.f, 100.f, 0.f));
    QuadRawMesh.VertexPositions.Emplace(FVector3f(0.f, 100.f, 0.f));

    QuadRawMesh.WedgeIndices.Emplace(0);
    QuadRawMesh.WedgeIndices.Emplace(1);
    QuadRawMesh.WedgeIndices.Emplace(2);

    QuadRawMesh.WedgeIndices.Emplace(0);
    QuadRawMesh.WedgeIndices.Emplace(2);
    QuadRawMesh.WedgeIndices.Emplace(3);

    QuadRawMesh.WedgeIndices.Emplace(1);
    QuadRawMesh.WedgeIndices.Emplace(0);
    QuadRawMesh.WedgeIndices.Emplace(3);

    QuadRawMesh.WedgeIndices.Emplace(1);
    QuadRawMesh.WedgeIndices.Emplace(3);
    QuadRawMesh.WedgeIndices.Emplace(2);

    for (int i = 0; i &lt; 4; ++i)
    {
        QuadRawMesh.WedgeColors.Add(WhiteVertex);
        QuadRawMesh.WedgeColors.Add(WhiteVertex);
        QuadRawMesh.WedgeColors.Add(WhiteVertex);

        QuadRawMesh.WedgeTangentX.Add(EmptyVector);
        QuadRawMesh.WedgeTangentX.Add(EmptyVector);
        QuadRawMesh.WedgeTangentX.Add(EmptyVector);

        QuadRawMesh.WedgeTangentY.Add(EmptyVector);
        QuadRawMesh.WedgeTangentY.Add(EmptyVector);
        QuadRawMesh.WedgeTangentY.Add(EmptyVector);

        QuadRawMesh.WedgeTangentZ.Add(EmptyVector);
        QuadRawMesh.WedgeTangentZ.Add(EmptyVector);
        QuadRawMesh.WedgeTangentZ.Add(EmptyVector);

        for (int UVIndex = 0; UVIndex &lt; MAX_MESH_TEXTURE_COORDS; UVIndex++)
        {
            QuadRawMesh.WedgeTexCoords[UVIndex].Add(FVector2f(0.0f, 0.0f));
            QuadRawMesh.WedgeTexCoords[UVIndex].Add(FVector2f(0.0f, 0.0f));
            QuadRawMesh.WedgeTexCoords[UVIndex].Add(FVector2f(0.0f, 0.0f));
        }

        QuadRawMesh.FaceMaterialIndices.Add(0);
        QuadRawMesh.FaceSmoothingMasks.Add(0xFFFFFFFF); // Phong ?
    }

    return QuadRawMesh;
}

huangapple
  • 本文由 发表于 2023年5月17日 20:13:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76271979.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定