Access to mesh data in object via C++

Hi - I’m complete newbie in UE4, so maybe my question is trivial. Suppose we create simple Actor class and we give it some primitive shape - sphere, for example. I would like now to access the mesh data from the level of C++ class - all vertices, triangles etc - and modify it for my application. So far, after few hours of searching and trying, I have found experimental plugin Procedural Mesh Component, which gives me - in very robust way - this option. I wonder, if there is a method to access same thing in vanilla UE4. We have UMeshComponent class, which should have some way to do it. This discussion on board had some trick to access it, but sadly, it doesn’t work where I try to implement it. Maybe I do something wrong.

What I ask is some example of complete new class creating it’s own mesh from scratch and reading it afterwards. Maybe it’s impossible without plugins.

You need a new component like this: UYourComponent : public UStaticMeshComponent.

Then:

#if WITH_EDITOR
void UYourComponent::OnComponentCreated()
{
	// create the UStaticMesh object
	UStaticMesh* newMesh = NewObject<UStaticMesh>(this, TEXT("ProceduralStaticMesh"));

	// add one LOD for the base mesh
	new(newMesh->SourceModels) FStaticMeshSourceModel();

	// use the new mesh
	SetStaticMesh(newMesh);

	Super::OnComponentCreated();
}

void UYourComponent::Build()
{
	if (StaticMesh == nullptr)
		return;

	//*** Fill m_RawMesh (FRawMesh type) with your custom data ***//

	// save raw mesh
	StaticMesh->SourceModels[0].RawMeshBulkData->SaveRawMesh(m_RawMesh);

	// setup materials
	int32 numMaterials = 0;
	for (int32 idx : m_RawMesh.FaceMaterialIndices)
		numMaterials = FMath::Max(numMaterials, idx + 1);

	// setup the SectionInfoMap & default material
	for (int32 SectionIdx = 0; SectionIdx < numMaterials; ++SectionIdx)
	{
		StaticMesh->Materials.Add(UMaterial::GetDefaultMaterial(MD_Surface));

		FMeshSectionInfo Info = StaticMesh->SectionInfoMap.Get(0, SectionIdx);
		Info.MaterialIndex = SectionIdx;
		Info.bEnableCollision = true;
		Info.bCastShadow = true;
		StaticMesh->SectionInfoMap.Set(0, SectionIdx, Info);
	}

	StaticMesh->MarkPackageDirty();
	StaticMesh->Build();
	MarkRenderStateDirty();
	FlushRenderingCommands();
}
#endif

Please note the #if WITH_EDITOR.

If you want to access/modify the geometry in the standalone build there is another story (it’s a lot harder but still possible).

Hope it helps!

Yes. In the example above I’ve used UStaticMeshComponent as base class.

My compiler can’t eat FlushRenderingCommands function, and to use FRawMesh type I had to add “RawMesh” in cs build (and include “RawMesh.h” in file).

Try adding “RenderCore” in cs build file.

Also RawMesh should be added like:

if (UEBuildConfiguration.bBuildEditor)
PublicDependencyModuleNames.Add(“RawMesh”);

Okay, thanks to your post I’ve got what I have wanted. Thank you very much! I’ll leave my code post under for next person looking for answer.

Here is my raw code to get all vertex positions. If I would want to create new vertices, I need to change LoadRawMesh into SaveRawMesh.

I took simple C++ class as Pawn object. Probably would work with Actor, too.

.cpp file:

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyProject13.h"
#include "CiastkoPawn.h"
#include "RawMesh.h"

ACiastkoPawn::ACiastkoPawn()
{
	PrimaryActorTick.bCanEverTick = true;

	USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
	RootComponent = SphereComponent;
	SphereComponent->InitSphereRadius(40.0f);
	SphereComponent->SetCollisionProfileName(TEXT("Pawn"));

	UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));

	SphereVisual->SetupAttachment(RootComponent);
	static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));

	SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
	SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
	
	FRawMesh rawMesh;

	SphereVisual->StaticMesh->SourceModels[0].RawMeshBulkData->LoadRawMesh(rawMesh);

	TArray<FVector> vert = rawMesh.VertexPositions;

	int N = vert.Num();

	for (int i = 0; i < N; i++) {
		FVector vec = vert[i];
		UE_LOG(LogTemp, Log, TEXT("Vertex %d: %f %f %f"),i,vec.X,vec.Y,vec.Z);
	}

}

This way I gave my object a Sphere shape and accessed it’s vertex data. In MyFile.Build.cs I added one more string to list of loaded plugins:

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "RawMesh" });

Do you have any info for doing this in a packaged game? I was able to use the ENQUEUE_UNIQUE_RENDER_COMMAND_… to retrieve the indexbuffer but haven’t been able to get the positionvertexbuffer.

If you only want to read the geometry data in you packaged build, then cache it when building your custom mesh (we are doing this to dynamically paint explosion damages into a vertex color channel and we need the distance between vertices and explosion’s center).

If you want your geometry to be fully dynamic @ runtime, UStaticMesh is not a good option. I guess it is possible to go fully dynamic by packing you positions into OverrideVertexColors, then use this into your vertex shader with some crazy material hacks. Do you need more info on this?

Hello, I’m trying to access the bulkData, but for some reason I don’t have access to any of the functions (I already included “RawMesh.h”, even though I had to include it as “Developer/RawMesh/Public/RawMesh.h” otherwise I get an error)

125971-dissertationtesting+-+microsoft+visual+studio-000402.png

Also when I go in to RawMesh.h I get those errors on each of them

125973-dissertationtesting+-+microsoft+visual+studio-000403.png

Any clue?

Thanks

Thanks a lot! This is helpful for me. But What if I want to create a UStaticMesh used vertices and indices data in a standalone build,what should I do?
Best Wish!

hi, I test the code list above. but when showed in editor, the actor turned completed black when i touch it. Could you give me some advices? thx