It is currently Sat Aug 22, 2020 4:28 am


All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Flat Plane Tutorial
PostPosted: Thu Sep 05, 2013 1:38 pm 
User avatar

Joined: Thu Sep 05, 2013 3:38 am
Posts: 51
Location: USA - Arizona
Hello! This is my first post to the PolyVox Forums!

I would like to start off saying what an amazing job you two are doing on PolyVox and I hope to see it's continued success. That being said, would it be possible to get a quick tutorial on how to create a flat plane so I can compare it to the sphere tutorial?

Thanks in advance, your help is greatly appreciated! :)

_________________
Dream Big Or Go Home.
ENet - http://enet.bespin.org
Recast - https://github.com/memononen/recastnavigation
Irrlicht - http://irrlicht.sourceforge.net/forum
PolyVox - http://www.volumesoffun.com/phpBB3/
Help Me Help You.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Fri Sep 06, 2013 6:25 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
Hi, assuming you are working with BasicExample you can use the following function to create a floor in your volume:

Code:
void createFloorInVolume(SimpleVolume<uint8_t>& volData, uint32_t floorHeight)
{
   //This vector hold the position of the center of the volume
   Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);

   //This three-level for loop iterates over every voxel in the volume
   for (int z = 1; z < volData.getDepth()-1; z++)
   {
      for (int y = 1; y < volData.getHeight()-1; y++)
      {
         for (int x = 1; x < volData.getWidth()-1; x++)
         {
            uint8_t uVoxelValue = 0;

            //If the current voxel is lower than the floor then we make it solid.
            if(y < floorHeight)
            {
               //Our new voxel value
               uVoxelValue = 255;
            }

            //Wrte the voxel value into the volume   
            volData.setVoxelAt(x, y, z, uVoxelValue);
         }
      }
   }
}


You can probably understand the differences, but I'll just point out that it's iterating over less of the volume. e.g. the loops start at 1 instead of 0 and finish 1 element earlier as well. This stops the floor going right to the edge of the volume, because if it goes right to the edge then the sides will not be drawn (which may or may not be what you want, but in this case will stop you seeing the floor until you rotate).

You can call:

Code:
createFloorInVolume(volData, 10);


Instead of createSphereInVolume(). Both functions overwrite any initial contents so you have to modify them further if you want both floor and a sphere.

** Important Note: ** You actually helped me find a bug here. When you run the code you'll see a ceiling instead of a floor... it turns out the OpenGL window is upside down and I didn't notice because you can't tell with a sphere! You can apply the fix found here: https://bitbucket.org/volumesoffun/poly ... are-upside


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Fri Sep 06, 2013 11:35 pm 
User avatar

Joined: Thu Sep 05, 2013 3:38 am
Posts: 51
Location: USA - Arizona
Thank you very much my kind sir I was able to get what I needed completed, now I have a large flat surface to walk around on!

I'm glad I could help you squash that little bug also ;)

This may be a hop and a skip from a flat plane but could you point me in the right direction to generating non-flat surfaces? I would like to get hills and valleys going so it's not such a dull flat surface.

Maybe with use of a .bmp height-map so I can use other colors for extra information in the future such as placing buildings for example.


Thank you very much for all the help it's greatly appreciated.

_________________
Dream Big Or Go Home.
ENet - http://enet.bespin.org
Recast - https://github.com/memononen/recastnavigation
Irrlicht - http://irrlicht.sourceforge.net/forum
PolyVox - http://www.volumesoffun.com/phpBB3/
Help Me Help You.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Sun Sep 08, 2013 6:27 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
kklouzal wrote:
This may be a hop and a skip from a flat plane but could you point me in the right direction to generating non-flat surfaces? I would like to get hills and valleys going so it's not such a dull flat surface.


The example function I posted takes a parameter which controls the height of the floor. To get varying heights you should not receive this value as a parameter but instead compute it from the x and z positions. This means that the height of your floor will vary depending on the x and z position in the volume.

kklouzal wrote:
Maybe with use of a .bmp height-map...


Yep, in this case you lookup the height of the floor using the (x,z) position in the volume as the (x,y) position in your bitmap.

kklouzal wrote:
...so I can use other colors for extra information in the future such as placing buildings for example.


I assume you are working with the cubic style terrain here? Colours are a bit complex as you will need some shader programming skills, but have a read of the material on 'texture mapping', and in particular on 'using the material identifier'.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Sun Sep 08, 2013 7:54 am 
User avatar

