diff --git a/CMakeLists.txt b/CMakeLists.txt index f333e937..774030e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ SET(SRC_FILES source/MaterialMapManager.cpp source/MaterialMapSerializer.cpp source/PolyVoxSceneManager.cpp + source/Surface.cpp source/Volume.cpp source/VolumeIterator.cpp source/VolumeManager.cpp @@ -24,6 +25,7 @@ SET(INC_FILES include/MaterialMapManager.h include/MaterialMapSerializer.h include/PolyVoxSceneManager.h + include/Surface.h include/Triangle.h include/TypeDef.h include/Vertex.h diff --git a/include/PolyVoxSceneManager.h b/include/PolyVoxSceneManager.h index e4f6839f..e36a0932 100644 --- a/include/PolyVoxSceneManager.h +++ b/include/PolyVoxSceneManager.h @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "Constants.h" #include "MaterialMap.h" +#include "Surface.h" #include "Triangle.h" #include "TypeDef.h" #include "Volume.h" @@ -95,6 +96,8 @@ namespace Ogre bool manualObjectUpToDate[OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS][OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS][OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS]; bool regionIsHomogenous[OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS][OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS][OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS]; + std::map m_mapSurfaces[OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS][OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS][OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS]; + void igniteVoxel(UIntVector3 voxelToIgnite); private: @@ -115,6 +118,8 @@ namespace Ogre std::queue m_queueVoxelsToBurn; + bool m_bHaveGeneratedMeshes; + //std::string m_aMaterialNames[256]; }; } diff --git a/include/Surface.h b/include/Surface.h new file mode 100644 index 00000000..7cb04f30 --- /dev/null +++ b/include/Surface.h @@ -0,0 +1,30 @@ +#ifndef __SURFACE_H__ +#define __SURFACE_H__ + +#include "Ogre.h" +#include + +#include "Triangle.h" +#include "Vertex.h" + +namespace Ogre +{ + class Surface : public SimpleRenderable + { + public: + Surface(); + Surface(const String& material); + ~Surface(void); + + void setGeometry(std::vector verticesToSet, std::vector indicesToSet); + + Real getSquaredViewDepth(const Camera *cam) const; + Real getBoundingRadius(void) const; + protected: + //void getWorldTransforms(Matrix4 *xform) const; + const Quaternion &getWorldOrientation(void) const; + const Vector3 &getWorldPosition(void) const; + }; +} + +#endif /* __SURFACE_H__ */ \ No newline at end of file diff --git a/include/Triangle.h b/include/Triangle.h new file mode 100644 index 00000000..9a95dff5 --- /dev/null +++ b/include/Triangle.h @@ -0,0 +1,54 @@ +/****************************************************************************** +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 __Triangle_H__ +#define __Triangle_H__ + +#include "OgrePrerequisites.h" + +#include "OgreVector3.h" + +namespace Ogre +{ + class Triangle + { + public: + + //FIXME - maybe these should be short? + ulong v0; + ulong v1; + ulong v2; + + Triangle() + :v0(0) + ,v1(0) + ,v2(0) + { + } + + Triangle(uint v0ToSet, uint v1ToSet, uint v2ToSet) + :v0(v0ToSet) + ,v1(v1ToSet) + ,v2(v2ToSet) + { + } + }; +} + +#endif diff --git a/source/PolyVoxSceneManager.cpp b/source/PolyVoxSceneManager.cpp index f53653a3..93eeb3ff 100644 --- a/source/PolyVoxSceneManager.cpp +++ b/source/PolyVoxSceneManager.cpp @@ -68,6 +68,7 @@ namespace Ogre ,useNormalSmoothing(false) ,normalSmoothingFilterSize(1) ,m_normalGenerationMethod(SOBEL) + ,m_bHaveGeneratedMeshes(false) { for(uint regionZ = 0; regionZ < OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS; ++regionZ) { @@ -145,7 +146,7 @@ namespace Ogre { destroySceneNode(sceneNodes[blockX][blockY][blockZ]->getName()); //FIXME - when it's available in CVS, use destroyAllSceneNodes commented out below. } - sceneNodes[blockX][blockY][blockZ] = 0; + sceneNodes[blockX][blockY][blockZ] = getRootSceneNode()->createChildSceneNode(Vector3(blockX*OGRE_REGION_SIDE_LENGTH,blockY*OGRE_REGION_SIDE_LENGTH,blockZ*OGRE_REGION_SIDE_LENGTH));; manualObjectUpToDate[blockX][blockY][blockZ] = false; } } @@ -324,8 +325,64 @@ namespace Ogre LogManager::getSingleton().logMessage("regionZ = " + StringConverter::toString(regionZ)); for(uint regionY = 0; regionY < OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS; ++regionY) { + //LogManager::getSingleton().logMessage("regionY = " + StringConverter::toString(regionY)); for(uint regionX = 0; regionX < OGRE_VOLUME_SIDE_LENGTH_IN_REGIONS; ++regionX) { + //LogManager::getSingleton().logMessage("regionX = " + StringConverter::toString(regionX)); + if(manualObjectUpToDate[regionX][regionY][regionZ] == false) + { + std::vector vertexData; + std::vector< std::vector< Triangle> > indexData; + generateMeshDataForRegion(regionX,regionY,regionZ,vertexData,indexData); + + sceneNodes[regionX][regionY][regionZ]->detachAllObjects(); + + for(uint meshCt = 1; meshCt < 256; ++meshCt) + { + if(indexData[meshCt].size() == 0) + { + continue; + } + std::map::iterator iterSurface = m_mapSurfaces[regionX][regionY][regionZ].find(meshCt); + if(iterSurface == m_mapSurfaces[regionX][regionY][regionZ].end()) + { + //We have to create the surface + Surface* surface = new Surface(materialMap->getMaterialAtIndex(meshCt)); + + sceneNodes[regionX][regionY][regionZ]->attachObject(surface); + + m_mapSurfaces[regionX][regionY][regionZ].insert(std::make_pair(meshCt,surface)); + + surface->setGeometry(vertexData,indexData[meshCt]); + } + else + { + //We just update the existing surface + iterSurface->second->setGeometry(vertexData,indexData[meshCt]); + sceneNodes[regionX][regionY][regionZ]->attachObject(iterSurface->second); + + //sceneNodes[regionX][regionY][regionZ]->detachObject(iterSurface->second); + /*delete iterSurface->second; + m_mapSurfaces[regionX][regionY][regionZ].erase(iterSurface); + + //We have to create the surface + Surface* surface = new Surface(materialMap->getMaterialAtIndex(meshCt)); + + //sceneNodes[regionX][regionY][regionZ] = getRootSceneNode()->createChildSceneNode(Vector3(regionX*OGRE_REGION_SIDE_LENGTH,regionY*OGRE_REGION_SIDE_LENGTH,regionZ*OGRE_REGION_SIDE_LENGTH)); + sceneNodes[regionX][regionY][regionZ]->attachObject(surface); + + m_mapSurfaces[regionX][regionY][regionZ].insert(std::make_pair(meshCt,surface)); + + surface->setGeometry(vertexData,indexData[meshCt]);*/ + } + } + manualObjectUpToDate[regionX][regionY][regionZ] = true; + } + + //m_bHaveGeneratedMeshes = true; + +#ifdef USE_MAN_OBJS + if(manualObjectUpToDate[regionX][regionY][regionZ] == false) { /*for(uint materialCt2 = 0; materialCt2 < MAX_NO_OF_MATERIAL_BOUNDARIES_PER_REGION; ++materialCt2) @@ -444,8 +501,9 @@ namespace Ogre //++materialCt; } } +#endif - manualObjectUpToDate[regionX][regionY][regionZ] = true; + //manualObjectUpToDate[regionX][regionY][regionZ] = true; } } } @@ -792,6 +850,7 @@ namespace Ogre material = std::max(material,v111); //vertexScaled values are always integers and so can be used as indices. + //FIXME - these integer values can just be obtained by using floor()? long int index; unsigned int vertexScaledX; unsigned int vertexScaledY; diff --git a/source/Surface.cpp b/source/Surface.cpp new file mode 100644 index 00000000..8ab2366f --- /dev/null +++ b/source/Surface.cpp @@ -0,0 +1,173 @@ +#include "Surface.h" + +#include "OgreVertexIndexData.h" + +namespace Ogre +{ + + Surface::Surface() + { + mRenderOp.vertexData = NULL; + mRenderOp.indexData = NULL; + + this->setMaterial("BaseWhiteNoLighting"); + } + + Surface::Surface(const String& material) + { + mRenderOp.vertexData = NULL; + mRenderOp.indexData = NULL; + + this->setMaterial(material); + } + + Surface::~Surface(void) + { + delete mRenderOp.vertexData; + delete mRenderOp.indexData; + } + + void Surface::setGeometry(std::vector verticesToSet, std::vector indicesToSet) + { + if(mRenderOp.vertexData) + { + delete mRenderOp.vertexData; + mRenderOp.vertexData = NULL; + } + + if(mRenderOp.indexData) + { + delete mRenderOp.indexData; + mRenderOp.indexData = NULL; + } + + mRenderOp.vertexData = new VertexData(); + mRenderOp.indexData = new IndexData(); + //LogManager::getSingleton().logMessage("In setGeometry()"); + // Initialization stuff + mRenderOp.vertexData->vertexCount = verticesToSet.size(); + mRenderOp.vertexData->vertexStart = 0; + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; // OT_LINE_LIST, OT_LINE_STRIP + mRenderOp.useIndexes = true; + mRenderOp.indexData->indexStart = 0; + mRenderOp.indexData->indexCount = indicesToSet.size()*3; + + //LogManager::getSingleton().logMessage("Finished initialisaing stuff"); + + VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; + VertexBufferBinding *bind = mRenderOp.vertexData->vertexBufferBinding; + + //FIXME - this should be moved to constructor? + //LogManager::getSingleton().logMessage("Creating Vertex Declaration"); + decl->removeAllElements(); + decl->addElement(0, 0, VET_FLOAT3, VES_POSITION); + decl->addElement(0, 3 * sizeof(float), VET_FLOAT3, VES_NORMAL); + + //LogManager::getSingleton().logMessage("Creating Vertex Buffer"); + HardwareVertexBufferSharedPtr vbuf = + HardwareBufferManager::getSingleton().createVertexBuffer( + decl->getVertexSize(0), + mRenderOp.vertexData->vertexCount, + HardwareBuffer::HBU_STATIC_WRITE_ONLY); + + bind->setBinding(0, vbuf); + + //LogManager::getSingleton().logMessage("Creating Index Buffer"); + HardwareIndexBufferSharedPtr ibuf = + HardwareBufferManager::getSingleton().createIndexBuffer( + HardwareIndexBuffer::IT_16BIT, // type of index + mRenderOp.indexData->indexCount * 3, // number of indexes + HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage + false); // no shadow buffer + + mRenderOp.indexData->indexBuffer = ibuf; + + + // Drawing stuff + int size = verticesToSet.size(); + Vector3 vaabMin = verticesToSet[0].position; + Vector3 vaabMax = verticesToSet[0].position; + + //LogManager::getSingleton().logMessage("Setting Vertex Data of size " + StringConverter::toString(size)); + + Real *prPos = static_cast(vbuf->lock(HardwareBuffer::HBL_DISCARD)); + + for(int i = 0; i < size; i++) + { + *prPos++ = verticesToSet[i].position.x; + *prPos++ = verticesToSet[i].position.y; + *prPos++ = verticesToSet[i].position.z; + + *prPos++ = verticesToSet[i].normal.x; + *prPos++ = verticesToSet[i].normal.y; + *prPos++ = verticesToSet[i].normal.z; + + if(verticesToSet[i].position.x < vaabMin.x) + vaabMin.x = verticesToSet[i].position.x; + if(verticesToSet[i].position.y < vaabMin.y) + vaabMin.y = verticesToSet[i].position.y; + if(verticesToSet[i].position.z < vaabMin.z) + vaabMin.z = verticesToSet[i].position.z; + + if(verticesToSet[i].position.x > vaabMax.x) + vaabMax.x = verticesToSet[i].position.x; + if(verticesToSet[i].position.y > vaabMax.y) + vaabMax.y = verticesToSet[i].position.y; + if(verticesToSet[i].position.z > vaabMax.z) + vaabMax.z = verticesToSet[i].position.z; + } + + vbuf->unlock(); + + mBox.setExtents(vaabMin, vaabMax); + + //LogManager::getSingleton().logMessage("Setting Index Data of size " + StringConverter::toString(indicesToSet.size())); + + unsigned short* pIdx = static_cast(ibuf->lock(HardwareBuffer::HBL_DISCARD)); + for(int i = 0; i < indicesToSet.size(); i++) + { + *pIdx = indicesToSet[i].v0; + pIdx++; + *pIdx = indicesToSet[i].v1; + pIdx++; + *pIdx = indicesToSet[i].v2; + pIdx++; + } + ibuf->unlock(); + + + } + + Real Surface::getSquaredViewDepth(const Camera *cam) const + { + Vector3 vMin, vMax, vMid, vDist; + vMin = mBox.getMinimum(); + vMax = mBox.getMaximum(); + vMid = ((vMin - vMax) * 0.5) + vMin; + vDist = cam->getDerivedPosition() - vMid; + + return vDist.squaredLength(); + } + + Real Surface::getBoundingRadius(void) const + { + return Math::Sqrt((std::max)(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength())); + //return mRadius; + } + /* + void Line3D::getWorldTransforms(Matrix4 *xform) const + { + // return identity matrix to prevent parent transforms + *xform = Matrix4::IDENTITY; + } + */ + const Quaternion &Surface::getWorldOrientation(void) const + { + return Quaternion::IDENTITY; + } + + const Vector3 &Surface::getWorldPosition(void) const + { + return Vector3::ZERO; + } +} \ No newline at end of file