Change mesh vertex at runtime (Apply custom Transformation on mesh)

Hello everyone, I’m working on a game system that allow the player to transform certain object . Translataion, Rotation and Scale are pretty straighforward, but the tricky part is the player must be able to Shear and Reflect the object.

Beleive me, if I could avoid these transformations I would, but it’s a boss’s request :frowning: .

I know how to access the vertices with that

		FPositionVertexBuffer* vBuffer = &_mesh->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer;

I do my calculus stuffs without problem, but how could I force the mesh reconstruction ??? (the problem)

I know several persons says “it’s impossible to change vertices at runtime”, but there’s certainly a solution.

I know even if it works, it will be slow, but I don’t care at this point because it won’t happen often.

I digged the core mesh/render code for several days without success.

Any suggestions/solutions or anything else will be appreciate.

If you need more details let me know.

gamer08

Hey again Gamer08, moving over here since it will easier for other people to find relevant information. I’m currently at work and I’m not tasked with vertices manipulation so I’ll have to refresh my memory once I get home but have you checked out the FDynamicRHI::RHICreateVertexBuffer function?

If you have the vertex buffer you want then this should apply it to the mesh. According to the API you can even call it at runtime. Here’s an example (written by Epic in the 4.7 engine) of how to use it to create a unit cube:

class FUnitCubeVertexBuffer : public FVertexBuffer
{
public:
	/**
	* Initialize the RHI for this rendering resource
	*/
	void InitRHI() override
	{
		const int32 NumVerts = 8;
		TResourceArray<FVector4, VERTEXBUFFER_ALIGNMENT> Verts;
		Verts.SetNumUninitialized(NumVerts);

		for (uint32 Z = 0; Z < 2; Z++)
		{
			for (uint32 Y = 0; Y < 2; Y++)
			{
				for (uint32 X = 0; X < 2; X++)
				{
					const FVector4 Vertex = FVector4(
						(X ? -1 : 1),
						(Y ? -1 : 1),
						(Z ? -1 : 1),
						1.0f
						);

					Verts[GetCubeVertexIndex(X, Y, Z)] = Vertex;
				}
			}
		}

		uint32 Size = Verts.GetResourceDataSize();

		// Create vertex buffer. Fill buffer with initial data upon creation
		FRHIResourceCreateInfo CreateInfo(&Verts);
		VertexBufferRHI = RHICreateVertexBuffer(Size, BUF_Static, CreateInfo);
	}
};

Hope it helps!

Hey Philip thanks again,

I’ll try when I get home.

I let you know.

gamer08

Hey philip, I’m really busy right now, but i did not forget you.

I’ll test ans let you know.

gamer08

Hello Philip,

After few days of trying couple of things, your idea thanks anyway.

I’ll post my code and the “result on screen” for future starting point if someone wanna try.

First the code,

TArray<FVector> vec;
	FMatrix shearMatrix = FMatrix(FVector(1, 0, 0), 
		                           FVector(0, 1, 0.1), 
								   FVector(0, 0, 1), 
								   FVector(0, 0, 0));

if(!IsValidLowLevel()) return;
if(!_mesh) return;
if(!_mesh->StaticMesh) return;
if(!_mesh->StaticMesh->RenderData) return;

	if (_mesh->StaticMesh->RenderData->LODResources.Num() > 0)
	{
		FPositionVertexBuffer* vBuffer = &_mesh->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer;

		if (vBuffer)
		{
			const int32 nbVertices = vBuffer->GetNumVertices();
			for (int32 index = 0; index < nbVertices; index++)
			{
				const FVector position = GetActorLocation() + GetTransform().TransformVector(vBuffer->VertexPosition(index));
				vec.Add(position);
			}
		}

		for (FVector& v : vec)
			v = MatrixMultiplication(shearMatrix, v);
		
		_mesh->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer.Init(vec);
		_mesh->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer.InitRHI();

		_mesh->MarkRenderStateDirty();
		_mesh->MarkRenderDynamicDataDirty();
		_mesh->MarkRenderTransformDirty();
	}

Before function call :

After function call :

Thanks again and if someones have an idea how to achieve mesh reconstruction at runtime, I’m open to everything.

In the mean time, I did a “pseudo shear and reflection” with the tranform even if not right.

gamer08

Thx for sharing the code. However, there is a problem which you can see from your screenshot: all the actor using the same static mesh is changed. Is there a way to only modify one actor’s mesh without change others?

Hi tianqi,

To be honest I don’t know and as I said my stuff did not work at first.

If someone can give an answer it could be cool even if my topic is old.

gamer08

The solution would be to generate a new static mesh from the old one, modify the vertex data and then finally replace the selected actor’s mesh.

Hello Philip,

Your answer is excellent!
But I want to ask a question. If I change the TResourceArray, would the VertexBufferRHI change accordingly?
And one more question, can it be done if I use the C float array not the TResourceArray to create the VertexBufferRHI?