Announcement

Collapse
No announcement yet.

Accessing Vertex Positions of static mesh

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    Originally posted by IonutStef View Post
    Hi!

    Sorry for reviving this long since dead thread
    First of all, Thank you for all your help, Rama! Your tutorials are fun to watch and makes you think a lot about what you can do.
    The same with this thread full of interesting information.
    I see that there is a way to get all the vertices of the mesh. This is amazing, and close to what I need. but, still, not there...

    My question is.. is there a way to get the Edges of the mesh, as there is with the vertices?
    I need only to know what vertices are adjacent, for a pattern detection AI.

    I've tried doing it by myself, thinking that the order I read the vertices, is given by the connection, but after some tries, I don't know what to think... "Am I doing it wrong, or the order has nothing to do with the connections?"

    Please, could you help me?

    Thank you very much!
    Stefan
    May I ask have you found ways to get the Edges of the mesh?

    Leave a comment:


  • replied
    Originally posted by Burnrate View Post
    But how can the position vertex buffer be retrieved in a packaged game. It's possible to retrieve the index buffer using ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER but it seems the position vertex buffer cannot be acquired the same way. It doesn't work even when the thread is held up using FlushRenderingCommands. I'm trying to use it only during initialization so this wouldn't cause gameplay delay but it seems difficult to grab the data. I don't want to just edit the engine to set bNeedsCPUAccess to true for packaged builds. It would be a waste of memory. Anyone have experience with this?

    I know this is an old thread, but it helped me nonetheless to get the vertex positions of a mesh. I also ran unto the problem that it only works in the editor and not in builds (except when using OpenGL, apparently Unreal chooses to keep them CPU accessible there), and struggled with fixing it.

    For anyone else who ever runs into this exact problem in the future: there's a "Allow CPUAccess" flag you can set on your meshes' properties: https://answers.unrealengine.com/que...s-on-mesh.html

    Leave a comment:


  • replied
    Originally posted by Muzaheed View Post
    where are you putting this part of the code?
    i need to figure out GetTransform() of whose.
    Hey, that post was from 2014 if I were to do this now, I would extract ComponentToWorld from your mesh - i.e. GetComponentTransform() and then use TransformPosition(vert.Position) on it.

    Or you can use TransformVector like the original code did and add it to GetComponentLocation(), should have the same effect in theory.

    GetTransform - i.e. the actor's transform will only work if your static mesh component is also the root component (true for a Static Mesh Actor, but not necessarily for others), so the component's transform should be what you're looking for.


    Edit: If you specifically meant for a Brush/Volume actor, then GetTransform() (the brush/volume actor's transform) is indeed what you're looking for because in that case no primitive components are involved.
    Last edited by VSZ; 05-26-2017, 03:29 PM.

    Leave a comment:


  • replied
    Originally posted by VSZ View Post
    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:

    Code:
    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;

    where are you putting this part of the code?
    i need to figure out GetTransform() of whose.

    Leave a comment:


  • replied
    Originally posted by RyanGadz View Post
    could this be modified to work with splinemesh?
    Shown how here:
    https://forums.unrealengine.com/show...in-world-space

    Leave a comment:


  • replied
    Hi!

    Sorry for reviving this long since dead thread
    First of all, Thank you for all your help, Rama! Your tutorials are fun to watch and makes you think a lot about what you can do.
    The same with this thread full of interesting information.
    I see that there is a way to get all the vertices of the mesh. This is amazing, and close to what I need. but, still, not there...

    My question is.. is there a way to get the Edges of the mesh, as there is with the vertices?
    I need only to know what vertices are adjacent, for a pattern detection AI.

    I've tried doing it by myself, thinking that the order I read the vertices, is given by the connection, but after some tries, I don't know what to think... "Am I doing it wrong, or the order has nothing to do with the connections?"

    Please, could you help me?

    Thank you very much!
    Stefan

    Leave a comment:


  • replied
    But how can the position vertex buffer be retrieved in a packaged game. It's possible to retrieve the index buffer using ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER but it seems the position vertex buffer cannot be acquired the same way. It doesn't work even when the thread is held up using FlushRenderingCommands. I'm trying to use it only during initialization so this wouldn't cause gameplay delay but it seems difficult to grab the data. I don't want to just edit the engine to set bNeedsCPUAccess to true for packaged builds. It would be a waste of memory. Anyone have experience with this?

    Leave a comment:


  • replied
    Simple. You have no AActor's functionality in UBlueprintFunctionLibrary, but the original code does (since it's inherited from AActor).

    Leave a comment:


  • replied
    Originally posted by Rama View Post
    You want the PositionVertex not the Painted, that's why its all cats and dogs

    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

    Code:
    //~~~~~~~~~~~~~~~~~~~~
    //                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!!

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


    Rama
    I'm unable to get this work in the current version of the engine. I've created a c++ function library

    Code:
    #pragma once
    
    #include "Engine.h"
    #include "Components/StaticMeshComponent.h"
    #include "Kismet/BlueprintFunctionLibrary.h"
    #include "StaticMeshResources.h"
    #include "kohLibrary.generated.h"
    
    
    
    
    /**
     * 
     */
    UCLASS()
    class TEST_API UkohLibrary : public UBlueprintFunctionLibrary
    {
        GENERATED_UCLASS_BODY()
    
    
        UFUNCTION(BlueprintPure, Category = "KohFunctions", meta = (Keywords = "vertex mesh get", NativeBreakFunc))
        TArray<FVector> MeshData(const UStaticMeshComponent* StaticMeshComponent);
        
    };

    Code:
    #include "Test.h"#include "kohLibrary.h"
    #include "Components/StaticMeshComponent.h"
    #include "StaticMeshResources.h"
    
    
    UkohLibrary::UkohLibrary(const FObjectInitializer& ObjectInitializer)
        : Super(ObjectInitializer)
    {
    
    
    }
    
    
    TArray<FVector> UkohLibrary::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;
    }
    The errors are located in the red line. What is wrong?

    Leave a comment:


  • replied
    HI guys,
    I've obtained the vertex position of the mesh as you suggested and it worked! Thanks!

    Now I've to get the UV coordinate and the vertex normal for each vertex, how can I obtain such information?

    Thanks in advance!

    Leave a comment:


  • replied
    splinemesh?

    could this be modified to work with splinemesh?

    Leave a comment:


  • replied
    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 :-(

    Leave a comment:


  • replied
    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: https://answers.unrealengine.com/que...es-in-shi.html

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

    Leave a comment:


  • replied
    Originally posted by The Beej View Post
    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:

    Code:
    const FVector WorldSpaceVertexLocation = StaticMeshComponent->GetComponentTransform().TransformPosition(VertexBuffer->VertexPosition(Index));
    You are absolutely right!

    Great job mate

    Leave a comment:


  • replied
    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:

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

    Leave a comment:

Working...
X