Announcement

Collapse
No announcement yet.

Accessing Vertex Positions of static mesh

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

    #16
    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?
    [On Hold]WIP: Vertex-Based Ledge Detection/Parkour Engine

    Looking for fellow programmers to develop a project.

    Comment


      #17
      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));

      Comment


        #18
        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
        [On Hold]WIP: Vertex-Based Ledge Detection/Parkour Engine

        Looking for fellow programmers to develop a project.

        Comment


          #19
          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.

          Comment


            #20
            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 :-(

            Comment


              #21
              splinemesh?

              could this be modified to work with splinemesh?
              Crystal Flux a Snowboarding Shooter:https://twitter.com/GadzGamz
              Pinball Template:http://www.pinterest.com/gadzgamz/pinball-template/
              Hot Springs Air Hockey: Hot Springs
              Latest release: Bonsai Golf Coral

              Comment


                #22
                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!

                Comment


                  #23
                  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?

                  Comment


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

                    Comment


                      #25
                      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?

                      Comment


                        #26
                        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

                        Comment


                          #27
                          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

                          Comment


                            #28
                            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.
                            Contract

                            Need help?
                            google hangout or gmail

                            Comment


                              #29
                              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.

                              Steam Early Access: ❀ Drunk On Nectar (The Nature Simulator) ❀

                              UE4 Plugins: DoN’s Dynamic Mesh FX | DoN’s 3D Pathfinding

                              Comment


                                #30
                                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

                                Comment

                                Working...
                                X