It is currently Sat Aug 22, 2020 2:12 pm


All times are UTC




Post new topic Reply to topic  [ 128 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6 ... 13  Next
Author Message
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Fri Jan 20, 2012 9:10 pm 

Joined: Wed Jan 11, 2012 7:33 pm
Posts: 109
I changed a little bit of it to get the correct colourValue but I don't know how I can compare the ColourValue returned from getColourAt(x,y,z) to the current height in my for loop that iterates over all the voxels. I think I'm trying to compare a float value to the int value in the for loop so it throws an error at compile time. Any ideas on how I should do this? Thanks!

Code:
   Ogre::Image myTerrainHM;
   myTerrainHM.load("terrain.png","General");
   
   //Create a volume 
    LargeVolume<uint8_t> volData(myTerrainHM.getWidth(),256,myTerrainHM.getHeight()); 
    //Clear volume to zeros. 
    //FIXME - Add function to PolyVox for this. 
    for(unsigned int z = 0; z < volData.getDepth(); ++z) 
    { 
            for(unsigned int y = 0; y < volData.getHeight(); ++y) 
            { 
                    for(unsigned int x = 0; x < volData.getWidth(); ++x) 
                    { 
                            volData.setVoxelAt(x,y,z,0); 
                    } 
            } 
    } 
 
    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) 
                    { 
                            //We check the red channel, but in a greyscale image they should all be the same. 
                            ColourValue height = myTerrainHM.getColourAt(x,y,0);   
                            //Set the voxel based on the height. 
                            if(y <= height.r) 
                            { 
                                    volData.setVoxelAt(x,y,z,1); 
                            } 
                            else if(y <= height) 
                            { 
                                    volData.setVoxelAt(x,y,z,2); 
                            } 
                            //Zero the faces 
                            //FIXME - looks like a bug - shouldn't be -2? 
                            //if((x == 0) || (y == 0) || (z == 0) || (x == volumeSideLength-2) || (y == volumeSideLength-2) || (z == volumeSideLength-2)) 
                            //{ 
                            //      volIter.setVoxel(0); 
                            //} 
                    } 
            } 
    }


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Sat Jan 21, 2012 3:35 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
What kind of terrain do you want to generate? Will it be cubic or smooth (based on marching cubes). Assuming smooth, you should probably use Density8 as your voxelType. Also, use a stable release (not Git master) because changes are taking place with this.

If you use Density8 then I think you need to set your voxel values to either 0 or 255 depending on whether they should be solid or not. You can also use something like Density8::getMaximumDensity() instead of 255 (I forget exactly what it is called - this is changing in the future).

You probably don't want to compare 'y' to 'height' as height is a ColourValue. Instead just compare it to 'height.r' as all channels should be the same for a grey scale image. You may need to adjust the values... for example if 'height.r' is a float between 0.0 and 1.0 you may need to multiply if by 255 (or whatever the height of you volume is) to make them comparable.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Sat Jan 21, 2012 6:24 pm 

Joined: Wed Jan 11, 2012 7:33 pm
Posts: 109
Yes, I wanted a smooth terrain using marching cubes. Which function should I use to smooth it? I'm also running into some trouble using the Ogre mesh code in the Wiki. Mainly around here - beginIndex and endIndex are 0 so the for loop never goes anywhere

Code:
   // Begin writing to manualObject
   unsigned int uLodLevel = 0;
   int beginIndex = mesh2.m_vecLodRecords[uLodLevel].beginIndex;
   int endIndex = mesh2.m_vecLodRecords[uLodLevel].endIndex;
   for(int index = beginIndex; index < endIndex; ++index) {
      const PolyVox::PositionMaterialNormal& vertex = vecVertices[vecIndices[index]];
      const PolyVox::Vector3DFloat& v3dVertexPos = vertex.getPosition();
      const PolyVox::Vector3DFloat& v3dVertexNormal = vertex.getNormal();
      //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength);
      const PolyVox::Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast<PolyVox::Vector3DFloat>(mesh2.m_Region.getLowerCorner());
      ogreMesh->position(v3dFinalVertexPos.getX(), v3dFinalVertexPos.getY(), v3dFinalVertexPos.getZ());
      ogreMesh->normal(v3dVertexNormal.getX(), v3dVertexNormal.getY(), v3dVertexNormal.getZ());
      uint8_t mat = vertex.getMaterial() + 0.5;
      uint8_t red = mat & 0xF0;
      uint8_t green = mat & 0x03;
      uint8_t blue = mat & 0x0C;
      ogreMesh->colour(red*2, green*4, blue*4);// just some random colors, I'm too lazy for hsv
   }