Joined: Thu Sep 05, 2013 3:38 am
Posts: 51
Location: USA - Arizona
This is really awesome, thank you so much for the help!

I was able to create the mesh with a .bmp heightmap and irrlicht using this function

Code:
void createFloorInVolume2(SimpleVolume<MaterialDensityPair44>& volData, uint32_t floorHeight, IVideoDriver* driver)
{
   //Get our heightmap
   IImage* Heightmap = driver->createImageFromFile("content/heightmaps/heightmap1.bmp");
 
   //This three-level for loop iterates over every voxel in the volume
   for (int z = 1; z < volData.getDepth()-1; z++)
   {
      for (int x = 1; x < volData.getWidth()-1; x++)
      {
         SColor HeightCol = Heightmap->getPixel(x, z);
         uint32_t Height = (HeightCol.getRed() + HeightCol.getGreen() + HeightCol.getBlue())/48;

         //Y should be our height
         for (int y = 1; y < volData.getHeight()-1; y++)
         {
            //Get Old Voxel
            MaterialDensityPair44 Voxel = volData.getVoxelAt(x,y,z);

            //If the current voxel is lower than the floor then we make it solid.
            if(y < Height)
            {
               //Solid Voxel

               //New Density Value
               uint8_t uDensity = MaterialDensityPair44::getMaxDensity();

               //Modify Density
               Voxel.setDensity(255);

               Voxel.setMaterial(1);

               //Write New Voxel Into Volume
               volData.setVoxelAt(x,y,z,Voxel);
            } else {
               //Empty Voxel

               //Wrte the voxel value into the volume   
               volData.setVoxelAt(x, y, z, Voxel);
            }
         }
      }
   }
}


Finally I would like to attempt to make a smooth mesh from all this!
Creating more than 256x256x16 takes quite a while to load, irrlicht also complains about running out of verticies and crashes on anything much larger.

I would think I can create multiple meshes and place them in a sort of grid system, I'll give this a try.

EDIT:
I was able to create a semi-smooth mesh using this extractor
Code:
MarchingCubesSurfaceExtractor<SimpleVolume<MaterialDensityPair44>> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);


It was a simple conversion from the CubicExtractor, it is semi-smooth though :P is there a way to turn up the smoothing factor?

I still haven't played with the idea of multiple meshes in a grid pattern for larger play fields.

_________________
Dream Big Or Go Home.
ENet - http://enet.bespin.org
Recast - https://github.com/memononen/recastnavigation
Irrlicht - http://irrlicht.sourceforge.net/forum
PolyVox - http://www.volumesoffun.com/phpBB3/
Help Me Help You.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Mon Sep 09, 2013 8:44 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
kklouzal wrote:
I was able to create the mesh with a .bmp heightmap and irrlicht using this function


Great, it looks like you are on the right path.

kklouzal wrote:
I would think I can create multiple meshes and place them in a sort of grid system, I'll give this a try.


Yes, the surface extractors take a 'region' parameter which you can use for this purpose. If your voxel data changes you can then make sure you only regenerate the meshes for the affected regions.

kklouzal wrote:
It was a simple conversion from the CubicExtractor, it is semi-smooth though :P is there a way to turn up the smoothing factor?


Basically you need to smooth the underlying volume data. Read this thread for some initial ideas (note that I'm linking to page 2 - you can go back further for more context).

http://www.volumesoffun.com/phpBB3/viewtopic.php?p=3599#p3599

Then we can talk about it some more :-)


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Mon Sep 09, 2013 7:52 pm 
User avatar

Joined: Thu Sep 05, 2013 3:38 am
Posts: 51
Location: USA - Arizona
Thank you again David it's really helping me understand how PolyVox works internally.

So, from what I gather on that topic, the smoothing is calculated from the Density of the voxel?
How exactly does this influence the smoothing?

I tried to create a function that iterates back through the volData once the origional data is set via heightmap, then take the surrounding 6 voxels density and average them together to get our current voxel's density.

