Download

Accessing Vertex Positions of static mesh

Hello community :slight_smile:

I’m trying to integrate a system into UE4 we had as an external content pipeline for CE3 that let us build large amounts of corridors for our hobby project.

For that I need to somehow get a hold of the vertex positions in a static mesh, containing a 3D shape like this one:

To that end I tried to create a new Blueprint node which would get a UStaticMeshComponent as input and puts out the vertices of that mesh in given order as a TArray<FVector>, like so:

StaticMesh->LODData[0].PaintedVertices[X].Position; //for each vertex of course :slight_smile:

(I do have that BP node part up and running as part of the UObjectPlugin)

Yet, no matter what I try and what different parts of the static mesh I try to access that could hold the info I want, they all come back as empty or invalid or as cats and dogs living together.
I tried looking at its LodData, RenderData and all the others that would make half sense, same non-result.

It seems so simple but the solution still evades me. :frowning:

I am hoping you guys can help me figure this out. (Please bear in mind, C++ n00b here :smiley: )

You want the PositionVertex not the Painted, that’s why its all cats and dogs :slight_smile:

Also you need to convert the verticies from UStaticMesh asset space into World Actor space, including scaling and rotation!


**Code For You**

Here's my code which I put together for you



```


//~~~~~~~~~~~~~~~~~~~~
//				Vertex Buffer
if(!IsValidLowLevel()) return;
if(!StaticMeshComponent) return;
if(!StaticMeshComponent->StaticMesh) return;
if(!StaticMeshComponent->StaticMesh->RenderData) return;

if(StaticMeshComponent->StaticMesh->RenderData->LODResources.Num() > 0)
{
	FPositionVertexBuffer* VertexBuffer = &StaticMeshComponent->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer;
	if (VertexBuffer) 
	{
		const int32 VertexCount = VertexBuffer->GetNumVertices();
		for (int32 Index = 0;  Index < VertexCount; Index++ )
		{
			//This is in the Static Mesh Actor Class, so it is location and tranform of the SMActor
			const FVector WorldSpaceVertexLocation = **GetActorLocation() + GetTransform().TransformVector(VertexBuffer->VertexPosition(Index));**
			//add to output FVector array
		}
	}
}


```



The Critical Part

This is the critical part that took me long time to figure out on my own during the Beta

converts the UStaticMesh vertex into world actor space including Translation, Rotation, and Scaling!!


const FVector WorldSpaceVertexLocation = **GetActorLocation() + GetTransform().TransformVector(VertexBuffer->VertexPosition(Index));**

:slight_smile:

Rama

Thanks a lot Rama, that worked! :smiley:

Next sushi is on me!

Here’s the code for everyone:

Header:



#pragma once

#include "Components/StaticMeshComponent.h"
#include "CorridorBlueprintFunctionLib.generated.h"

UCLASS(MinimalAPI)
class ACorridorBlueprintFunctionLib : public AActor
{
	GENERATED_UCLASS_BODY()

	UFUNCTION(BlueprintPure, Category = "Corridor", meta = (Keywords = "corridor vertex mesh meshdata", NativeBreakFunc))
	TArray<FVector> MeshData(const UStaticMeshComponent* StaticMeshComponent);
};


and the cpp:



#include "UObjectPluginPrivatePCH.h"
#include "CorridorBlueprintFunctionLib.h"
#include "Components/StaticMeshComponent.h"

ACorridorBlueprintFunctionLib::ACorridorBlueprintFunctionLib(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
}

TArray<FVector> ACorridorBlueprintFunctionLib::MeshData(const UStaticMeshComponent* StaticMeshComponent)
{
	TArray<FVector> vertices = TArray<FVector>();

	//~~~~~~~~~~~~~~~~~~~~
	// Many thanks to Rama for this solution! :)
	//
	// Vertex Buffer
	if (!IsValidLowLevel()) return vertices;
	if (!StaticMeshComponent) return vertices;
	if (!StaticMeshComponent->StaticMesh) return vertices;
	if (!StaticMeshComponent->StaticMesh->RenderData) return vertices;

	if (StaticMeshComponent->StaticMesh->RenderData->LODResources.Num() > 0)
	{
		FPositionVertexBuffer* VertexBuffer = &StaticMeshComponent->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer;
		if (VertexBuffer)
		{
			const int32 VertexCount = VertexBuffer->GetNumVertices();
			for (int32 Index = 0; Index < VertexCount; Index++)
			{
				//This is in the Static Mesh Actor Class, so it is location and tranform of the SMActor
				const FVector WorldSpaceVertexLocation = GetActorLocation() + GetTransform().TransformVector(VertexBuffer->VertexPosition(Index));
				//add to output FVector array
				vertices.Add(WorldSpaceVertexLocation);
			}
		}
	}	
	
	return vertices;
}


Many thanks again Rama. Now we can continue with our corridors YAY :smiley:

Happy coding.

Ruben

Yaaay!

:slight_smile:

Rama

Thanks a lot Rama and Rube, this is exactly what I was looking for!

I also needed to get vertex data for volumes (brush actors) and managed to figure that thanks to this thread. Here’s the snippet with brush specific part in bold:



