diff --git a/CMakeLists.txt b/CMakeLists.txt index 94e8814f..435bab62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ SET(SRC_FILES source/Volume.cpp source/VolumeIterator.cpp source/VolumeManager.cpp + source/VolumeResource.cpp source/VolumeSerializer.cpp ) @@ -34,6 +35,7 @@ SET(INC_FILES include/Volume.h include/VolumeIterator.h include/VolumeManager.h + include/VolumeResource.h include/VolumeSerializer.h ) diff --git a/include/PolyVoxSceneManager.h b/include/PolyVoxSceneManager.h index 39b2940b..fb9520e8 100644 --- a/include/PolyVoxSceneManager.h +++ b/include/PolyVoxSceneManager.h @@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "Volume.h" #include "SurfaceVertex.h" #include "RegionGeometry.h" +#include "VolumeResource.h" #include @@ -100,7 +101,8 @@ namespace Ogre NormalGenerationMethod m_normalGenerationMethod; - VolumePtr volumeData; + VolumeResourcePtr volumeResource; + Volume* volumeData; bool m_bHaveGeneratedMeshes; diff --git a/include/Volume.h b/include/Volume.h new file mode 100644 index 00000000..ba9bb00f --- /dev/null +++ b/include/Volume.h @@ -0,0 +1,68 @@ +/****************************************************************************** +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 __Volume_H__ +#define __Volume_H__ + +#include "OgrePrerequisites.h" +#include "OgreSharedPtr.h" + +#include "Block.h" +#include "Constants.h" +#include "TypeDef.h" +#include "IntegralVector3.h" + +#include + +namespace Ogre +{ + class VOXEL_SCENE_MANAGER_API Volume + { + //Make VolumeIterator a friend + friend class VolumeIterator; + friend class VolumeResource; + + //Volume interface + public: + Volume(); + Volume(const Volume& rhs); + ~Volume(); + + Volume& operator=(const Volume& rhs); + + //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); + + bool containsPoint(Vector3 pos, float boundary); + bool containsPoint(IntVector3 pos, uint boundary); + + bool loadFromFile(const std::string& sFilename); + bool saveToFile(const std::string& sFilename); + + void regionGrow(uint xStart, uint yStart, uint zStart, uchar value); + void tidy(void); + + private: + static SharedPtr mHomogeneousBlocks[256]; + SharedPtr mBlocks[OGRE_NO_OF_BLOCKS_IN_VOLUME]; + }; + + VOXEL_SCENE_MANAGER_API Volume createDilatedCopy(Volume& volInput, uchar value); +} + +#endif diff --git a/include/VolumeManager.h b/include/VolumeManager.h index 5ed1f1c4..96bc09ea 100644 --- a/include/VolumeManager.h +++ b/include/VolumeManager.h @@ -2,7 +2,7 @@ #define __VOLUMEMANAGER_H__ #include -#include "Volume.h" +#include "VolumeResource.h" namespace Ogre { @@ -20,7 +20,7 @@ namespace Ogre VolumeManager (); virtual ~VolumeManager (); - virtual VolumePtr load (const Ogre::String &name, const Ogre::String &group); + virtual VolumeResourcePtr load (const Ogre::String &name, const Ogre::String &group); static VolumeManager &getSingleton (); static VolumeManager *getSingletonPtr (); diff --git a/include/VolumeResource.h b/include/VolumeResource.h new file mode 100644 index 00000000..9989a4e5 --- /dev/null +++ b/include/VolumeResource.h @@ -0,0 +1,92 @@ +/****************************************************************************** +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 __VolumeResource_H__ +#define __VolumeResource_H__ + +#include "OgrePrerequisites.h" +#include "OgreSharedPtr.h" + +#include "Block.h" +#include "Constants.h" +#include "TypeDef.h" +#include "IntegralVector3.h" +#include "Volume.h" + +#include + +namespace Ogre +{ + class VOXEL_SCENE_MANAGER_API VolumeResource : public Ogre::Resource + { + public: + VolumeResource (Ogre::ResourceManager *creator, const Ogre::String &name, + Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual = false, + Ogre::ManualResourceLoader *loader = 0); + ~VolumeResource(); + + Volume* volume; + + protected: + + // must implement these from the Ogre::Resource interface + void loadImpl (); + void unloadImpl (); + size_t calculateSize () const; + }; + + class VolumeResourcePtr : public Ogre::SharedPtr + { + public: + VolumeResourcePtr () : Ogre::SharedPtr () {} + explicit VolumeResourcePtr (VolumeResource *rep) : Ogre::SharedPtr (rep) {} + VolumeResourcePtr (const VolumeResourcePtr &r) : Ogre::SharedPtr (r) {} + VolumeResourcePtr (const Ogre::ResourcePtr &r) : Ogre::SharedPtr () + { + // lock & copy other mutex pointer + OGRE_LOCK_MUTEX (*r.OGRE_AUTO_MUTEX_NAME) + OGRE_COPY_AUTO_SHARED_MUTEX (r.OGRE_AUTO_MUTEX_NAME) + pRep = static_cast (r.getPointer ()); + pUseCount = r.useCountPointer (); + if (pUseCount) + { + ++ (*pUseCount); + } + } + + /// Operator used to convert a ResourcePtr to a VolumeResourcePtr + VolumeResourcePtr& operator=(const Ogre::ResourcePtr& r) + { + if (pRep == static_cast (r.getPointer ())) + return *this; + release (); + // lock & copy other mutex pointer + OGRE_LOCK_MUTEX (*r.OGRE_AUTO_MUTEX_NAME) + OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) + pRep = static_cast (r.getPointer()); + pUseCount = r.useCountPointer (); + if (pUseCount) + { + ++ (*pUseCount); + } + return *this; + } + }; +} + +#endif diff --git a/source/PolyVoxSceneManager.cpp b/source/PolyVoxSceneManager.cpp index ff6f31e6..76172e5b 100644 --- a/source/PolyVoxSceneManager.cpp +++ b/source/PolyVoxSceneManager.cpp @@ -37,7 +37,8 @@ namespace Ogre // PolyVoxSceneManager ////////////////////////////////////////////////////////////////////////// PolyVoxSceneManager::PolyVoxSceneManager() - :volumeData(0) + :volumeResource(0) + ,volumeData(0) ,useNormalSmoothing(false) ,normalSmoothingFilterSize(1) ,m_normalGenerationMethod(SOBEL) @@ -52,14 +53,16 @@ namespace Ogre bool PolyVoxSceneManager::loadScene(const String& filename) { - volumeData = VolumeManager::getSingletonPtr()->load(filename + ".volume", "General"); - if(volumeData.isNull()) + volumeResource = VolumeManager::getSingletonPtr()->load(filename + ".volume", "General"); + if(volumeResource.isNull()) { LogManager::getSingleton().logMessage("Generating default volume"); generateLevelVolume(); LogManager::getSingleton().logMessage("Done generating default volume"); } + volumeData = volumeResource->volume; + volumeData->tidy(); @@ -177,7 +180,8 @@ namespace Ogre void PolyVoxSceneManager::generateLevelVolume(void) { - volumeData = VolumePtr(new Volume); + //volumeData = VolumePtr(new Volume); + volumeData = new Volume(); VolumeIterator volIter(*volumeData); for(uint z = 0; z < OGRE_VOLUME_SIDE_LENGTH; ++z) { diff --git a/source/Volume.cpp b/source/Volume.cpp new file mode 100644 index 00000000..032dd290 --- /dev/null +++ b/source/Volume.cpp @@ -0,0 +1,394 @@ +/****************************************************************************** +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. +******************************************************************************/ + +#include "IntegralVector3.h" +#include "Volume.h" +#include "VolumeIterator.h" + +#include "VolumeSerializer.h" + +#include "OgreVector3.h" +#include "OgreLogManager.h" +#include "OgreStringConverter.h" + +#include //FIXME - remove this... + +namespace Ogre +{ + SharedPtr Volume::mHomogeneousBlocks[256]; + + Volume::Volume() + { + //FIXME - Add checking... + SharedPtr& homogeneousBlock = mHomogeneousBlocks[0]; + if(homogeneousBlock.isNull()) + { + homogeneousBlock = SharedPtr(new Block); + homogeneousBlock->fillWithValue(0); + } + + for(uint i = 0; i < OGRE_NO_OF_BLOCKS_IN_VOLUME; ++i) + { + mBlocks[i] = mHomogeneousBlocks[0]; + } + } + + Volume::Volume(const Volume& rhs) + { + std::cout << "Warning - Copying Volume" << std::endl; + *this = rhs; + } + + Volume::~Volume() + { + } + + Volume& Volume::operator=(const Volume& rhs) + { + std::cout << "Warning - Assigning Volume" << std::endl; + if (this == &rhs) + { + return *this; + } + + /*for(uint i = 0; i < OGRE_NO_OF_BLOCKS_IN_VOLUME; ++i) + { + //FIXME - Add checking... + mBlocks[i] = SharedPtr(new Block); + }*/ + + for(uint i = 0; i < OGRE_NO_OF_BLOCKS_IN_VOLUME; ++i) + { + //I think this is OK... If a block is in the homogeneous array it's ref count will be greater + //than 1 as there will be the pointer in the volume and the pointer in the static homogeneous array. + if(rhs.mBlocks[i].unique()) + { + mBlocks[i] = SharedPtr(new Block(*(rhs.mBlocks[i]))); + } + else + { + //we have a block in the homogeneous array - just copy the pointer. + mBlocks[i] = rhs.mBlocks[i]; + } + } + + return *this; + } + + /*uchar Volume::getVoxelAt(const uint xPosition, const uint yPosition, const uint zPosition) const + { + const uint blockX = xPosition >> OGRE_BLOCK_SIDE_LENGTH_POWER; + const uint blockY = yPosition >> OGRE_BLOCK_SIDE_LENGTH_POWER; + const uint blockZ = zPosition >> OGRE_BLOCK_SIDE_LENGTH_POWER; + + const uint xOffset = xPosition - (blockX << OGRE_BLOCK_SIDE_LENGTH_POWER); + const uint yOffset = yPosition - (blockY << OGRE_BLOCK_SIDE_LENGTH_POWER); + const uint zOffset = zPosition - (blockZ << OGRE_BLOCK_SIDE_LENGTH_POWER); + + Block* block = mBlocks + [ + blockX + + blockY * OGRE_VOLUME_SIDE_LENGTH_IN_BLOCKS + + blockZ * OGRE_VOLUME_SIDE_LENGTH_IN_BLOCKS * OGRE_VOLUME_SIDE_LENGTH_IN_BLOCKS + ]; + + return block->getVoxelAt(xOffset,yOffset,zOffset); + }*/ + + /*void Volume::setVoxelAt(const uint xPosition, const uint yPosition, const uint zPosition, const uchar value) + { + const uint blockX = xPosition >> OGRE_BLOCK_SIDE_LENGTH_POWER; + const uint blockY = yPosition >> OGRE_BLOCK_SIDE_LENGTH_POWER; + const uint blockZ = zPosition >> OGRE_BLOCK_SIDE_LENGTH_POWER; + + const uint xOffset = xPosition - (blockX << OGRE_BLOCK_SIDE_LENGTH_POWER); + const uint yOffset = yPosition - (blockY << OGRE_BLOCK_SIDE_LENGTH_POWER); + const uint zOffset = zPosition - (blockZ << OGRE_BLOCK_SIDE_LENGTH_POWER); + + Block* block = mBlocks + [ + blockX + + blockY * OGRE_VOLUME_SIDE_LENGTH_IN_BLOCKS + + blockZ * OGRE_VOLUME_SIDE_LENGTH_IN_BLOCKS * OGRE_VOLUME_SIDE_LENGTH_IN_BLOCKS + ]; + + block->setVoxelAt(xOffset,yOffset,zOffset, value); + }*/ + + + + bool Volume::containsPoint(Vector3 pos, float boundary) + { + return (pos.x < OGRE_VOLUME_SIDE_LENGTH - 1 - boundary) + && (pos.y < OGRE_VOLUME_SIDE_LENGTH - 1 - boundary) + && (pos.z < OGRE_VOLUME_SIDE_LENGTH - 1 - boundary) + && (pos.x > boundary) + && (pos.y > boundary) + && (pos.z > boundary); + } + + bool Volume::containsPoint(IntVector3 pos, uint boundary) + { + return (pos.x < OGRE_VOLUME_SIDE_LENGTH - 1 - boundary) + && (pos.y < OGRE_VOLUME_SIDE_LENGTH - 1 - boundary) + && (pos.z < OGRE_VOLUME_SIDE_LENGTH - 1 - boundary) + && (pos.x > boundary) + && (pos.y > boundary) + && (pos.z > boundary); + } + + bool Volume::loadFromFile(const std::string& sFilename) + { + //Open the file + std::ifstream file; + file.open(sFilename.c_str(), std::ios::in | std::ios::binary); + if(!file.is_open()) + { + LogManager::getSingleton().logMessage("Failed to open volume file " + sFilename); + return false; + } + + //Read volume dimensions + uchar volumeWidth = 0; + uchar volumeHeight = 0; + uchar volumeDepth = 0; + file.read(reinterpret_cast(&volumeWidth), sizeof(volumeWidth)); + file.read(reinterpret_cast(&volumeHeight), sizeof(volumeHeight)); + file.read(reinterpret_cast(&volumeDepth), sizeof(volumeDepth)); + if(file.fail()) + { + LogManager::getSingleton().logMessage("Failed to read dimentions"); + return false; + } + + //Read data + VolumeIterator volIter(*this); + for(uint z = 0; z < OGRE_VOLUME_SIDE_LENGTH; ++z) + { + for(uint y = 0; y < OGRE_VOLUME_SIDE_LENGTH; ++y) + { + for(uint x = 0; x < OGRE_VOLUME_SIDE_LENGTH; ++x) + { + uchar value; + file.read(reinterpret_cast(&value), sizeof(value)); //FIXME - check for error here + volIter.setVoxelAt(x,y,z,value); + } + } + + //Periodically see if we can tidy the memory to avoid excessive usage during loading. + if(z%OGRE_BLOCK_SIDE_LENGTH == OGRE_BLOCK_SIDE_LENGTH-1) + { + tidy(); //FIXME - we don't actually have to tidy the whole volume here - just the part we loaded since the last call to tidy. + } + } + return true; + } + + bool Volume::saveToFile(const std::string& sFilename) + { + //Open the file + std::ofstream file; + + file.open(sFilename.c_str(), std::ios::out | std::ios::binary); + if(!file.is_open()) + { + LogManager::getSingleton().logMessage("Failed to open file for saving volume"); + return false; + } + + //Read volume dimensions + uchar volumeWidth = 0; + uchar volumeHeight = 0; + uchar volumeDepth = 0; + file.write(reinterpret_cast(&volumeWidth), sizeof(volumeWidth)); + file.write(reinterpret_cast(&volumeHeight), sizeof(volumeHeight)); + file.write(reinterpret_cast(&volumeDepth), sizeof(volumeDepth)); + if(file.fail()) + { + LogManager::getSingleton().logMessage("Failed to write dimensions"); + return false; + } + + //Write data + VolumeIterator volIter(*this); + for(uint z = 0; z < OGRE_VOLUME_SIDE_LENGTH; ++z) + { + for(uint y = 0; y < OGRE_VOLUME_SIDE_LENGTH; ++y) + { + for(uint x = 0; x < OGRE_VOLUME_SIDE_LENGTH; ++x) + { + uchar value = volIter.getVoxelAt(x,y,z); + file.write(reinterpret_cast(&value), sizeof(value)); //FIXME - check for error here + } + } + } + return true; + } + + void Volume::regionGrow(uint xStart, uint yStart, uint zStart, uchar value) + { + //FIXME - introduce integrer 'isInVolume' function + if((xStart > OGRE_VOLUME_SIDE_LENGTH-1) || (yStart > OGRE_VOLUME_SIDE_LENGTH-1) || (zStart > OGRE_VOLUME_SIDE_LENGTH-1) + || (xStart < 0) || (yStart < 0) || (zStart < 0)) + { + //FIXME - error message.. + return; + } + + VolumeIterator volIter(*this); + const uchar uSeedValue = volIter.getVoxelAt(xStart,yStart,zStart); + + if(value == uSeedValue) + { + return; //FIXME - Error message? Exception? + } + + std::queue seeds; + seeds.push(UIntVector3(xStart,yStart,zStart)); + + while(!seeds.empty()) + { + UIntVector3 currentSeed = seeds.front(); + seeds.pop(); + + //std::cout << "x = " << currentSeed.x << " y = " << currentSeed.y << " z = " << currentSeed.z << std::endl; + + //FIXME - introduce 'safe' function which tests this? + if((currentSeed.x > OGRE_VOLUME_SIDE_LENGTH-2) || (currentSeed.y > OGRE_VOLUME_SIDE_LENGTH-2) || (currentSeed.z > OGRE_VOLUME_SIDE_LENGTH-2) + || (currentSeed.x < 1) || (currentSeed.y < 1) || (currentSeed.z < 1)) + { + continue; + } + + if(volIter.getVoxelAt(currentSeed.x, currentSeed.y, currentSeed.z+1) == uSeedValue) + { + volIter.setVoxelAt(currentSeed.x, currentSeed.y, currentSeed.z+1, value); + seeds.push(UIntVector3(currentSeed.x, currentSeed.y, currentSeed.z+1)); + } + + if(volIter.getVoxelAt(currentSeed.x, currentSeed.y, currentSeed.z-1) == uSeedValue) + { + volIter.setVoxelAt(currentSeed.x, currentSeed.y, currentSeed.z-1, value); + seeds.push(UIntVector3(currentSeed.x, currentSeed.y, currentSeed.z-1)); + } + + if(volIter.getVoxelAt(currentSeed.x, currentSeed.y+1, currentSeed.z) == uSeedValue) + { + volIter.setVoxelAt(currentSeed.x, currentSeed.y+1, currentSeed.z, value); + seeds.push(UIntVector3(currentSeed.x, currentSeed.y+1, currentSeed.z)); + } + + if(volIter.getVoxelAt(currentSeed.x, currentSeed.y-1, currentSeed.z) == uSeedValue) + { + volIter.setVoxelAt(currentSeed.x, currentSeed.y-1, currentSeed.z, value); + seeds.push(UIntVector3(currentSeed.x, currentSeed.y-1, currentSeed.z)); + } + + if(volIter.getVoxelAt(currentSeed.x+1, currentSeed.y, currentSeed.z) == uSeedValue) + { + volIter.setVoxelAt(currentSeed.x+1, currentSeed.y, currentSeed.z, value); + seeds.push(UIntVector3(currentSeed.x+1, currentSeed.y, currentSeed.z)); + } + + if(volIter.getVoxelAt(currentSeed.x-1, currentSeed.y, currentSeed.z) == uSeedValue) + { + volIter.setVoxelAt(currentSeed.x-1, currentSeed.y, currentSeed.z, value); + seeds.push(UIntVector3(currentSeed.x-1, currentSeed.y, currentSeed.z)); + } + } + } + + void Volume::tidy(void) + { + //Check for homogeneous blocks + for(ulong ct = 0; ct < OGRE_NO_OF_BLOCKS_IN_VOLUME; ++ct) + { + if(mBlocks[ct]->isHomogeneous()) + { + //LogManager::getSingleton().logMessage("Got homogeneous block with value " + StringConverter::toString(mBlocks[ct]->getVoxelAt(0,0,0))); + + const uchar homogeneousValue = mBlocks[ct]->getVoxelAt(0,0,0); + SharedPtr& homogeneousBlock = mHomogeneousBlocks[homogeneousValue]; + if(homogeneousBlock.isNull()) + { + homogeneousBlock = SharedPtr(new Block); + homogeneousBlock->fillWithValue(homogeneousValue); + } + mBlocks[ct] = homogeneousBlock; + } + } + } + + Volume createDilatedCopy(Volume& volInput, uchar value) + { + Volume volResult = volInput; + + VolumeIterator iterResult(volResult); + VolumeIterator iterInput(volInput); + + //FIXME - use looping over region thing... + for(uint z = 1; z < OGRE_VOLUME_SIDE_LENGTH-1; z++) + { + //std::cout << "z = " << z << std::endl; + for(uint y = 1; y < OGRE_VOLUME_SIDE_LENGTH-1; y++) + { + for(uint x = 1; x < OGRE_VOLUME_SIDE_LENGTH-1; x++) + { + iterInput.setPosition(x,y,z); + if + ( + (iterInput.peekVoxel1nx1ny1nz() == value) || + (iterInput.peekVoxel1nx1ny0pz() == value) || + (iterInput.peekVoxel1nx1ny1pz() == value) || + (iterInput.peekVoxel1nx0py1nz() == value) || + (iterInput.peekVoxel1nx0py0pz() == value) || + (iterInput.peekVoxel1nx0py1pz() == value) || + (iterInput.peekVoxel1nx1py1nz() == value) || + (iterInput.peekVoxel1nx1py0pz() == value) || + (iterInput.peekVoxel1nx1py1pz() == value) || + + (iterInput.peekVoxel0px1ny1nz() == value) || + (iterInput.peekVoxel0px1ny0pz() == value) || + (iterInput.peekVoxel0px1ny1pz() == value) || + (iterInput.peekVoxel0px0py1nz() == value) || + //(iterInput.peekVoxel0px0py0pz() == value) || + (iterInput.peekVoxel0px0py1pz() == value) || + (iterInput.peekVoxel0px1py1nz() == value) || + (iterInput.peekVoxel0px1py0pz() == value) || + (iterInput.peekVoxel0px1py1pz() == value) || + + (iterInput.peekVoxel1px1ny1nz() == value) || + (iterInput.peekVoxel1px1ny0pz() == value) || + (iterInput.peekVoxel1px1ny1pz() == value) || + (iterInput.peekVoxel1px0py1nz() == value) || + (iterInput.peekVoxel1px0py0pz() == value) || + (iterInput.peekVoxel1px0py1pz() == value) || + (iterInput.peekVoxel1px1py1nz() == value) || + (iterInput.peekVoxel1px1py0pz() == value) || + (iterInput.peekVoxel1px1py1pz() == value) + ) + { + iterResult.setVoxelAt(x,y,z,value); + } + } + } + } + return volResult; + } +} diff --git a/source/VolumeManager.cpp b/source/VolumeManager.cpp index a5157451..453c0e3b 100644 --- a/source/VolumeManager.cpp +++ b/source/VolumeManager.cpp @@ -34,10 +34,10 @@ namespace Ogre Ogre::ResourceGroupManager::getSingleton ()._unregisterResourceManager (mResourceType); } - VolumePtr VolumeManager::load (const Ogre::String &name, const Ogre::String &group) + VolumeResourcePtr VolumeManager::load (const Ogre::String &name, const Ogre::String &group) { Ogre::LogManager::getSingleton().logMessage("DAVID - calling getByName"); - VolumePtr textf = getByName (name); + VolumeResourcePtr textf = getByName (name); Ogre::LogManager::getSingleton().logMessage("DAVID - done getByName"); if (textf.isNull ()) @@ -54,6 +54,6 @@ namespace Ogre const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, const Ogre::NameValuePairList *createParams) { - return new Volume (this, name, handle, group, isManual, loader); + return new VolumeResource (this, name, handle, group, isManual, loader); } } diff --git a/source/VolumeResource.cpp b/source/VolumeResource.cpp new file mode 100644 index 00000000..4d45183f --- /dev/null +++ b/source/VolumeResource.cpp @@ -0,0 +1,93 @@ +/****************************************************************************** +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. +******************************************************************************/ + +#include "IntegralVector3.h" +#include "VolumeResource.h" +#include "VolumeIterator.h" + +#include "VolumeSerializer.h" + +#include "OgreVector3.h" +#include "OgreLogManager.h" +#include "OgreStringConverter.h" + +#include //FIXME - remove this... + +namespace Ogre +{ + VolumeResource::VolumeResource (Ogre::ResourceManager* creator, const Ogre::String &name, + Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual, + Ogre::ManualResourceLoader *loader) : + Ogre::Resource (creator, name, handle, group, isManual, loader) + { + /* If you were storing a pointer to an object, then you would set that pointer to NULL here. + */ + + /* For consistency with StringInterface, but we don't add any parameters here + That's because the Resource implementation of StringInterface is to + list all the options that need to be set before loading, of which + we have none as such. Full details can be set through scripts. + */ + createParamDictionary ("Volume"); + + volume = new Volume(); + } + + VolumeResource::~VolumeResource() + { + unload (); + } + + // farm out to VolumeSerializer + void VolumeResource::loadImpl () + { + /* If you were storing a pointer to an object, then you would create that object with 'new' here. + */ + + VolumeSerializer serializer; + Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton ().openResource (mName, mGroup, true, this); + serializer.importVolume (stream, this->volume); + } + + void VolumeResource::unloadImpl () + { + /* If you were storing a pointer to an object, then you would check the pointer here, + and if it is not NULL, you would destruct the object and set its pointer to NULL again. + */ + + //mString.clear (); + } + + size_t VolumeResource::calculateSize () const + { + //NOTE - I don't really know what this function is for, so am therefore + //a bit vague on how to implement it. But here's my best guess... + ulong uNonHomogeneousBlocks = 0; + for(uint i = 0; i < OGRE_NO_OF_BLOCKS_IN_VOLUME; ++i) + { + //I think this is OK... If a block is in the homogeneous array it's ref count will be greater + //than 1 as there will be the pointer in the volume and the pointer in the static homogeneous array. + if(volume->mBlocks[i].unique()) + { + ++uNonHomogeneousBlocks; + } + } + return uNonHomogeneousBlocks * OGRE_NO_OF_VOXELS_IN_BLOCK; + } +}