Volumes Of Fun http://www.volumesoffun.com/phpBB3/ |
|
Flat Plane Tutorial http://www.volumesoffun.com/phpBB3/viewtopic.php?f=14&t=535 |
Page 1 of 2 |
Author: | kklouzal [ Thu Sep 05, 2013 1:38 pm ] |
Post subject: | Flat Plane Tutorial |
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! |
Author: | David Williams [ Fri Sep 06, 2013 6:25 am ] |
Post subject: | Re: Flat Plane Tutorial |
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 |
Author: | kklouzal [ Fri Sep 06, 2013 11:35 pm ] |
Post subject: | Re: Flat Plane Tutorial |
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. |
Author: | David Williams [ Sun Sep 08, 2013 6:27 am ] |
Post subject: | Re: Flat Plane Tutorial |
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'. |
Author: | kklouzal [ Sun Sep 08, 2013 7:54 am ] |
Post subject: | Re: Flat Plane Tutorial |
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 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. |
Author: | David Williams [ Mon Sep 09, 2013 8:44 am ] |
Post subject: | Re: Flat Plane Tutorial |
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 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 |
Author: | kklouzal [ Mon Sep 09, 2013 7:52 pm ] |
Post subject: | Re: Flat Plane Tutorial |
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. 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); |
Author: | ker [ Mon Sep 09, 2013 10:02 pm ] |
Post subject: | Re: Flat Plane Tutorial |
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. |
Author: | kklouzal [ Tue Sep 10, 2013 3:01 am ] |
Post subject: | Re: Flat Plane Tutorial |
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. |
Author: | David Williams [ Tue Sep 10, 2013 8:15 am ] |
Post subject: | Re: Flat Plane Tutorial |
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. |
Page 1 of 2 | All times are UTC |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |