Commits

Xiangquan Xiao committed c727caf

gsoc12-terrain: Remove AutoUpdateLod from Terrain

Comments (0)

Files changed (9)

Components/Terrain/include/OgreTerrain.h

 #include "OgreTerrainMaterialGenerator.h"
 #include "OgreTerrainLayerBlendMap.h"
 #include "OgreWorkQueue.h"
-#include "OgreTerrainAutoUpdateLod.h"
 #include "OgreTerrainLodManager.h"
 
 namespace Ogre
 		static const uint16 TERRAINLAYERINSTANCE_CHUNK_VERSION;
 		static const uint32 TERRAINDERIVEDDATA_CHUNK_ID;
 		static const uint16 TERRAINDERIVEDDATA_CHUNK_VERSION;
-		static const uint32 TERRAINHEIGHTDATA_CHUNK_ID;
-		static const uint16 TERRAINHEIGHTDATA_CHUNK_VERSION;
+		static const uint32 TERRAINGENERALINFO_CHUNK_ID;
+		static const uint16 TERRAINGENERALINFO_CHUNK_VERSION;
 
 		static const size_t LOD_MORPH_CUSTOM_PARAM;
 
 
 		void freeCPUResources();
 		void freeGPUResources();
+		inline void freeLodData();
 		void determineLodLevels();
 		void distributeVertexData();
 		void updateBaseScale();
 
 		bool mIsPrepared;	/// Is Terrain prepared?
 		TerrainLodManager* mLodManager;
-		TerrainAutoUpdateLod* mAutoUpdateLod;
 
 	public:
 		/** Read separated geometry data from file into allocated memory
 		int getHighestLodLoaded() { return (mLodManager) ? mLodManager->mHighestLodLoaded : -1; };
 		int getTargetLodLevel() { return (mLodManager) ? mLodManager->mTargetLodLevel : -1; };
 //------------------------
-		// automatic LOD update
-		void setAutoUpdateLod(TerrainAutoUpdateLod* autoUpdate) { mAutoUpdateLod = autoUpdate; }
-		const TerrainAutoUpdateLod* getAutoUpdateLod() const { return mAutoUpdateLod; }
-		void autoUpdateLod(bool synchronous, const Any &data);
-
 		class _OgreTerrainExport TextureAllocator : public TerrainAlloc
 		{
 		public:

Components/Terrain/include/OgreTerrainGroup.h

 #include "OgreTerrain.h"
 #include "OgreWorkQueue.h"
 #include "OgreIteratorWrappers.h"
+#include "OgreTerrainAutoUpdateLod.h"
 
 namespace Ogre
 {

Components/Terrain/include/OgreTerrainLodManager.h

 	class _OgreTerrainExport TerrainLodManager : public WorkQueue::RequestHandler, public WorkQueue::ResponseHandler
 	{
 	public:
+		static const uint32 TERRAINLODDATA_CHUNK_ID;
+		static const uint16 TERRAINLODDATA_CHUNK_VERSION;
+
+		struct LoadLodRequest
+		{
+			uint16 lodLevel;
+			bool readDone;
+			bool synchronous;
+			_OgreTerrainExport friend std::ostream& operator<<(std::ostream& o, const LoadLodRequest& r)
+			{ return o; }
+		};
+
+	public:
         TerrainLodManager(Terrain* t, const String& filename);
         ~TerrainLodManager();
 
 			    0: 01 03 05 06 07 08 09 11 13 15 16 17 18 19 21 23
 		  */
 		float* separateData(float* data);
-		/** Write already separated geometry data into stream
-		  @param data A geometry data to save
-		  @param stream Stream to write into
-		  @remarks Each LOD level has its own Chunk of data for easy read later.
-			Each chunk's payload is compressed using deflate() as well.
-		  */
-		void writeGeometryData(float* data, StreamSerialiser& stream);
-		/** Read separated geometry data from file into allocated memory
-		  @param filename A file to read from
-		  @param lodLevel Which LOD level to load
-		  @returns Allocated array containing geometry data of given LOD level
-		  @remarks Geometry data are uncompressed using inflate() and stored into
-			    allocated buffer
-		  */
-		float* readGeometryData(StreamSerialiser& stream, uint lodLevel);
+
+		/// save each LOD level separately compressed so seek is possible
+		void saveLodData(StreamSerialiser& stream, float* height, float* delta);
 		/** Removes highest LOD level loaded
 		  @param onlyLast Remove LOD level only if it is lowest one in its associated vertex data range
 		  @remarks If there is LOD level load in progress it's load is canceled instead of removal of already loaded one.
 				LOD level is removed to find out if it is OK to remove whole vertex data range.
 		*/
 		bool getVertexDataRange(uint lodLevel, uint *treeStart, uint *treeEnd, uint *lastLevel = NULL);
-
+		/** Read separated geometry data from file into allocated memory
+		  @param filename A file to read from
+		  @param lodLevel Which LOD level to load
+		  @returns Allocated array containing geometry data of given LOD level
+		  @remarks Geometry data are uncompressed using inflate() and stored into
+			    allocated buffer
+		  */
+		float* readGeometryData(StreamSerialiser& stream, uint lodLevel);
+		void waitForDerivedProcesses();
+	private:
+		/** Write already separated geometry data into stream
+		  @param stream Stream to write into
+		  @param data A geometry data to save
+		  @remarks Each LOD level has its own Chunk of data for easy read later.
+			Each chunk's payload is compressed using deflate() as well.
+		  */
+		void writeGeometryData(StreamSerialiser& stream, float* data);
 	public:
-		struct LoadLodRequest
-		{
-			uint16 lodLevel;
-			bool readDone;
-			bool synchronous;
-			_OgreTerrainExport friend std::ostream& operator<<(std::ostream& o, const LoadLodRequest& r)
-			{ return o; }
-		};
-
 		int mHighestLodPrepared;  /// Highest LOD level stored in memory i.e. mHeightData/mDeltaData
 		int mHighestLodLoaded;  /// Highest LOD level loaded in GPU
 		int mTargetLodLevel;    /// Which LOD level is demanded
 		bool mIsPrepared;	/// Is Terrain prepared?
-		bool mIncreaseLodLevelInProgress;  /// Is increaseLodLevel() running?
 	private:
 		uint16 mWorkQueueChannel;
 		Terrain* terrain;
 		String datafile;
+
+		bool mIncreaseLodLevelInProgress;  /// Is increaseLodLevel() running?
 	};
 	/** @} */
 	/** @} */

Components/Terrain/include/OgreTerrainQuadTreeNode.h

 		void prepare(StreamSerialiser& stream);
 		/// Load node and children (perform GPU tasks, will be render thread)
 		void load();
+		/// Load node and children in a depth range (perform GPU tasks, will be render thread)
+		void load(uint16 depthStart, uint16 depthEnd);
 		/// Unload node and children (perform GPU tasks, will be render thread)
 		void unload();
+		/// Unload node and children in a depth range (perform GPU tasks, will be render thread)
+		void unload(uint16 depthStart, uint16 depthEnd);
 		/// Unprepare node and children (perform CPU tasks, may be background thread)
 		void unprepare();
 		/// Save node to a stream
 
 		/// Returns the internal renderable object for this node
 		Renderable *_getRenderable();
-
-		void load(uint16 treeDepthStart, uint16 treeDepthEnd);
-		void unload(uint16 treeStart, uint16 treeEnd);
-		bool isInGpu();
-		bool isInCpu();
-
 	protected:
 		Terrain* mTerrain;
 		TerrainQuadTreeNode* mParent;

Components/Terrain/src/OgreTerrain.cpp

 	//---------------------------------------------------------------------
 	const uint32 Terrain::TERRAIN_CHUNK_ID = StreamSerialiser::makeIdentifier("TERR");
 	const uint16 Terrain::TERRAIN_CHUNK_VERSION = 2;
+	const uint32 Terrain::TERRAINGENERALINFO_CHUNK_ID = StreamSerialiser::makeIdentifier("TGIN");
+	const uint16 Terrain::TERRAINGENERALINFO_CHUNK_VERSION = 1;
 	const uint32 Terrain::TERRAINLAYERDECLARATION_CHUNK_ID = StreamSerialiser::makeIdentifier("TDCL");
 	const uint16 Terrain::TERRAINLAYERDECLARATION_CHUNK_VERSION = 1;
 	const uint32 Terrain::TERRAINLAYERSAMPLER_CHUNK_ID = StreamSerialiser::makeIdentifier("TSAM");
 	const uint16 Terrain::TERRAINLAYERINSTANCE_CHUNK_VERSION = 1;
 	const uint32 Terrain::TERRAINDERIVEDDATA_CHUNK_ID = StreamSerialiser::makeIdentifier("TDDA");
 	const uint16 Terrain::TERRAINDERIVEDDATA_CHUNK_VERSION = 1;
-	const uint32 Terrain::TERRAINHEIGHTDATA_CHUNK_ID = StreamSerialiser::makeIdentifier("THDA");
-	const uint16 Terrain::TERRAINHEIGHTDATA_CHUNK_VERSION = 1;
 	// since 129^2 is the greatest power we can address in 16-bit index
 	const uint16 Terrain::TERRAIN_MAX_BATCH_SIZE = 129; 
 	const uint16 Terrain::WORKQUEUE_DERIVED_DATA_REQUEST = 1;
 		, mLastViewportHeight(0)
 		, mCustomGpuBufferAllocator(0)
 		, mIsPrepared(false)
-		, mAutoUpdateLod(0)
 		, mCustomTextureAllocator(0)
 		, mLodManager(0)
 
 		freeTemporaryResources();
 		freeGPUResources();
 		freeCPUResources();
+		freeLodData();
 		if (mSceneMgr)
 		{
 			mSceneMgr->destroySceneNode(mRootNode);
 		stream.write(&mMinBatchSize);
 		stream.write(&mPos);
 
-		// write heights
-		mLodManager->writeGeometryData(mHeightData, stream);
-		// write deltas
-		mLodManager->writeGeometryData(mDeltaData, stream);
+		mLodManager->saveLodData(stream,mHeightData,mDeltaData);
 
 		writeLayerDeclaration(mLayerDecl, stream);
 
 	//---------------------------------------------------------------------
 	bool Terrain::prepare(const String& filename)
 	{
-		if(mLodManager)
-			OGRE_DELETE mLodManager;
+		freeLodData();
 		mLodManager = OGRE_NEW TerrainLodManager( this, filename );
 
 		DataStreamPtr stream = Root::getSingleton().openFileStream(filename, 
 
 		copyGlobalOptions();
 
-		//TODO: Compatible with the Version 1
-		const StreamSerialiser::Chunk* terrain_chunk = stream.readChunkBegin(TERRAIN_CHUNK_ID, TERRAIN_CHUNK_VERSION);
-		if (!terrain_chunk)
+		if (!stream.readChunkBegin(TERRAIN_CHUNK_ID, TERRAIN_CHUNK_VERSION))
 			return false;
 
 		uint8 align;
 
 		stream.read(&mMaxBatchSize);
 		stream.read(&mMinBatchSize);
-		stream.read(&mPos);
+		stream.read(&mPos);
 		mRootNode->setPosition(mPos);
 		updateBaseScale();
 		determineLodLevels();
 		// skip height/delta data
 		for (int i = 0; i < mNumLodLevels; i++)
 		{
-			stream.readChunkBegin(TERRAINHEIGHTDATA_CHUNK_ID, TERRAINHEIGHTDATA_CHUNK_VERSION);
-			stream.readChunkEnd(TERRAINHEIGHTDATA_CHUNK_ID);
+			stream.readChunkBegin(TerrainLodManager::TERRAINLODDATA_CHUNK_ID, TerrainLodManager::TERRAINLODDATA_CHUNK_VERSION);
+			stream.readChunkEnd(TerrainLodManager::TERRAINLODDATA_CHUNK_ID);
 		}
 		for (int i = 0; i < mNumLodLevels; i++)
 		{
-			stream.readChunkBegin(TERRAINHEIGHTDATA_CHUNK_ID, TERRAINHEIGHTDATA_CHUNK_VERSION);
-			stream.readChunkEnd(TERRAINHEIGHTDATA_CHUNK_ID);
+			stream.readChunkBegin(TerrainLodManager::TERRAINLODDATA_CHUNK_ID, TerrainLodManager::TERRAINLODDATA_CHUNK_VERSION);
+			stream.readChunkEnd(TerrainLodManager::TERRAINLODDATA_CHUNK_ID);
 		}
 
 
 	{
 		freeTemporaryResources();
 		freeCPUResources();
+		freeLodData();
 
 		copyGlobalOptions();
 
 		calculateHeightDeltas(rect);
 		finaliseHeightDeltas(rect, true);
 
-		if(mLodManager)
-			mLodManager->mHighestLodPrepared = 0;
-
 		distributeVertexData();
 
 		// Imported data is treated as modified because it's not saved
 	//---------------------------------------------------------------------
 	void Terrain::waitForDerivedProcesses()
 	{
-		while (mDerivedDataUpdateInProgress || mLodManager->mIncreaseLodLevelInProgress)
+		while (mDerivedDataUpdateInProgress)
 		{
 			// we need to wait for this to finish
 			OGRE_THREAD_SLEEP(50);
 
 	}
 	//---------------------------------------------------------------------
+	void Terrain::freeLodData()
+	{
+		OGRE_DELETE mLodManager;
+		mLodManager = 0;
+	}
+	//---------------------------------------------------------------------
 	Rect Terrain::calculateHeightDeltas(const Rect& rect)
 	{
 		Rect clampedRect(rect);
 		}
 	}
 	//---------------------------------------------------------------------
-	void Terrain::autoUpdateLod(bool synchronous, const Any &data)
-	{
-		if (mAutoUpdateLod)
-			mAutoUpdateLod->autoUpdateLod(this, synchronous, data);
-	}
-	//---------------------------------------------------------------------
 	void Terrain::setTextureAllocator(TextureAllocator* alloc)
 	{
 		if (alloc != getTextureAllocator())

Components/Terrain/src/OgreTerrainAutoUpdateLod.cpp

 #include "OgreMaterialManager.h"
 #include "OgreHardwareBufferManager.h"
 #include "OgreDeflate.h"
+#include "OgreTerrainAutoUpdateLod.h"
 
 /*
 #if OGRE_COMPILER == OGRE_COMPILER_MSVC
 {
 	void TerrainAutoUpdateLodByDistance::autoUpdateLod(Terrain *terrain, bool synchronous, const Any &data)
 	{
-		autoUpdateLodByDistance(terrain, synchronous, any_cast<Real>(data));
+		if( terrain )
+			autoUpdateLodByDistance(terrain, synchronous, any_cast<Real>(data));
 	}
 
 	void TerrainAutoUpdateLodByDistance::autoUpdateLodByDistance(Terrain *terrain, bool synchronous, const Real holdDistance)

Components/Terrain/src/OgreTerrainGroup.cpp

 	void TerrainGroup::increaseLodLevel(long x, long y, bool synchronous /* = false */)
 	{
 		TerrainSlot* slot = getTerrainSlot(x, y, false);
-		if (slot)
+		if (slot && slot->instance)
 		{
 			slot->instance->increaseLodLevel(synchronous);
 		}
 	void TerrainGroup::decreaseLodLevel(long x, long y)
 	{
 		TerrainSlot* slot = getTerrainSlot(x, y, false);
-		if (slot)
+		if (slot && slot->instance)
 		{
-			// if not allocated or image imported
-			if (!slot->instance || slot->def.filename.empty())
-				return ;
-
 			slot->instance->decreaseLodLevel();
 		}
 	}
 	void TerrainGroup::setAutoUpdateLod(TerrainAutoUpdateLod* autoUpdate)
 	{
 		mAutoUpdateLod = autoUpdate;
-
-		TerrainIterator ti = getTerrainIterator();
-		while(ti.hasMoreElements())
-		{
-			ti.getNext()->instance->setAutoUpdateLod(mAutoUpdateLod);
-		}
 	}
 	//---------------------------------------------------------------------
 	void TerrainGroup::autoUpdateLod(long x, long y, bool synchronous, const Any &data)
 		TerrainSlot* slot = getTerrainSlot(x, y, synchronous);
 		if (slot)
 		{
-			if (!slot->def.filename.empty() && slot->instance)
-				slot->instance->autoUpdateLod(synchronous, data);
+			mAutoUpdateLod->autoUpdateLod(slot->instance, synchronous, data);
 		}
 	}
 	//---------------------------------------------------------------------
 		for (TerrainSlotMap::iterator i = mTerrainSlots.begin(); i != mTerrainSlots.end(); ++i)
 		{
 			TerrainSlot* slot = i->second;
-			if (!slot->def.filename.empty() && slot->instance)
-				slot->instance->autoUpdateLod(synchronous, data);
+			mAutoUpdateLod->autoUpdateLod(slot->instance, synchronous, data);
 		}
 	}
 	//---------------------------------------------------------------------
 					}
 
 				}
-				if (mAutoUpdateLod)
-					slot->instance->setAutoUpdateLod(mAutoUpdateLod);
 			}
 		}
 		else

Components/Terrain/src/OgreTerrainLodManager.cpp

 namespace Ogre
 {
 	const uint16 TerrainLodManager::WORKQUEUE_LOAD_DATA_REQUEST = 1;
+	//TODO: use "TLDA"
+	const uint32 TerrainLodManager::TERRAINLODDATA_CHUNK_ID = StreamSerialiser::makeIdentifier("THDA");
+	const uint16 TerrainLodManager::TERRAINLODDATA_CHUNK_VERSION = 1;
 
 	TerrainLodManager::TerrainLodManager(Terrain* t, const String& filename)
 		: mHighestLodPrepared(-1)
 
 	TerrainLodManager::~TerrainLodManager()
 	{
+		waitForDerivedProcesses();
 		WorkQueue* wq = Root::getSingleton().getWorkQueue();
 		wq->removeRequestHandler(mWorkQueueChannel, this);
 		wq->removeResponseHandler(mWorkQueueChannel, this);
 	}
 
 	// save each LOD level separately compressed so seek is possible
-	void TerrainLodManager::writeGeometryData(float* data, StreamSerialiser& stream)
+	void TerrainLodManager::saveLodData(StreamSerialiser& stream, float* height, float* delta)
+	{
+		// write heights
+		writeGeometryData(stream, height);
+		// write deltas
+		writeGeometryData(stream, delta);
+	}
+
+	// save each LOD level separately compressed so seek is possible
+	void TerrainLodManager::writeGeometryData(StreamSerialiser& stream, float* data)
 	{
 		uint16 numLodLevels = terrain->getNumLodLevels();
 
 			int flush = Z_NO_FLUSH;
 			uint done = 0;
 
-			stream.writeChunkBegin(Terrain::TERRAINHEIGHTDATA_CHUNK_ID, Terrain::TERRAINHEIGHTDATA_CHUNK_VERSION);
+			stream.writeChunkBegin(TERRAINLODDATA_CHUNK_ID, TERRAINLODDATA_CHUNK_VERSION);
 			do
 			{
 				zstream->next_in = ((Bytef*)(sep + offset)) + done;
 					stream.write(out, compressed);
 				} while (zstream->avail_out == 0);
 			} while (flush != Z_FINISH);
-			stream.writeChunkEnd(Terrain::TERRAINHEIGHTDATA_CHUNK_ID);
+			stream.writeChunkEnd(TERRAINLODDATA_CHUNK_ID);
 
 			assert(zstream->avail_in == 0 && "all input not read");	 // all input will be used
 			assert(ret == Z_STREAM_END && "ret not END");		// stream will be complete
 		uint32 lvlCalc = lodLevel + 1 + numLodLevels;
 		for (uint i = numLodLevels*2; i > 0 ; i--)
 		{
-			stream.readChunkBegin(Terrain::TERRAINHEIGHTDATA_CHUNK_ID, Terrain::TERRAINHEIGHTDATA_CHUNK_VERSION);
+			stream.readChunkBegin(TERRAINLODDATA_CHUNK_ID, TERRAINLODDATA_CHUNK_VERSION);
 
 			if (i != lvlCalc && i != lvlCalc-numLodLevels)
 			{
-				stream.readChunkEnd(Terrain::TERRAINHEIGHTDATA_CHUNK_ID);
+				stream.readChunkEnd(TERRAINLODDATA_CHUNK_ID);
 				continue;
 			}
 
 			zstream->avail_in = c->length;
 			zstream->next_in = (Bytef*)in;
 
-			stream.readChunkEnd(Terrain::TERRAINHEIGHTDATA_CHUNK_ID);
+			stream.readChunkEnd(TERRAINLODDATA_CHUNK_ID);
 
 			// uncompress
 			if (inflateInit(zstream) != Z_OK)
 
 		return true;
 	}
+	void TerrainLodManager::waitForDerivedProcesses()
+	{
+		while (mIncreaseLodLevelInProgress)
+		{
+			// we need to wait for this to finish
+			OGRE_THREAD_SLEEP(50);
+			Root::getSingleton().getWorkQueue()->processResponses();
+		}
+	}
 }

Components/Terrain/src/OgreTerrainQuadTreeNode.cpp

 	//---------------------------------------------------------------------
 	void TerrainQuadTreeNode::load(uint16 treeDepthStart, uint16 treeDepthEnd)
 	{
-		if (mDepth >= treeDepthStart && mDepth < treeDepthEnd)
-		{
-			createGpuVertexData();
-			createGpuIndexData();
-		}
+		if (mDepth >= treeDepthEnd)
+			return ;
 
 		if (!isLeaf())
 			for (int i = 0; i < 4; ++i)
 
 		if (mDepth >= treeDepthStart && mDepth < treeDepthEnd)
 		{
+			createGpuVertexData();
+			createGpuIndexData();
+
 			if (!mLocalNode)
 				mLocalNode = mTerrain->_getRootSceneNode()->createChildSceneNode(mLocalCentre);
 
 		//unload(0, mTerrain->mNumLodLevels - mTerrain->mNumLodLevelsPerLeafNode + 1);
 	}
 
-	void TerrainQuadTreeNode::unload(uint16 treeStart, uint16 treeEnd)
+	void TerrainQuadTreeNode::unload(uint16 treeDepthStart, uint16 treeDepthEnd)
 	{
-		if (mDepth >= treeEnd)
+		if (mDepth >= treeDepthEnd)
 			return ;
 
 		if (!isLeaf())
 			for (int i = 0; i < 4; ++i)
-				mChildren[i]->unload(treeStart, treeEnd);
+				mChildren[i]->unload(treeDepthStart, treeDepthEnd);
 
-		if (mDepth >= treeStart && mDepth < treeEnd)
+		if (mDepth >= treeDepthStart && mDepth < treeDepthEnd)
 		{
 			destroyGpuVertexData();
 
 			//    mLocalNode->detachObject(mMovable);
 		}
 	}
-
-	bool TerrainQuadTreeNode::isInGpu()
-	{
-		const VertexDataRecord *vdr = getVertexDataRecord();
-		return ( vdr!=NULL && vdr->gpuVertexData!=NULL);
-	}
-	bool TerrainQuadTreeNode::isInCpu()
-	{
-		const VertexDataRecord *vdr = getVertexDataRecord();
-		return ( vdr!=NULL && vdr->cpuVertexData!=NULL);
-	}
 	//---------------------------------------------------------------------
 	void TerrainQuadTreeNode::unprepare()
 	{