Volumes Of Fun http://www.volumesoffun.com/phpBB3/ |
|
Polyvox to Ogre Mesh http://www.volumesoffun.com/phpBB3/viewtopic.php?f=14&t=387 |
Page 1 of 4 |
Author: | drwbns [ Thu Apr 26, 2012 6:58 pm ] |
Post subject: | Polyvox to Ogre Mesh |
Hi guys, Ive recently switched from using a manualObject due to it's glitchy graphics when updated constantly so now Im using the Vertex and Index buffers to recreate the voxels but the generated meshes aren't in the shapes of voxels like they're suppsoed to be. I thought maybe my vertex declaration was wrong or my vertices wern't in the expected order. I'm not sure. Any thoughts? Code: void WorldCraft::PolyMeshToMesh(Polymesh &p)
{ // ************ start mesh build code // Make a surfaceMesh from the voxelData SurfaceMesh<PositionMaterialNormal> mesh; SurfaceMesh<PositionMaterialNormal> mesh2; // Extract the surface //PolyVox::SurfaceExtractor<SimpleVolume, Density8> surf(&resultVolume, fullRegion2, &mesh); // Use if smoothing PolyVox::SurfaceExtractor<LargeVolume, Density8> surf(&volume, p.region, &mesh); // Use for semi-smooth surface //PolyVox::CubicSurfaceExtractorWithNormals <SimpleVolume, Density8> surf(pMesh.volume, pMesh.volume->getEnclosingRegion(), &mesh); // Use if not smoothing try { surf.execute(); } catch(...) { cout << "Failed execute Surface Extractor" << endl; } // Change mesh to mesh2 if using decimation const std::vector<PolyVox::PositionMaterialNormal>& vecVertices = mesh.getVertices(); const std::vector<uint32_t>& vecIndices = mesh.getIndices(); if( vecVertices.size() > 0 && vecIndices.size() > 0) { if (p.mMeshAttached == true){ if(p.entity != NULL) { if(p.entity->isAttached()) { p.node->detachObject(p.entity); mKeyDevices.mSceneMgr->destroyEntity(p.entity); } } p.entity = mKeyDevices.mSceneMgr->createEntity("Polymesh"); p.entity->setMaterialName("Worldcraft/Greengrass"); p.node->attachObject(p.entity); } /// Create the mesh via the MeshManager p.meshOBJ = MeshManager::getSingleton().createManual("Polymesh", "General"); /// Create one submesh p.submeshOBJ = p.meshOBJ->createSubMesh(); // We first create a VertexData Ogre::VertexData* vertexData = new Ogre::VertexData(); // Then, we link it to our Mesh/SubMesh : #ifdef SHARED_GEOMETRY mMesh->sharedVertexData = data; #else p.submeshOBJ->useSharedVertices = false; // This value is 'true' by default p.submeshOBJ->vertexData = vertexData; #endif // We have to provide the number of vertices we'll put into this Mesh/SubMesh vertexData->vertexCount = vecVertices.size(); // Then we can create our VertexDeclaration Ogre::VertexDeclaration* decl = vertexData->vertexDeclaration; // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); //currOffset += VertexElement::getTypeSize(VET_FLOAT3); // normals //vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); //currOffset += VertexElement::getTypeSize(VET_FLOAT3); // allocate the vertex buffer HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, // You can use several different value types here vecIndices.size(), // The number of indices you'll put in that buffer Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY // Properties ); unsigned short* pIndices = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD)); if (p.node == NULL) { p.node = mKeyDevices.mSceneMgr->getRootSceneNode()->createChildSceneNode(p.position); } // 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(); *pVertex++ = v3dVertexPos.getX(); *pVertex++ = v3dVertexPos.getY(); *pVertex++ = v3dVertexPos.getZ(); *pIndices++ = vecIndices[index]; //const PolyVox::Vector3DFloat& v3dVertexNormal = vertex.getNormal(); //*pVertex++ = v3dVertexNormal.getX(); //*pVertex++ = v3dVertexNormal.getY(); //*pVertex++ = v3dVertexNormal.getZ(); } vBuf->unlock(); ibuf->unlock(); /// Set parameters of the submesh p.submeshOBJ->indexData->indexBuffer = ibuf; p.submeshOBJ->indexData->indexCount = vecIndices.size(); p.submeshOBJ->indexData->indexStart = 0; /// Set bounding information (for culling) p.meshOBJ->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100)); p.meshOBJ->_setBoundingSphereRadius(Math::Sqrt(3*100*100)); /// Notify -Mesh object that it has been loaded p.meshOBJ->load(); if (p.mMeshAttached == false){ p.entity = mKeyDevices.mSceneMgr->createEntity("Polymesh"); p.entity->setMaterialName("Worldcraft/Greengrass"); p.node->attachObject(p.entity); p.mMeshAttached = true; } } // Deleted voxel area else { if(p.entity != NULL) { if(p.entity->isAttached()) { p.node->detachObject(p.entity); mKeyDevices.mSceneMgr->destroyEntity(p.entity); } } } } |
Author: | zprg [ Fri Apr 27, 2012 4:38 pm ] |
Post subject: | Re: Polyvox to Ogre Mesh |
excuse im not sure but this looks for me not correct, cause you get the vertex through the indices and i think in this way you get some vertices multiple times. you should use two forloops for vertices and indices?: Code: for(int index = 0; index < vecIndices.size(); index++) {
const PolyVox::PositionMaterialNormal& vertex = vecVertices[vecIndices[index]]; const PolyVox::Vector3DFloat& v3dVertexPos = vertex.getPosition(); *pVertex++ = v3dVertexPos.getX(); *pVertex++ = v3dVertexPos.getY(); *pVertex++ = v3dVertexPos.getZ(); *pIndices++ = vecIndices[index]; } |
Author: | drwbns [ Fri Apr 27, 2012 7:01 pm ] |
Post subject: | Re: Polyvox to Ogre Mesh |
Hmm, I tried like this without much better results - Code: // Indices ( faces )
for(int index = 0; index < vecIndices.size(); index++) { *pIndices++ = vecIndices[index]; } // Vertices ( verts ) for(int index = 0; index < vecVertices.size(); index++) { const PolyVox::PositionMaterialNormal& vertex = vecVertices[index]; const PolyVox::Vector3DFloat& v3dVertexPos = vertex.getPosition(); *pVertex++ = v3dVertexPos.getX(); *pVertex++ = v3dVertexPos.getY(); *pVertex++ = v3dVertexPos.getZ(); } |
Author: | David Williams [ Sat Apr 28, 2012 10:30 pm ] |
Post subject: | Re: Polyvox to Ogre Mesh |
The code is quite long so it's not obvious to me what the problem is, but does it appear to be a problem with PolyVox? For example, if you bypass PolyVox and just pass in hardcoded position and index values then does the mesh show up where you expect? Switching to wireframe might also help identify the problem? |
Author: | drwbns [ Sat Jun 09, 2012 2:00 pm ] | ||
Post subject: | Re: Polyvox to Ogre Mesh | ||
I've revamped my code but I still have trouble getting the entire mesh to display. Sometimes - especially when trying to display multiple PolyMeshes which is just the voxel representation of that region. You'll see what I mean by the picture - the mesh should have a top and full sides, but it doesn't. If I click to add to the top, then the top will show for some reason. Here's my updated code also - Code: // RECENT PolyMeshToMesh
bool WorldCraft::PolyMeshToMesh(Polymesh &p) { // ************ start mesh build code // Make a surfaceMesh from the voxelData // Extract the surface //PolyVox::SurfaceExtractor<SimpleVolume, Density8> surf(&resultVolume, fullRegion2, &mesh); // Use if smoothing PolyVox::CubicSurfaceExtractorWithNormals<LargeVolume, Density8> surf(&volume, p.region, &mesh); // Use for semi-smooth surface //PolyVox::CubicSurfaceExtractorWithNormals <SimpleVolume, Density8> surf(pMesh.volume, pMesh.volume->getEnclosingRegion(), &mesh); // Use if not smoothing try { surf.execute(); } catch(...) { cout << "Failed execute Surface Extractor" << endl; } vertsAppended = false; indicesAppended = false; if (p.mMeshAttached == true){ //p.meshOBJ->unload(); // Destroy all the attached objects SceneNode::ObjectIterator itObject = p.node->getAttachedObjectIterator(); while (itObject.hasMoreElements() ) { Entity * pObject = static_cast<Entity *>(itObject.getNext()); String name = pObject->getName(); if (name.compare(0,10,"nodeMarker") != 0) { pObject->detachFromParent(); mKeyDevices.mSceneMgr->destroyEntity( pObject ); } } p.entity = NULL; Ogre::MeshManager::getSingleton().remove("CustomMesh"+ Ogre::StringConverter::toString(p.position / divisor)); } if( vecVertices.size() > 0 && vecIndices.size() > 0) { /// Create the mesh via the MeshManager Ogre::ResourceManager::ResourceCreateOrRetrieveResult result = MeshManager::getSingleton().createOrRetrieve("CustomMesh"+ Ogre::StringConverter::toString(p.position / divisor), "General", true,tfm,0,HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,false,false); p.meshOBJ = result.first; /// Create one submesh p.submeshOBJ = p.meshOBJ->createSubMesh(); // We first create a VertexData // Then, we link it to our Mesh/SubMesh : #ifdef SHARED_GEOMETRY mMesh->sharedVertexData = data; #else p.submeshOBJ->useSharedVertices = false; // This value is 'true' by default p.submeshOBJ->vertexData = new Ogre::VertexData(); #endif // We have to provide the number of vertices we'll put into this Mesh/SubMesh p.submeshOBJ->vertexData->vertexCount = vecVertices.size(); // Then we can create our VertexDeclaration Ogre::VertexDeclaration* decl = p.submeshOBJ->vertexData->vertexDeclaration; // define the vertex format VertexDeclaration* vertexDecl = p.submeshOBJ->vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); // allocate the vertex buffer HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), p.submeshOBJ->vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false); VertexBufferBinding* binding = p.submeshOBJ->vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, // You can use several different value types here vecIndices.size(), // The number of indices you'll put in that buffer Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE // Properties ); unsigned short* pIndices = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD)); // Create new Scene Node if (p.node == NULL) { p.node = mKeyDevices.mSceneMgr->getRootSceneNode()->createChildSceneNode(p.position); } // Print debug info to gui windows showDebugStats(p); // Begin writing to manualObject unsigned int uLodLevel = 0; for(int v = 0; v < vecVertices.size(); v++) { PolyVox::PositionMaterialNormal vertex = vecVertices[v]; const PolyVox::Vector3DFloat& v3dVertexPos = vertex.getPosition(); *pVertex++ = v3dVertexPos.getX(); *pVertex++ = v3dVertexPos.getY(); *pVertex++ = v3dVertexPos.getZ(); } for(int index = 0; index < vecIndices.size(); index++) { *pIndices++ = vecIndices.at(index); } vBuf->unlock(); ibuf->unlock(); /// Set parameters of the submesh p.submeshOBJ->indexData->indexBuffer = ibuf; p.submeshOBJ->indexData->indexCount = vecIndices.size(); p.submeshOBJ->indexData->indexStart = 0; /// Set bounding information (for culling) AxisAlignedBox aabox = AxisAlignedBox(0, 0, 0, divisor, divisor, divisor); p.meshOBJ->_setBounds(aabox); p.meshOBJ->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0); /// Notify -Mesh object that it has been loaded if(p.mMeshAttached == false) p.meshOBJ->load(); p.entity = mKeyDevices.mSceneMgr->createEntity("CustomMesh"+ Ogre::StringConverter::toString(p.position / divisor)); p.entity->setMaterialName("Worldcraft/Greengrass"); p.node->attachObject(p.entity); if (p.mMeshAttached == false) p.mMeshAttached = true; return true; } return false; }
|
Author: | drwbns [ Sat Jun 09, 2012 2:38 pm ] |
Post subject: | Re: Polyvox to Ogre Mesh |
Video showing some meshes not showing all sides. I wanted to add that it seems that this usually occurs when the face that's missing is exactly on a mesh region seam. My PolyMesh regions are split by 32 x 32 x 32 voxels. http://www.youtube.com/watch?v=sclXcaDl2-4&feature=youtu.be This could be a Polyvox problem, but to me it seems as though the missing verts and faces were never sent to the buffer somehow. Which seems wrong considering they are the face of the region / mesh. |
Author: | David Williams [ Sat Jun 09, 2012 6:05 pm ] |
Post subject: | Re: Polyvox to Ogre Mesh |
I notice you're not actually using the normal... so can you try the CubicSurfaceExtractor rather than the CubicSurfaceExtractorWithNormals? Does the problem still occur? There are/were some issues with the 'WithNormals' version but I forget the details. Also (at least with the CubicSurfaceExtractor) the descision whether to create a quad can depend on voxels outside of the region you are extracting. Imagine you have a solid voxel on the edge of your region, and the next voxel (just outside your region) is also solid. In this case no quad should be generated between the two voxels because they are both solid. I'm not sure if this is the situation you are facing though. |
Author: | drwbns [ Sun Jun 10, 2012 2:32 am ] |
Post subject: | Re: Polyvox to Ogre Mesh |
I tried it and the results are pretty much the same. It's much more noticable and reoccuring if I try to fill a large area filling in multiple regions |
Author: | David Williams [ Sun Jun 10, 2012 6:49 am ] |
Post subject: | Re: Polyvox to Ogre Mesh |
When you modify a particular voxel, which regions do you then regenerate the mesh for? I'm guessing you are only regenerating the mesh for the region which contains the voxel you modified? Actually, if the voxel lies on the edge of a region then you need to update the neighbouring region's mesh as well. Does that make sense? |
Author: | drwbns [ Mon Jun 11, 2012 5:17 am ] |
Post subject: | Re: Polyvox to Ogre Mesh |
I'm only updating neighboring regions if I'm adding multiple voxels using a radius value - because I could be modifying voxels in neighboring regions. Yes, it makes sense, but why would I update a neighboring region for a single voxel? |
Page 1 of 4 | All times are UTC |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |