It is currently Sat Aug 22, 2020 3:37 am


All times are UTC




Post new topic Reply to topic  [ 11 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Modifying the voxel terrain
PostPosted: Thu Dec 14, 2017 1:47 pm 

Joined: Thu Dec 14, 2017 10:53 am
Posts: 6
Hey all!
I'm struggling to implement terrain modification using polyvox with unreal engine 4.
I use a raycasting function in UE4 to locate the block location, create a reference of the chunk actor, and then access the PolyVox::PagedVolume<PolyVox::MaterialDensityPair44> pointer to modify the chunk with setVoxel().
Code:


void ATerrainGenManager::EditVoxelAtLoc(FVector Loc)
{
    float locx = Loc.X;
    float locy = Loc.Y;
    float locz = Loc.Z;
   
    PolyVox::MaterialDensityPair44 Air;
   
    Air.setMaterial(1);
    Air.setDensity(255);
   

   
    UE_LOG(LogTemp, Error, TEXT("chunk fullfilled"))
   
    FVector UpdateLoc = GetActorLocation();
    float upx = UpdateLoc.X;
    float upy = UpdateLoc.Y;
    float upz = UpdateLoc.Z;
   
    //org wit up
    PolyVox::Region ToExtract(PolyVox::Vector3DInt32(0, 0, 0), PolyVox::Vector3DInt32(sizevec_x, sizevec_y, sizevec_z));
   
    PolyVox::PagedVolume<PolyVox::MaterialDensityPair44>* VoxChunk = VoxelVolume.Get();
   
    //VoxChunk->getVoxel(10, 10, 10);
   
    /*for (int x = ToExtract.getLowerX(); x <= ToExtract.getUpperX(); x++)
    {
        for (int y = ToExtract.getLowerY(); y <= ToExtract.getUpperY(); y++)
        {
            for (int z = ToExtract.getLowerZ(); z <= ToExtract.getUpperZ(); z++) {
                VoxChunk->setVoxel(x, y, z, Air);
            }
        }
    }*/
   
   
   
   
   
    for (int x = 0; x < 10; x++)
    {
        for (int y = 0; y < 10; y++)
        {
            for (int z = 0; z < 100; z++) {
                //VoxChunk->setVoxel(x, y, z, Air);
                VoxChunk->getChunk(upx, upy, upz)->setVoxel(x, y, z, Air);
                UE_LOG(LogTemp, Error, TEXT("chunk"))
            }
        }
    }
   
   
    // Define variables to pass into the CreateMeshSection function
    auto Vertices = TArray<FVector>();
    auto Indices = TArray<int32>();
    auto Normals = TArray<FVector>();
    auto UV0 = TArray<FVector2D>();
    auto Colors = TArray<FColor>();
    auto Tangents = TArray<FProcMeshTangent>();
   
    //auto ExtractedMesh = PolyVox::extractCubicMesh(PolyVoxelVolume.Get(), ToExtract);
   
    auto ExtractedMesh = PolyVox::extractMarchingCubesMesh(VoxelVolume.Get(), ToExtract);
   
    auto DecodedMesh = decodeMesh(ExtractedMesh);
   
    auto Index = DecodedMesh.getNoOfIndices();
   
    //UE_LOG(LogTemp, Error, TEXT("number of indices: %d"), Index)
    /*if(Index > 0){
     for (uint32 i = 0; i < Index - 2; i+=3)
     UE_LOG(LogTemp, Error, TEXT("Generated"))
     }*/
   
    UE_LOG(LogTemp, Error, TEXT("Loading new indices from the extractor"))
   
    if(Index >= 2){
        // Loop over all of the triangle vertex indices
        for (uint32 i = 0; i < Index - 2; i+=3)
        {
            // We need to add the vertices of each triangle in reverse or the mesh will be upside down
            auto Index = DecodedMesh.getIndex(i + 2);
            auto Vertex2 = DecodedMesh.getVertex(Index);
            Indices.Add(Vertices.Add(FPolyVoxVector(Vertex2.position) * 100.f));
           
            Index = DecodedMesh.getIndex(i + 1);
            auto Vertex1 = DecodedMesh.getVertex(Index);
            Indices.Add(Vertices.Add(FPolyVoxVector(Vertex1.position) * 100.f));
           
            Index = DecodedMesh.getIndex(i);
            auto Vertex0 = DecodedMesh.getVertex(Index);
            Indices.Add(Vertices.Add(FPolyVoxVector(Vertex0.position) * 100.f));
           
            // Calculate the tangents of our triangle
            const FVector Edge01 = FPolyVoxVector(Vertex1.position - Vertex0.position);
            const FVector Edge02 = FPolyVoxVector(Vertex2.position - Vertex0.position);
           
            const FVector TangentX = Edge01.GetSafeNormal();
            FVector TangentZ = (Edge01 ^ Edge02).GetSafeNormal();
           
            for (int32 j = 0; j < 3; j++)
            {
                Tangents.Add(FProcMeshTangent(TangentX, false));
                Normals.Add(TangentZ);
            }
        }
    }
   
   
    Mesh->CreateMeshSection(0, Vertices, Indices, Normals, UV0, Colors, Tangents, true);




As you can see, I'm trying to fill a chunk with solid blocks.
But when I try to modify a chunk, it shrinks and changes shape.
When I use Mesh->UpdateMeshSection(), nothing happens.
What's the right way to modify the terrain with polyvox, and how should I fix my code?
Thanks.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Thu Dec 14, 2017 10:21 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
Hi,

Unfortunately I am not familiar with Unreal so I can't really say if you are doing it correctly. To debug the first thing you need to do is work out whether PolyVox is the problem, or Unreal, or the way you are linking them together.

For example, you say that the problem occurs when doing an update. So presumably you do see a terrain before you start updating? So you know that you have a working code which generates a Unreal mesh from a PolyVox one?

Assuming you have already got this far then create the simplest scene that you can, like a volume with a single voxel set. Does this display correctly? Not try setting the second voxel from your update code (no need for a raycast, just hard-code the change). Does it update? If not, you need to check whether PolyVox is now outputting different data so try printing the vertex positions as there should only be a few of them. Do they change after the update? If they do but you still don't see the change in Unreal then maybe there is a synchronisation problem... what if you delete the Unreal mesh and recreate it rather than just updating it?

These kind of tests should help you see what it going on. Also post a screenshot if you can't get it to work, it helps give me some context. Good luck!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Fri Dec 15, 2017 11:11 am 

Joined: Thu Dec 14, 2017 10:53 am
Posts: 6
David Williams wrote:
Hi,

Unfortunately I am not familiar with Unreal so I can't really say if you are doing it correctly. To debug the first thing you need to do is work out whether PolyVox is the problem, or Unreal, or the way you are linking them together.

For example, you say that the problem occurs when doing an update. So presumably you do see a terrain before you start updating? So you know that you have a working code which generates a Unreal mesh from a PolyVox one?

Assuming you have already got this far then create the simplest scene that you can, like a volume with a single voxel set. Does this display correctly? Not try setting the second voxel from your update code (no need for a raycast, just hard-code the change). Does it update? If not, you need to check whether PolyVox is now outputting different data so try printing the vertex positions as there should only be a few of them. Do they change after the update? If they do but you still don't see the change in Unreal then maybe there is a synchronisation problem... what if you delete the Unreal mesh and recreate it rather than just updating it?

These kind of tests should help you see what it going on. Also post a screenshot if you can't get it to work, it helps give me some context. Good luck!


Hey David, thanks for replying!
I just solved the problem of modifying primitive voxel volumes, but now i'm having a problem with modifying the paged volume. I can modify the terrain, but the updated terrain mesh is different with the original one.
It might be that i didn't use set the region variable that extractCubicMesh needs to gain specific data that matches this specific chunk.
Here's a video demonstrating the problem:https://youtu.be/93FOxwieHVM

Code:
    PolyVox::MaterialDensityPair44 Air;
    Air.setMaterial(0);
    Air.setDensity(0);
    UE_LOG(LogTemp, Error, TEXT("chunk fullfilled"))
   
    FVector loc = GetActorLocation(); //returns the world location vector of the chunk actor
    float upx = loc.X;
    float upy = loc.Y;
    float upz = -25.0f; // the height to spawn the chunks
   
   // this should be where things go wrong, as the extracted data might not be accurate
   //sizevec_x y and z represent the chunk volume's size
    PolyVox::Region ToExtract(PolyVox::Vector3DInt32(0, 0, 0), PolyVox::Vector3DInt32(sizevec_x, sizevec_y, sizevec_z + upz));

    PolyVox::PagedVolume<PolyVox::MaterialDensityPair44>* VoxChunk = VoxelVolume.Get();
    //ToExtract.getLowerX() - 5
   
    // set the voxels
    for (int x = 0; x <= 30; x++)
    {
        for (int y = 0; y <= 30; y++)
        {
            for (int z = 0; z <= 30; z++) {
                VoxChunk->setVoxel(x, y, z, Air);
            }
        }
    }

  //Extract the chunk data using the ToExtract variable
  auto ExtractedMesh = PolyVox::extractCubicMesh(VoxelVolume.Get(), ToExtract);



As you can see, the terrain chunk, after being edited, has a different heightmap for some reason.

I'm quite sure that the engine is interpreting the values correctly, as i'm using the same algo that generates the terrain to read the vertices.
Thanks!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Sat Dec 16, 2017 10:43 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
My memory is a little hazy but I think the Mesh class contains an offset, which you need to add on to your vertex positions as you send them to Unreal. That is, the returned vertex positions might not be relative to the origin but instead be relative to this offset. Have a check of the code and PolyVox examples to see if you can find this being used. Try printing out this offset as well as the vertex positions to see if you can spot what is going on.

Also, for simplicity I would encourage you to use the RawVolume rather than the PagedVolume. The RawVolume is faster and simpler ( internally it is just one big array), and is fine for volumes up to e.g. 256x256x256. You can (and should) still use a Region when extracting from a RawVolume. The concept of Regions for extraction is different from the concept of Chunks inside PagedVolume, and so if you initially just work with RawVolume then you can avoid this confusion.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Sat Dec 16, 2017 5:29 pm 

Joined: Thu Dec 14, 2017 10:53 am
Posts: 6
David Williams wrote:
My memory is a little hazy but I think the Mesh class contains an offset, which you need to add on to your vertex positions as you send them to Unreal. That is, the returned vertex positions might not be relative to the origin but instead be relative to this offset. Have a check of the code and PolyVox examples to see if you can find this being used. Try printing out this offset as well as the vertex positions to see if you can spot what is going on.

Also, for simplicity I would encourage you to use the RawVolume rather than the PagedVolume. The RawVolume is faster and simpler ( internally it is just one big array), and is fine for volumes up to e.g. 256x256x256. You can (and should) still use a Region when extracting from a RawVolume. The concept of Regions for extraction is different from the concept of Chunks inside PagedVolume, and so if you initially just work with RawVolume then you can avoid this confusion.

Now I have created a sphere chunk with the raw volume class. However, i'm not quite sure about the way to share the raw volume uint8_t variable declared in the function responsible for chunk construction to the update function.
Code:
// Within the generateChunk() function. Not so sure about how to create a pointer for the update() function to access
PolyVox::RawVolume<uint8_t> volData(PolyVox::Region(PolyVox::Vector3DInt32(0, 0, 0), PolyVox::Vector3DInt32(63, 63, 63)));

The update function has to access the same raw volume that the construction function uses. Do you have any idea?
Thanks.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Sat Dec 16, 2017 7:01 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
davidbrainlittle wrote:
The update function has to access the same raw volume that the construction function uses. Do you have any idea?


I'm not sure about the structure of your code (or of Unreal projects), but in general I would expect you to create the RawVolume on the heap with the 'new' operator so that you have a pointer to it, and then either store that pointer somewhere fairly global or pass it as a parameter into or out of your functions.

Something like (untested):

Code:
PolyVox::RawVolume<uint8_t> volDataPtr = new PolyVox::RawVolume<uint8_t>(PolyVox::Region(PolyVox::Vector3DInt32(0, 0, 0), PolyVox::Vector3DInt32(63, 63, 63)));


Or am I misunderstanding your question?

davidbrainlittle wrote:
Now I have created a sphere chunk with the raw volume class.


Also I will clarify a point with regards to the word 'chunk'. The RawVolume does not use chunks and instead stores all its data in a single array. The PagedVolume does break the voxel data down into several arrays which we call chunks, but this is mostly invisible to you (I think except when providing functions to page data in and out?).

In either case you should have exactly one volume no matter how big your world is. From that single volume you can extract multiple meshes covering different parts of the volume, and then you can then update these individually. I generally refer to these as 'Regions' though other engines may refer to them a chunks. But there is this difference between breaking the voxel data into pieces (chunks) for memory management and breaking the mesh into pieces (regions) for rendering and ease of updating. Most engines do not make this distinction.

So create one volume (probably a RawVolume) and begin by creating one mesh from it. Then try to get that single mesh updating as you expect, and then try breaking it down into multiple regions but still using only one volume.

Sorry if I am telling you something you already know, but this is a common source of confusion :-)


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Sun Dec 17, 2017 10:06 am 

Joined: Thu Dec 14, 2017 10:53 am
Posts: 6
David Williams wrote:
davidbrainlittle wrote:
The update function has to access the same raw volume that the construction function uses. Do you have any idea?


I'm not sure about the structure of your code (or of Unreal projects), but in general I would expect you to create the RawVolume on the heap with the 'new' operator so that you have a pointer to it, and then either store that pointer somewhere fairly global or pass it as a parameter into or out of your functions.

Something like (untested):

Code:
PolyVox::RawVolume<uint8_t> volDataPtr = new PolyVox::RawVolume<uint8_t>(PolyVox::Region(PolyVox::Vector3DInt32(0, 0, 0), PolyVox::Vector3DInt32(63, 63, 63)));


Or am I misunderstanding your question?

davidbrainlittle wrote:
Now I have created a sphere chunk with the raw volume class.


Also I will clarify a point with regards to the word 'chunk'. The RawVolume does not use chunks and instead stores all its data in a single array. The PagedVolume does break the voxel data down into several arrays which we call chunks, but this is mostly invisible to you (I think except when providing functions to page data in and out?).

In either case you should have exactly one volume no matter how big your world is. From that single volume you can extract multiple meshes covering different parts of the volume, and then you can then update these individually. I generally refer to these as 'Regions' though other engines may refer to them a chunks. But there is this difference between breaking the voxel data into pieces (chunks) for memory management and breaking the mesh into pieces (regions) for rendering and ease of updating. Most engines do not make this distinction.

So create one volume (probably a RawVolume) and begin by creating one mesh from it. Then try to get that single mesh updating as you expect, and then try breaking it down into multiple regions but still using only one volume.

Sorry if I am telling you something you already know, but this is a common source of confusion :-)



Thanks for the long reply David!
I managed to solve the pointer problem with the TSharedPtr structure, built within the Unreal Engine. Now I have a huge volume of solid blocks and I can edit it with hard-coded function.
Code:
TSharedPtr<PolyVox::RawVolume<uint8_t>>RawVolTest (new PolyVox::RawVolume<uint8_t>(PolyVox::Region(PolyVox::Vector3DInt32(0, 0, 0), PolyVox::Vector3DInt32(63, 63, 63))));



However, I'm not sure about the way to convert the world position of these voxels to a format that can be interpreted by polyvox. I can edit the volume, but the way whereby I convert the world location to local location doesn't work properly. I spent several hours on it and got quite frustrated :(
Can you please give me some insights about cubiquity, which supports unreal? Can you give some hint about how it deals with converting the world locations of voxels to the local locations that setVoxel() can use?
Thanks for the explanation of the chunk part, btw :D
Thank you!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Tue Dec 19, 2017 11:59 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
I don't know the details of Cubiquity for Unreal because I didn't write that, but I suspect it simply placed the volume a the origin and avoids performing and scaling or translation of the volume, so that local and world space are the same.

I'm getting hazy as to how PolyVox worked because it has been a good couple of years since I used it. But as I recall, when you extract a region the resulting mesh has an offset variable which closely corresponds to the lower corner of the region, and all vertices are relative to that. So probably you create your Unreal mesh, copy the vertex data into it, and then set the position of the Unreal mesh to be the same as the offset of the PolyVox mesh. Alternatively, you could leave the Unreal mesh at the origin and simply add the offset to the vertex positions as you copy them across. Start small, and really print vertex and offset positions (or look in the debugger) to understand what is going on.

However, before you even start messing around with multiple meshes and offsets you should get it working with a single volume, with a single extracted mesh, and with the volume placed at the origin. At this point local space and world space should be the same, so make sure that works first. Then try splitting the volume into just two meshes, and take it from there.

Also, keep in mind that the Cubiquity for Unreal source code is online here: https://github.com/volumesoffun/cubiqui ... eal-engine

I don't know if it is useful though as PolyVox and Cubiquity do have some differences.

Unfortunately I'm going to away until the new year now, so I won't be able to help you further for the next couple of weeks. Good luck with your project until then!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Wed Dec 20, 2017 1:26 am 

Joined: Thu Dec 14, 2017 10:53 am
Posts: 6
David Williams wrote:
I don't know the details of Cubiquity for Unreal because I didn't write that, but I suspect it simply placed the volume a the origin and avoids performing and scaling or translation of the volume, so that local and world space are the same.

I'm getting hazy as to how PolyVox worked because it has been a good couple of years since I used it. But as I recall, when you extract a region the resulting mesh has an offset variable which closely corresponds to the lower corner of the region, and all vertices are relative to that. So probably you create your Unreal mesh, copy the vertex data into it, and then set the position of the Unreal mesh to be the same as the offset of the PolyVox mesh. Alternatively, you could leave the Unreal mesh at the origin and simply add the offset to the vertex positions as you copy them across. Start small, and really print vertex and offset positions (or look in the debugger) to understand what is going on.

However, before you even start messing around with multiple meshes and offsets you should get it working with a single volume, with a single extracted mesh, and with the volume placed at the origin. At this point local space and world space should be the same, so make sure that works first. Then try splitting the volume into just two meshes, and take it from there.

Also, keep in mind that the Cubiquity for Unreal source code is online here: https://github.com/volumesoffun/cubiqui ... eal-engine

I don't know if it is useful though as PolyVox and Cubiquity do have some differences.

Unfortunately I'm going to away until the new year now, so I won't be able to help you further for the next couple of weeks. Good luck with your project until then!


Thanks for the reply! Yeah, I'll spend some time to try this out.
Merry christmas and happy new year. I'll post my progress here when I finish it :)


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Modifying the voxel terrain
PostPosted: Sun Dec 24, 2017 9:43 am 

Joined: Thu Dec 14, 2017 10:53 am
Posts: 6
https://www.youtube.com/watch?v=I_cQoZc ... e=youtu.be

I made it! Thanks for helping :D


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: Majestic-12 [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme created StylerBB.net