Code:
void SmoothTerrainData(SimpleVolume<MaterialDensityPair44>& volData)
{
   for (int z = 1; z < volData.getDepth()-1; z++)
   {
      for (int x = 1; x < volData.getWidth()-1; x++)
      {
         for (int y = 0; y < volData.getHeight()-1; y++)
         {
            //Get Our Voxel
            MaterialDensityPair44 Voxel = volData.getVoxelAt(x,y,z);
            //Get The Voxels Around Us
            //Left
            MaterialDensityPair44 LTVoxel = volData.getVoxelAt(x+1,y,z);
            uint8_t LTDen = LTVoxel.getDensity();
            //Right
            MaterialDensityPair44 RTVoxel = volData.getVoxelAt(x-1,y,z);
            uint8_t RTDen = RTVoxel.getDensity();
            //Up
            MaterialDensityPair44 UPVoxel = volData.getVoxelAt(x,y+1,z);
            uint8_t UPDen = UPVoxel.getDensity();
            //Down
            MaterialDensityPair44 DNVoxel = volData.getVoxelAt(x,y-1,z);
            uint8_t DNDen = DNVoxel.getDensity();
            //Front
            MaterialDensityPair44 FTVoxel = volData.getVoxelAt(x,y,z+1);
            uint8_t FTDen = FTVoxel.getDensity();
            //Back
            MaterialDensityPair44 BKVoxel = volData.getVoxelAt(x,y,z-1);
            uint8_t BKDen = BKVoxel.getDensity();
            //Compute Our Average Density

            uint8_t AvgDen = (LTDen + RTDen + UPDen + DNDen + FTDen + BKDen)/6;

            //Set Our Voxel To This New Density
            Voxel.setDensity(AvgDen);
         }
      }
   }
}


It appears to have had no effect on the resulting mesh what so ever.
Image


Also for people who might stumble upon this in the future to get PolyVox and Irrlicht integrated here is what we're doing so far:

Create voldata:
Code:
//Create Our PolyVox Volume
   SimpleVolume<MaterialDensityPair44> volData(Region(Vector3DInt32(0,0,0), Vector3DInt32( 256, 64, 256 )));


Create our Image to be used as a heightmap
Code:
   //Get our heightmap
   IImage* Heightmap = driver->createImageFromFile("content/heightmaps/terrain-heightmap.bmp");


Run both of those through our CreateTerrainFromHieightmap function
Code:
void GenerateTerrainFromHeightmap(SimpleVolume<MaterialDensityPair44>& volData, IImage* Heightmap)
{
   //This three-level for loop iterates over every voxel in the volume
   for (int z = 0; z <= volData.getDepth(); z++)
   {
      for (int x = 0; x <= volData.getWidth(); x++)
      {
         //Get Our Position On The Heightmap
         SColor HeightCol = Heightmap->getPixel(x, z);
         //Compute Voxel's Height From The Pixel Color
         uint32_t Height = (HeightCol.getRed() + HeightCol.getGreen() + HeightCol.getBlue())/volData.getHeight();
         
         for (int y = 0; y < Height; y++)
         {
            //Get Our Voxel
            MaterialDensityPair44 Voxel = volData.getVoxelAt(x,y,z);
               //Modify Density
               Voxel.setDensity(255);

               //Modify Material
               Voxel.setMaterial(1);
               
               //Write New Voxel Into Volume
               volData.setVoxelAt(x,y,z,Voxel);
         }
      }
   }
   SmoothTerrainData(volData);
}

Run that through our SmoothTerrainData function

Finally convert the volData to a Mesh Buffer
Code:
IMeshBuffer* ConvertMesh(const SurfaceMesh<PositionMaterialNormal>& mesh)
{
    const vector<uint32_t>& indices = mesh.getIndices();
    const vector<PositionMaterialNormal>& vertices = mesh.getVertices();

    IDynamicMeshBuffer *mb = new CDynamicMeshBuffer(EVT_STANDARD, EIT_32BIT);
    mb->getVertexBuffer().set_used(vertices.size());
    for (size_t i = 0; i < vertices.size(); ++i)
    {
        const Vector3DFloat& position = vertices[i].getPosition();
        const Vector3DFloat& normal = vertices[i].getNormal();
        mb->getVertexBuffer()[i].Pos.X = position.getX();
        mb->getVertexBuffer()[i].Pos.Y = position.getY();
        mb->getVertexBuffer()[i].Pos.Z = position.getZ();
        mb->getVertexBuffer()[i].Normal.X = normal.getX();
        mb->getVertexBuffer()[i].Normal.Y = normal.getY();
        mb->getVertexBuffer()[i].Normal.Z = normal.getZ();
      mb->getVertexBuffer()[i].TCoords = vector2df(position.getX(), position.getZ());
      mb->getVertexBuffer()[i].Color = SColor(255, 255, 255, 255);
    }
    mb->getIndexBuffer().set_used(indices.size());
    for (size_t i = 0; i < indices.size(); ++i)
    {
        mb->getIndexBuffer().setValue(i, indices[i]);
    }
    mb->recalculateBoundingBox();
    return mb;
}


And create a SceneNode from the Mesh Buffer applying a nice pretty texture
Code:
   //Create An Irrlicht Mesh
   SurfaceMesh<PositionMaterialNormal> mesh;
   
   // Extract the mesh From PolyVox
   MarchingCubesSurfaceExtractor<SimpleVolume<MaterialDensityPair44>> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);

   //CubicSurfaceExtractorWithNormals<SimpleVolume<MaterialDensityPair44>> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
   surfaceExtractor.execute();

   // Convert the mesh and hand it to Irrlicht
   SMesh* testMesh = new SMesh;
   IMeshBuffer * testBuffer = ConvertMesh(mesh);
   testMesh->addMeshBuffer(testBuffer);
   testMesh->recalculateBoundingBox();

   //Create a scene node from our mesh
   ISceneNode* testNode= smgr->addMeshSceneNode(testMesh, 0, 0, vector3df(0, 0, 0), vector3df(0, 0, 0),vector3df(1.0F, 1.0F, 1.0F));
   //Scale Our Node
   testNode->setScale(vector3df(1.F,1.F,1.F));
   
   //Create A New Texture
   ITexture* NewTex = driver->getTexture("content/materials/terrain-texture.jpg");
   //Enable Full Bright
   testNode->setMaterialFlag(EMF_LIGHTING, false);
   //Set Our Nodes Material Texture To Our Newly Created Texture
   testNode->setMaterialTexture(0,NewTex);
   //Scale The Texture
   matrix4 mat;
   mat.setTextureScale(.003F,.003F);
   //mat.setScale(.01F);
   testNode->getMaterial(0).setTexture(0,NewTex);
   testNode->getMaterial(0).setTextureMatrix(0,mat);
   testNode->getMaterial(0).setFlag(EMF_LIGHTING, false);

_________________
Dream Big Or Go Home.
ENet - http://enet.bespin.org
Recast - https://github.com/memononen/recastnavigation
Irrlicht - http://irrlicht.sourceforge.net/forum
PolyVox - http://www.volumesoffun.com/phpBB3/
Help Me Help You.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Mon Sep 09, 2013 10:02 pm 
User avatar

Joined: Wed Jan 26, 2011 3:20 pm
Posts: 203
Location: Germany
Quote:
I tried to create a function that iterates back through the volData once the origional data is set via heightmap, then take the surrounding 6 voxels density and average them together to get our current voxel's density.


1. try using the surrounding 26 voxels + the one in the middle!
2. what you are currently doing won't work nicely, you need two volumes, one where you have the nonsmooth data, and one where you write the smooth data. otherwise all the voxels will use already smooth data to compute their value. needless to say, it'll be messy
3. why not generate a smooth landscape to begin with? I'm aware that kind of algorithm isn't as straight forward as your current bmp->voxel algorithm, but it's not that hard to cover all the cases if you assume the bmp data is smooth itself.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Tue Sep 10, 2013 3:01 am 
User avatar

Joined: Thu Sep 05, 2013 3:38 am
Posts: 51
Location: USA - Arizona
I would love to generate smooth data from the beginning, I don't know how to go about doing such a thing though..

I'm basically just trying to create some kind of landscape off the git go, no real preference as to how it looks other than it is smooth and not completely flat.

_________________
Dream Big Or Go Home.
ENet - http://enet.bespin.org
Recast - https://github.com/memononen/recastnavigation
Irrlicht - http://irrlicht.sourceforge.net/forum
PolyVox - http://www.volumesoffun.com/phpBB3/
Help Me Help You.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Flat Plane Tutorial
PostPosted: Tue Sep 10, 2013 8:15 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
In terms of smooth the data I agree with ker's points (1) and (2), and you can use the LowPassFilter to achieve this. Have a read of this thread: http://www.volumesoffun.com/phpBB3/viewtopic.php?f=14&t=530

As for smoothing the data in the beginning I'm not so sure... even if you have a smooth heightmap the problem is that you are making a binary decision about whether each voxel is below or above the specified height. So each voxel is being set as completely empty or completely solid (so the get the stepped artefacts).

I'm not sure about the correct solution so you'll need to do some experimentation here. At some point I need to do it myself as well so that we can import heightmaps as smooth terrain in Cubiquity.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 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