TArray<FVector> vertices = TArray<FVector>();
	TResourceArray<FModelVertex, 0U> modelVertices = **volumeOrBrushActor->Brush->VertexBuffer.Vertices;**

	for (FModelVertex vert : modelVertices)
	{
		const FVector WorldSpaceVertexLocation = volumeOrBrushActor->GetActorLocation() + GetTransform().TransformVector(vert.Position);
		vertices.AddUnique(WorldSpaceVertexLocation);
	}

	return vertices;


A quick digression - can this be simplified further with some functional programming construct?
eg pseudo code: Transform( ModelVerts, FUNC{vert -> actorLocation + GetTransform().TransformVector(vert.Position)} ); would accomplish all of that in one line but I’m not sure of the C++ equivalent.

Wow thanks for sharing guys! This sure comes in handy ^^

Any idea how to get the vertexes for a UPrimitiveComponent though?

PS- Is accessing the vertexes of a basic squared mesh expensive?

What is the actual end class of your Primitive Component class hierarchy? Is it Brush/BSP, Static Mesh, Skeletal ?

I dont think primitive component is something you use directly, you need at least a box component, sphere component, etc.

No accessing the vertices is not expensive, at least not until you start looping over 50k or 100k of them. But if you break up the loop you’ll still be fine :slight_smile:

Nevermind lol

**BP Node Released

Access All Vertex Locations of Any Static Mesh**

I just released a BP node to get all vertex locations, scaled translated and rotated, of any static mesh component!

C++ source code is in the download

This pic was achieved using only my custom BP node, also available to you via link above!
560b4f2b24fb116ffc5c2ddfd4f04754501ad6c2.jpeg

Rama

The LOD information doesn’t get updated if you rescale the object or am I doing something wrong?

Apparently it doesn’t, because when I use a basic cube mesh (default) it works fine, but if I scale that same mesh, sideways,upwards,etc, the found vertexes are still in the same position as if they were a cube.

Images:
Normal:


Rescaled:

@Horus: It also looks like the rotation is off. Did you change the Actors or Components transformation or both?

The way the vertices are transformed looks wrong to me. But I also still haven’t had that in-depth look at the engine I would have liked.

Lets assume you import a static mesh asset. The vertices of the static mesh are in model space just like they were imported.
Now a StaticMeshComponent has a StaticMesh. But the StaticMeshComponent can be translated, rotated, scaled. So in order to go from model to component space you have to transform the vertices through this first.
Finally a StaticMeshComponent is attached to A(n)Actor. The Actor also has a transformation consisting of translation, rotation and scale (which is applied to “all” components). To finally reach world space for the vertices the component space needs to be transformed by the actors transformation as well.
Theoretically there could be more transformations inbetween. For example if the StaticMeshComponent is attached to a socket which animates via some sort of skeleton. Depending on how “deep” this “inheritance” goes you’ll have quite a few calculations to do.

This may be completely wrong so please correct me in that case so I can learn too. :slight_smile:

Oh its off because the prime mesh, the cube, is tilted as you can see in the first image, my guess is the engine accesses the LOD information of the initial mesh, being the cube mesh, and takes that as reference.
I will read your entire reply as soon as I get home, and thanks for taking your time to help.

Sorry finally found time to read your reply. Yes it makes perfect sense, in theory, though I’m not sure how things work on the engine.

Wouldn’t one expect for this type of math to be implemented as a base of UE4? I mean, proper vertex calculation might be somewhat important lol

I noticed this as well in my initial testing with static meshes. Luckily volume/brush actors (which is what I need for now) do provide accurate vertex information even after scaling/rotation or even translation of individual vertices through the geometry edit tool.

Not trying to hijack the topic. But, is it possible to get vertices of all triangles present in the static mesh? I have been wanting to do that since a long time but couldn’t find any method to do so.

Guess I’ll have to take this one to Epic, hopefully they will implement it, makes no sense to have inaccurate information.

@evenger- You mean like in my picture?

The problem is that Rama’s transform code only works for meshes at the origin of the actor. UnrealEverything is on the right track but it’s actually dead simple to fix:


const FVector WorldSpaceVertexLocation = StaticMeshComponent->GetComponentTransform().TransformPosition(VertexBuffer->VertexPosition(Index));

1 Like

You are absolutely right!

Great job mate

I have a crash I’m able to reproduce with VertexBuffer->VertexPosition(index). When I via console type “Open -map-” with an actor that tries to loop through all vertices and index them using ->VertexPosition(i), it gives me “Unable to read memory” exception (out of bounds). I can’t check the Data variable in the VertexBuffer, but my guess would be that it is null. Still; it claims that the num of vertices are > 0, (actually ~40000 - which is correct). Anyone able to shed some light to this? I made a bug report/question that you can view here: FPositionVertexBuffer::VertexPosition crashes in shipping - UE4 AnswerHub

It also has the entire bit of code I’m using. Thank you for taking your time.
Matt.

Hi guys! Not that I want to hijack the thread, but I’m quite desperate and this seemed at least mildly related to my problem.

Is there any possibility something similar could be done with SkeletalMeshes? What I want to do is freeze a SkeletalMesh in a pose and obtain the vertex positions of the mesh in that pose, and then procced to dump those positions to a file. A more accurate description of the problem can be found here. Unfortunately no one suggested anything :frowning: