diff --git a/include/PolyVoxSceneManager.h b/include/PolyVoxSceneManager.h index 7597b84c..2cf292e1 100644 --- a/include/PolyVoxSceneManager.h +++ b/include/PolyVoxSceneManager.h @@ -35,13 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. namespace Ogre { - enum NormalGenerationMethod - { - SIMPLE, - CENTRAL_DIFFERENCE, - SOBEL - }; - /// Factory for default scene manager class VOXEL_SCENE_MANAGER_API PolyVoxSceneManagerFactory : public SceneManagerFactory { diff --git a/include/SurfacePatch.h b/include/SurfacePatch.h index 778c8e62..e58a7eb0 100644 --- a/include/SurfacePatch.h +++ b/include/SurfacePatch.h @@ -7,8 +7,18 @@ #include "SurfaceVertex.h" #include "SurfaceTriangle.h" +#include "VolumeIterator.h" + + namespace Ogre { + enum NormalGenerationMethod + { + SIMPLE, + CENTRAL_DIFFERENCE, + SOBEL + }; + class SurfacePatch { public: @@ -22,12 +32,14 @@ namespace Ogre void getVertexAndIndexData(std::vector& vertexData, std::vector& indexData); + void computeNormalsFromVolume(uint regionX, uint regionY, uint regionZ, VolumeIterator volIter); + private: std::set m_setVertices; std::list m_listTriangles; - std::vector m_vecVertexData; - std::vector m_vecIndexData; + //std::vector m_vecVertexData; + //std::vector m_vecIndexData; uint m_uTrianglesAdded; uint m_uVerticesAdded; diff --git a/include/VolumeIterator.h b/include/VolumeIterator.h new file mode 100644 index 00000000..fd63d390 --- /dev/null +++ b/include/VolumeIterator.h @@ -0,0 +1,133 @@ +/****************************************************************************** +This file is part of a voxel plugin for OGRE +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#ifndef __VolumeIterator_H__ +#define __VolumeIterator_H__ + +#include "OgrePrerequisites.h" +#include "OgreSharedPtr.h" + +#include "Typedef.h" + +namespace Ogre +{ + class Volume; + + class VOXEL_SCENE_MANAGER_API VolumeIterator + { + public: + VolumeIterator(Volume& volume); + ~VolumeIterator(); + + void setVoxel(uchar value); + uchar getVoxel(void); + + uchar getVoxelAt(const uint xPosition, const uint yPosition, const uint zPosition) const; + void setVoxelAt(const uint xPosition, const uint yPosition, const uint zPosition, const uchar value); + + float getAveragedVoxelAt(const uint xPosition, const uint yPosition, const uint zPosition, uint size) const; + + //FIXME - this shouldn't return float vector + Vector3 getCentralDifferenceGradient(void) const; + Vector3 getAveragedCentralDifferenceGradient(void) const; + Vector3 getSobelGradient(void) const; + + uint getPosX(void); + uint getPosY(void); + uint getPosZ(void); + + void setPosition(uint xPos, uint yPos, uint zPos); + void setValidRegion(uint xFirst, uint yFirst, uint zFirst, uint xLast, uint yLast, uint zLast); + void moveForwardInRegion(void); + + bool isValidForRegion(void); + + uchar peekVoxel1nx1ny1nz(void) const; + uchar peekVoxel1nx1ny0pz(void) const; + uchar peekVoxel1nx1ny1pz(void) const; + uchar peekVoxel1nx0py1nz(void) const; + uchar peekVoxel1nx0py0pz(void) const; + uchar peekVoxel1nx0py1pz(void) const; + uchar peekVoxel1nx1py1nz(void) const; + uchar peekVoxel1nx1py0pz(void) const; + uchar peekVoxel1nx1py1pz(void) const; + + uchar peekVoxel0px1ny1nz(void) const; + uchar peekVoxel0px1ny0pz(void) const; + uchar peekVoxel0px1ny1pz(void) const; + uchar peekVoxel0px0py1nz(void) const; + uchar peekVoxel0px0py0pz(void) const; + uchar peekVoxel0px0py1pz(void) const; + uchar peekVoxel0px1py1nz(void) const; + uchar peekVoxel0px1py0pz(void) const; + uchar peekVoxel0px1py1pz(void) const; + + uchar peekVoxel1px1ny1nz(void) const; + uchar peekVoxel1px1ny0pz(void) const; + uchar peekVoxel1px1ny1pz(void) const; + uchar peekVoxel1px0py1nz(void) const; + uchar peekVoxel1px0py0pz(void) const; + uchar peekVoxel1px0py1pz(void) const; + uchar peekVoxel1px1py1nz(void) const; + uchar peekVoxel1px1py0pz(void) const; + uchar peekVoxel1px1py1pz(void) const; + + private: + //The current volume + Volume& mVolume; + + //The current position in the volume + uint mXPosInVolume; + uint mYPosInVolume; + uint mZPosInVolume; + + //The position of the current block + uint mXBlock; + uint mYBlock; + uint mZBlock; + + //The offset into the current block + uint mXPosInBlock; + uint mYPosInBlock; + uint mZPosInBlock; + + //Other current position information + uchar* mCurrentVoxel; + //SharedPtr mCurrentBlock; + ulong mBlockIndexInVolume; + ulong mVoxelIndexInBlock; + + uint mXRegionFirst; + uint mYRegionFirst; + uint mZRegionFirst; + uint mXRegionLast; + uint mYRegionLast; + uint mZRegionLast; + + uint mXRegionFirstBlock; + uint mYRegionFirstBlock; + uint mZRegionFirstBlock; + uint mXRegionLastBlock; + uint mYRegionLastBlock; + uint mZRegionLastBlock; + + bool mIsValidForRegion; + }; +} + +#endif diff --git a/source/PolyVoxSceneManager.cpp b/source/PolyVoxSceneManager.cpp index 2c48065b..3a372189 100644 --- a/source/PolyVoxSceneManager.cpp +++ b/source/PolyVoxSceneManager.cpp @@ -772,21 +772,24 @@ namespace Ogre surfaceVertex0.alpha = 1.0; else surfaceVertex0.alpha = 0.0; - surfaceVertex0.normal = Vector3(1.0,1.0,1.0); + //surfaceVertex0.normal = Vector3(1.0,1.0,1.0); + surfaceVertex0.normal = Vector3(0.0,0.0,0.0); SurfaceVertex surfaceVertex1(vertex1); if(material1 == material) surfaceVertex1.alpha = 1.0; else surfaceVertex1.alpha = 0.0; - surfaceVertex1.normal = Vector3(1.0,1.0,1.0); + //surfaceVertex1.normal = Vector3(1.0,1.0,1.0); + surfaceVertex1.normal = Vector3(0.0,0.0,0.0); SurfaceVertex surfaceVertex2(vertex2); if(material2 == material) surfaceVertex2.alpha = 1.0; else surfaceVertex2.alpha = 0.0; - surfaceVertex2.normal = Vector3(1.0,1.0,1.0); + //surfaceVertex2.normal = Vector3(1.0,1.0,1.0); + surfaceVertex2.normal = Vector3(0.0,0.0,0.0); result[material].addTriangle(surfaceVertex0, surfaceVertex1, surfaceVertex2); @@ -1002,6 +1005,7 @@ namespace Ogre for(std::map::iterator iterPatch = result.begin(); iterPatch != result.end(); ++iterPatch) { + iterPatch->second.computeNormalsFromVolume(regionX,regionY,regionZ,volIter); iterPatch->second.endDefinition(); } diff --git a/source/SurfacePatch.cpp b/source/SurfacePatch.cpp index d09d7b99..a080bae9 100644 --- a/source/SurfacePatch.cpp +++ b/source/SurfacePatch.cpp @@ -18,7 +18,7 @@ namespace Ogre vertexIndices = 0; - beginDefinition(); //FIXME - we shouldn't really be calling this from the constructor. + //beginDefinition(); //FIXME - we shouldn't really be calling this from the constructor. } SurfacePatch::~SurfacePatch() @@ -27,8 +27,6 @@ namespace Ogre void SurfacePatch::beginDefinition(void) { - vertexIndices = new long int [(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)]; - memset(vertexIndices,0xFF,sizeof(long int)*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)); //0xFF is -1 as two's complement - this may not be portable... } void SurfacePatch::endDefinition(void) @@ -37,85 +35,113 @@ namespace Ogre //LogManager::getSingleton().logMessage("No of triangles present = " + StringConverter::toString(m_listTriangles.size())); //LogManager::getSingleton().logMessage("No of vertices added = " + StringConverter::toString(m_uVerticesAdded)); //LogManager::getSingleton().logMessage("No of vertices present = " + StringConverter::toString(m_setVertices.size())); - - delete vertexIndices; - vertexIndices = 0; } void SurfacePatch::addTriangle(const SurfaceVertex& v0,const SurfaceVertex& v1,const SurfaceVertex& v2) { m_uTrianglesAdded++; - m_uVerticesAdded += 3; - - /*m_vecVertexData.push_back(v0); - m_vecIndexData.push_back(m_vecVertexData.size()-1); - m_vecVertexData.push_back(v1); - m_vecIndexData.push_back(m_vecVertexData.size()-1); - m_vecVertexData.push_back(v2); - m_vecIndexData.push_back(m_vecVertexData.size()-1);*/ - - /*long int index; - //If a vertex has not yet been added, it's index is -1 - index = vertexIndices[(v0.position.x*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v0.position.y*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v0.position.z)]; - if((index == -1)) - { - //Add the vertex - m_vecVertexData.push_back(v0); - vertexIndices[(v0.position.x*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v0.position.y*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v0.position.z)] = m_vecVertexData.size()-1; - m_vecIndexData.push_back(m_vecVertexData.size()-1); - } - else - { - //Just reuse the existing vertex - m_vecIndexData.push_back(index); - } - - //If a vertex has not yet been added, it's index is -1 - index = vertexIndices[(v1.position.x*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v1.position.y*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v1.position.z)]; - if((index == -1)) - { - //Add the vertex - m_vecVertexData.push_back(v1); - vertexIndices[(v1.position.x*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v1.position.y*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v1.position.z)] = m_vecVertexData.size()-1; - m_vecIndexData.push_back(m_vecVertexData.size()-1); - } - else - { - //Just reuse the existing vertex - m_vecIndexData.push_back(index); - } - - //If a vertex has not yet been added, it's index is -1 - index = vertexIndices[(v2.position.x*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v2.position.y*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v2.position.z)]; - if((index == -1)) - { - //Add the vertex - m_vecVertexData.push_back(v2); - vertexIndices[(v2.position.x*(OGRE_REGION_SIDE_LENGTH*2+1)*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v2.position.y*(OGRE_REGION_SIDE_LENGTH*2+1)) + (v2.position.z)] = m_vecVertexData.size()-1; - m_vecIndexData.push_back(m_vecVertexData.size()-1); - } - else - { - //Just reuse the existing vertex - m_vecIndexData.push_back(index); - }*/ + m_uVerticesAdded += 3; SurfaceTriangle triangle; triangle.v0 = m_setVertices.insert(v0).first; triangle.v1 = m_setVertices.insert(v1).first; - triangle.v2 = m_setVertices.insert(v2).first; - - /*triangle.v0 = std::find(m_setVertices.begin(), m_setVertices.end(), v0); - triangle.v1 = std::find(m_setVertices.begin(), m_setVertices.end(), v1); - triangle.v2 = std::find(m_setVertices.begin(), m_setVertices.end(), v2); */ + triangle.v2 = m_setVertices.insert(v2).first; m_listTriangles.push_back(triangle); - /*triangle.v0->listTrianglesUsingThisVertex.push_back(m_listTriangles.end()); + triangle.v0->listTrianglesUsingThisVertex.push_back(m_listTriangles.end()); triangle.v1->listTrianglesUsingThisVertex.push_back(m_listTriangles.end()); - triangle.v2->listTrianglesUsingThisVertex.push_back(m_listTriangles.end());*/ + triangle.v2->listTrianglesUsingThisVertex.push_back(m_listTriangles.end()); + } + + void SurfacePatch::computeNormalsFromVolume(uint regionX, uint regionY, uint regionZ, VolumeIterator volIter) + { + //LogManager::getSingleton().logMessage("In SurfacePatch::computeNormalsFromVolume"); + for(std::set::iterator vertexIter = m_setVertices.begin(); vertexIter != m_setVertices.end(); ++vertexIter) + { + //LogManager::getSingleton().logMessage("In Loop"); + const float posX = vertexIter->position.x/2.0f + static_cast(regionX * OGRE_REGION_SIDE_LENGTH); + const float posY = vertexIter->position.y/2.0f + static_cast(regionY * OGRE_REGION_SIDE_LENGTH); + const float posZ = vertexIter->position.z/2.0f + static_cast(regionZ * OGRE_REGION_SIDE_LENGTH); + + const uint floorX = static_cast(vertexIter->position.x/2.0f) + regionX * OGRE_REGION_SIDE_LENGTH; + const uint floorY = static_cast(vertexIter->position.y/2.0f) + regionY * OGRE_REGION_SIDE_LENGTH; + const uint floorZ = static_cast(vertexIter->position.z/2.0f) + regionZ * OGRE_REGION_SIDE_LENGTH; + + NormalGenerationMethod normalGenerationMethod = CENTRAL_DIFFERENCE; + + switch(normalGenerationMethod) + { + case SIMPLE: + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); + const uchar uFloor = volIter.getVoxel() > 0 ? 1 : 0; + if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 + { + uchar uCeil = volIter.peekVoxel1px0py0pz() > 0 ? 1 : 0; + vertexIter->normal = Vector3(uFloor - uCeil,0.0,0.0); + } + else if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 + { + uchar uCeil = volIter.peekVoxel0px1py0pz() > 0 ? 1 : 0; + vertexIter->normal = Vector3(0.0,uFloor - uCeil,0.0); + } + else if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 + { + uchar uCeil = volIter.peekVoxel0px0py1pz() > 0 ? 1 : 0; + vertexIter->normal = Vector3(0.0, 0.0,uFloor - uCeil); + } + vertexIter->normal.normalise(); + break; + } + case CENTRAL_DIFFERENCE: + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); + const Vector3 gradFloor = volIter.getCentralDifferenceGradient(); + if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX+1.0),static_cast(posY),static_cast(posZ)); + } + if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY+1.0),static_cast(posZ)); + } + if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ+1.0)); + } + const Vector3 gradCeil = volIter.getCentralDifferenceGradient(); + vertexIter->normal = gradFloor + gradCeil; + vertexIter->normal *= -1; + vertexIter->normal.normalise(); + break; + } + case SOBEL: + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); + const Vector3 gradFloor = volIter.getSobelGradient(); + if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX+1.0),static_cast(posY),static_cast(posZ)); + } + if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY+1.0),static_cast(posZ)); + } + if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ+1.0)); + } + const Vector3 gradCeil = volIter.getSobelGradient(); + vertexIter->normal = gradFloor + gradCeil; + vertexIter->normal *= -1; + vertexIter->normal.normalise(); + break; + } + } + } } void SurfacePatch::getVertexAndIndexData(std::vector& vertexData, std::vector& indexData) @@ -123,87 +149,21 @@ namespace Ogre vertexData.clear(); indexData.clear(); - /*vertexData = m_vecVertexData; - indexData = m_vecIndexData;*/ - - //return; - vertexData.resize(m_setVertices.size()); std::copy(m_setVertices.begin(), m_setVertices.end(), vertexData.begin()); - //sort(vertexData.begin(),vertexData.end()); - //reverse(vertexData.begin(),vertexData.end()); - - //LogManager::getSingleton().logMessage("No of triangles = " + StringConverter::toString(m_listTriangles.size())); - for(std::list::iterator iterTriangles = m_listTriangles.begin(); iterTriangles != m_listTriangles.end(); ++iterTriangles) { - /*vertexData.push_back(*(iterTriangles->v0)); - indexData.push_back(vertexData.size()-1); - vertexData.push_back(*(iterTriangles->v1)); - indexData.push_back(vertexData.size()-1); - vertexData.push_back(*(iterTriangles->v2)); - indexData.push_back(vertexData.size()-1); */ + std::vector::iterator iterVertex; - /*std::set::iterator iterVertex = m_setVertices.find((*(iterTriangles->v0))); - indexData.push_back(iterVertex - m_setVertices.begin()); - iterVertex = m_setVertices.find((*(iterTriangles->v1))); - indexData.push_back(iterVertex - m_setVertices.begin()); - iterVertex = m_setVertices.find((*(iterTriangles->v2))); - indexData.push_back(iterVertex - m_setVertices.begin());*/ - - /*for(uint ct = 0; ct < vertexData.size(); ++ct) - { - if(vertexData[ct] == (*(iterTriangles->v0))) - { - indexData.push_back(ct); - break; - } - }*/ - - std::vector::iterator iterVertex = lower_bound(vertexData.begin(), vertexData.end(),(*(iterTriangles->v0))); - if(iterVertex == vertexData.end()) - { - LogManager::getSingleton().logMessage("Vertex 0 Not Found"); - } + iterVertex = lower_bound(vertexData.begin(), vertexData.end(),(*(iterTriangles->v0))); indexData.push_back(iterVertex - vertexData.begin()); iterVertex = lower_bound(vertexData.begin(), vertexData.end(),(*(iterTriangles->v1))); - if(iterVertex == vertexData.end()) - { - LogManager::getSingleton().logMessage("Vertex 1 Not Found"); - } indexData.push_back(iterVertex - vertexData.begin()); iterVertex = lower_bound(vertexData.begin(), vertexData.end(),(*(iterTriangles->v2))); - if(iterVertex == vertexData.end()) - { - LogManager::getSingleton().logMessage("Vertex 2 Not Found"); - } - indexData.push_back(iterVertex - vertexData.begin()); - - /*for(uint ct = 0; ct < vertexData.size(); ++ct) - { - if(vertexData[ct] == (*(iterTriangles->v1))) - { - indexData.push_back(ct); - break; - } - } - - for(uint ct = 0; ct < vertexData.size(); ++ct) - { - if(vertexData[ct] == (*(iterTriangles->v2))) - { - indexData.push_back(ct); - break; - } - }*/ + indexData.push_back(iterVertex - vertexData.begin()); } - //LogManager::getSingleton().logMessage("Out of Loop"); - - /*vertexData = m_vecVertexData; - indexData = m_vecIndexData;*/ - } }