UPDATE:
I changed the code to look like so. I'm not sure if changing to a simpleVolume instead of a largeVolume makes any difference, but I still don't know why my mesh isn't getting any vertices or indices from the surfaceExtraction. My for loop seems to set the density ok, but maybe it's not?

Code:
   // Heightmap to use for voxel filling
   Ogre::Image myTerrainHM;
   myTerrainHM.load("terrain.png","General");
   
   //Create a volume 
    SimpleVolume<Density8> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(myTerrainHM.getWidth(),256,myTerrainHM.getHeight())));

   // Set voxel type
   Density8 voxel;
   voxel.setMaterial(0);

    //Clear volume to zeros. 
    //FIXME - Add function to PolyVox for this. 
   /*
    for(unsigned int z = 0; z < volData.getDepth(); ++z) 
    { 
            for(unsigned int y = 0; y < volData.getHeight(); ++y) 
            { 
                    for(unsigned int x = 0; x < volData.getWidth(); ++x) 
                    { 
                            volData.setVoxelAt(x,y,z,voxel); 
                    } 
            } 
    } 
   */

   // loop through all voxels and set density for each based on heightmap
    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) 
                    { 
                            //We check the red channel, but in a greyscale image they should all be the same. 
                            ColourValue color = myTerrainHM.getColourAt(x,y,0); 
                     //RGBA colorRGBA = color.getAsRGBA();
                            //Set the voxel based on the height. 
                            if(y <= color.r * 256) 
                            { 
                        voxel.setMaterial(1);
                                    volData.setVoxelAt(x,y,z,voxel); 
                            } 
                            else if(y >= color.r * 256) 
                            { 
                        voxel.setMaterial(2);
                                    volData.setVoxelAt(x,y,z,voxel); 
                            } 
                            //Zero the faces 
                            //FIXME - looks like a bug - shouldn't be -2? 
                            //if((x == 0) || (y == 0) || (z == 0) || (x == volumeSideLength-2) || (y == volumeSideLength-2) || (z == volumeSideLength-2)) 
                            //{ 
                            //      volIter.setVoxel(0); 
                            //}
                    } 
            } 
    }    

   //PolyVox::Volume<Material8> volume(128,128,128);

   // now add some data to it
   //PolyVox::smoothRegion<MaterialDensityPair44>(volData, volData.getEnclosingRegion());

   // Make a surfaceMesh from the voxelData
   SurfaceMesh<PositionMaterialNormal> mesh;
   SurfaceMesh<PositionMaterialNormal> mesh2;

   // Extract the surface
   PolyVox::SurfaceExtractor<SimpleVolume, Density8> suf(&volData, volData.getEnclosingRegion(), &mesh);
   suf.execute(); // bug - mesh contains no vertices after this line!


UPDATE 2 : Setting the density rather than setting the material worked for getting the verts and indices

UPDATE 3 : For some reason the decimation wasn't passing values from mesh to mesh2, so I just used mesh to loop through it's indices and add to the manualObject, but for some reason I'm getting the same value across the x or z plane so it looks like the screenshot below, instead of a terrain like it should


Attachments:
screenshot01212012_111257860.gif
screenshot01212012_111257860.gif [ 175.86 KiB | Viewed 3029 times ]
Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Sun Jan 22, 2012 9:09 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
drwbns wrote:
Which function should I use to smooth it?


You should probably smmoth the volume data (rather than the mesh) which you can do using LowPassFilter. See TestLowPassFilter.cpp for an example. Make sure you get your surface extraction working as xpected before you try this though.

drwbns wrote:
UPDATE 2 : Setting the density rather than setting the material worked for getting the verts and indices


When you have a voxel of type Density8 it's not actually possible to set the material... I should have been more clear about this. The setMaterial() function on this class either does nothing or throw an assert (I forget which). This is a part of PolyVox which is currently being refactored because it can be confusing. For now, you can just use Density8 and setDensity()... we'll worry about materials when all that is working for you.

drwbns wrote:
UPDATE 3 : For some reason the decimation wasn't passing values from mesh to mesh2, so I just used mesh to loop through it's indices and add to the manualObject, but for some reason I'm getting the same value across the x or z plane so it looks like the screenshot below, instead of a terrain like it should


I'm not sure what you mean here.. I don't see you calling PolyVox's decimation (MeshDecimator) in your code. If you are using this, then are you saying it all looks correct before you perform decimation but then decimation breaks it? Can you show before and after?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Sun Jan 22, 2012 5:02 pm 

Joined: Wed Jan 11, 2012 7:33 pm
Posts: 109
I was using the code from the wiki here -http://www.volumesoffun.com/polyvox/documentation/dokuwiki/rendering_a_volume_in_ogre

Code:
std::cout << "smoothing volume" << std::endl;
PolyVox::smoothRegion<PolyVox::Material8>(volume, volume.getEnclosingRegion());
std::cout << "updating volume surface" << std::endl;
{
  PolyVox::SurfaceExtractor<PolyVox::Material8> suf(&volume, volume.getEnclosingRegion(), &mesh);
  suf.execute();
}
std::cout << "decimating meshes" << std::endl;
{
  PolyVox::MeshDecimator<PolyVox::PositionMaterialNormal> decim(&mesh, &mesh2);
  decim.execute();
}


I took out the smoothing code because I think it's outdated and with the decimation, the surface didn't show at all. Here's my current code without decimation, which actually crashes in Debug mode during surface extraction. I also wanted to note that if I change from a simpleVolume to a largeVolume of the same size, the largeVolume takes a very very very long time to iterate over, and the MeshDecimation also takes a very very long time, even with a simpleVolume.

Code:
   // Heightmap to use for voxel filling
   Ogre::Image myTerrainHM;
   myTerrainHM.load("terrain.png","General");
   
   //Create a volume 
    SimpleVolume<Density8> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(myTerrainHM.getWidth(),256,myTerrainHM.getHeight())));

   // Set voxel type
   Density8 voxel;

   // loop through all voxels and set density for each based on heightmap
    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) 
                    { 
                            //We check the red channel, but in a greyscale image they should all be the same. 
                            ColourValue color = myTerrainHM.getColourAt(x,y,0); 
                     //RGBA colorRGBA = color.getAsRGBA();
                            //Set the voxel based on the height. 
                            if(y <= color.r * 256) 
                            { 
                        voxel.setDensity(voxel.getMaxDensity());
                                    volData.setVoxelAt(x,y,z,voxel); 
                            } 
                            else if(y >= color.r * 256) 
                            { 
                        voxel.setDensity(voxel.getMinDensity());
                                    volData.setVoxelAt(x,y,z,voxel); 
                            }
                    } 
            } 
    }    

   // Make a surfaceMesh from the voxelData
   SurfaceMesh<PositionMaterialNormal> mesh;

   // Extract the surface
   PolyVox::SurfaceExtractor<SimpleVolume, Density8> suf(&volData, volData.getEnclosingRegion(), &mesh);
   suf.execute();

   const std::vector<PolyVox::PositionMaterialNormal>& vecVertices = mesh.getVertices();
   const std::vector<uint32_t>& vecIndices = mesh.getIndices();

   Ogre::ManualObject* ogreMesh;

   // create something to draw the PolyVox stuff to
   ogreMesh = mKeyDevices.mSceneMgr->createManualObject("PolyVox Mesh");

   // YES we do intend to change the mesh later -.-
   ogreMesh->setDynamic(true);
   ogreMesh->begin("OverhangTerrain_simple", Ogre::RenderOperation::OT_TRIANGLE_LIST);
   Ogre::SceneNode* ogreNode = mKeyDevices.mSceneMgr->getRootSceneNode()->createChildSceneNode("testnode1", Ogre::Vector3(20, 0, 0));
   
   // Begin writing to manualObject
   unsigned int uLodLevel = 0;

   for(int index = 0; index < vecIndices.size(); index++) {
      const PolyVox::PositionMaterialNormal& vertex = vecVertices[vecIndices[index]];
      const PolyVox::Vector3DFloat& v3dVertexPos = vertex.getPosition();
      const PolyVox::Vector3DFloat& v3dVertexNormal = vertex.getNormal();
      //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength);
      const PolyVox::Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast<PolyVox::Vector3DFloat>(mesh.m_Region.getLowerCorner());
      ogreMesh->position(v3dVertexPos.getX(), v3dVertexPos.getY(), v3dVertexPos.getZ());
      ogreMesh->normal(v3dVertexNormal.getX(), v3dVertexNormal.getY(), v3dVertexNormal.getZ());
      uint8_t mat = vertex.getMaterial() + 0.5;
      uint8_t red = mat & 0xF0;
      uint8_t green = mat & 0x03;
      uint8_t blue = mat & 0x0C;
      ogreMesh->colour(red*2, green*4, blue*4);// just some random colors, I'm too lazy for hsv
   }

   // end writing
   ogreMesh->end();

   //atach object to node
   ogreNode->attachObject(ogreMesh);


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Mon Jan 23, 2012 4:49 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
Ok, you should forget about smoothing, decimation, and LargeVolume until you have the basic extraction working correctly. As I understand it, even with these things disabled you are having a crash during surface extraction? Are you running in debug mode? If so, where is the crash and what does the call stack look like? Is it actually an assert()?

Be aware that debug mode is very slow, so make sure you are working on relatively small data set sizes (e.g. an input image of 256x256 should be ok).

Regarding the LargeVolume, it is indeed slower than SimpleVolume though I haven't measured how much. You can probably improve performance by increasing the number of blocks kept in memory and kept uncompressed. For example, see these two functions:

http://www.volumesoffun.com/polyvox/doc ... a51584c2b5

But there is probably some scope for optimization of this class.

As for the MeshDecimator, it does get very slow as the mesh gets large. Normally you won't extract a single mesh for your whole volume but will instead break the mesh down into several parts, in which case the decimation is not so bad. But I do think we need a new solution for decimation (probably integrated with the SurfaceExtractor).


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Mon Jan 23, 2012 5:06 pm 

Joined: Wed Jan 11, 2012 7:33 pm
Posts: 109
Hi David, I only get the crash during surfaceExtraction when running in debug mode. Release works ok for extraction. Here's the assert -

---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Assertion failed!

Program: ...
File: c:\users\andrew\downloads\polyvo...\surfac...tor.inl
Line: 620

Expression: ind0 < 1000000

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts

(Press Retry to debug the application - JIT must be enabled)
---------------------------
Abort Retry Ignore
---------------------------


Attachments:
screenshot01232012.gif
screenshot01232012.gif [ 56.31 KiB | Viewed 3005 times ]
Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Mon Jan 23, 2012 5:37 pm 

Joined: Wed Jan 11, 2012 7:33 pm
Posts: 109
David Williams wrote:
As for the MeshDecimator, it does get very slow as the mesh gets large. Normally you won't extract a single mesh for your whole volume but will instead break the mesh down into several parts, in which case the decimation is not so bad. But I do think we need a new solution for decimation (probably integrated with the SurfaceExtractor).


I tried setting the values for blocks in memory while using a largeVolume and that worked great for speeding up the iteration of the volume, but the decimation still takes forever. Quoting you - do you think decimation is a bad idea for a heightmap of 513 x 513 ?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Tue Jan 24, 2012 11:03 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
I have seen that assert in the past but I don't have an explanation for it at the moment. I would consider it a bug in PolyVox. However, most people have not encountered it so there must be something specific you are doing. Some things to try:

Try extracting a mesh which is smaller than the whole volume. It could be that the problem is coming from handling the edge cases, which are always more complex. Instead of:

Code:
PolyVox::SurfaceExtractor<SimpleVolume, Density8> suf(&volData, volData.getEnclosingRegion(), &mesh);


try (untested code):

Code:
Region reducedRegion = volData.getEnclosingRegion();
reducedRegion.shiftLowerCorner(Vector3DInt32(2,2,2));
reducedRegion.shiftUpperCorner(Vector3DInt32(-2,-2,-2));
PolyVox::SurfaceExtractor<SimpleVolume, Density8> suf(&volData, reducedRegion, &mesh);


and see if the assert goes away.

Also, you specifcally mention a size of 513x513... whereas a power of two would be more usual (e.g. 512x512). Perhaps there is some issue here.

As for decimation, yes, your mesh is too large. Most people using PolyVox will have a single large volume, but they will generate a number of smaller meshes from it. This way, once the data is modified, you only have to update the affected meshes rather than reextracting the whole thing. A typical mesh size might be something like 32x32x32 or 64x64x64 (could use some tests here).

The performance of the MeshDecimator decreases a lot as the number of vertices increases. Yours will have hundreds of times more vertices that the sizes I indicate above, so you won't be able to decimte that effectively. Sorry, but decimation of meshes is currently a weak area of PolyVox. If you really need it you could also consider an external library.

Also, how are you runnig decimation if the SurfaceExtractor is crashing? Is the SurfaceExtractor only crashing in some cases? Or you have only tested the decimation in release mode (when there are no asserts)? If code asserts is debug mode but runs in release you should not consider it reliable.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Realtime Ogre 1.8 Terrain Component manipulation
PostPosted: Tue Jan 24, 2012 5:00 pm 

Joined: Wed Jan 11, 2012 7:33 pm
Posts: 109
Quote:
Also, how are you runnig decimation if the SurfaceExtractor is crashing? Is the SurfaceExtractor only crashing in some cases? Or you have only tested the decimation in release mode (when there are no asserts)? If code asserts is debug mode but runs in release you should not consider it reliable.


The surfaceExtraction only crashes in debug mode with that assert, it works fine in release, but decimation fails in all cases.


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 128 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6 ... 13  Next

All times are UTC


Who is online

Users browsing this forum: Bing [Bot] and 5 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