Commits

Xiangquan Xiao committed 9edc9d2

gsoc12-terrain: Make LodManager as pointer, who also hold the filename binded

Comments (0)

Files changed (7)

Components/Terrain/include/OgreTerrain.h

 		*/
 		float* getHeightData(long x, long y) const;
 
-		float getHeightAtPointInterpolated(long x, long y) const;
 		/** Get the height data for a given terrain point. 
 		@param x, y Discrete coordinates in terrain vertices, values from 0 to size-1,
 			left/right bottom/top
 		size_t getDeltaBufVertexSize() const;
 
 		bool mIsPrepared;	/// Is Terrain prepared?
-		TerrainLodManager mLodManager;
+		TerrainLodManager* mLodManager;
 		TerrainAutoUpdateLod* mAutoUpdateLod;
 
 	public:
-		/// Free mHeightData/mDeltaData.
-		void freeData();
-
 		/** Read separated geometry data from file into allocated memory
 		  @param filename A file to read from
 		  @param lodLevel Which LOD level to load
 		  @param filename File to read geometry data from
 		  @param synchronous Run synchronously
 		  */
-		void increaseLodLevel(const String& filename, bool synchronous = false);		
+		void increaseLodLevel(bool synchronous = false);
 		/// Decrease Terrain's LOD level by 1
 		void decreaseLodLevel();
-
-		int getHighestLodPrepared() { return mLodManager.mHighestLodPrepared; };
-		int getHighestLodLoaded() { return mLodManager.mHighestLodLoaded; };
-		int getTargetLodLevel() { return mLodManager.mTargetLodLevel; };
-
+//---------------for debug
+		int getHighestLodPrepared() { return (mLodManager) ? mLodManager->mHighestLodPrepared : -1; };
+		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(const String& filename, bool synchronous, const Any &data);                
+		void setAutoUpdateLod(TerrainAutoUpdateLod* autoUpdate) { mAutoUpdateLod = autoUpdate; }
+		const TerrainAutoUpdateLod* getAutoUpdateLod() const { return mAutoUpdateLod; }
+		void autoUpdateLod(bool synchronous, const Any &data);
 
 		class _OgreTerrainExport TextureAllocator : public TerrainAlloc
 		{

Components/Terrain/include/OgreTerrainAutoUpdateLod.h

 			@remarks Filename is mandatory argument as typically if user wants to increase LOD level he needs file
 				from which to read data in but it is up to user how he will use it.
 		*/
-		virtual void autoUpdateLod(Terrain *terrain, const String& filename, bool synchronous, const Any &data) = 0;
+		virtual void autoUpdateLod(Terrain *terrain, bool synchronous, const Any &data) = 0;
 	};
 
 	/** Class implementing TerrainAutoUpdateLod interface. It does LOD level increase/decrease according to camera's
 	class _OgreTerrainExport TerrainAutoUpdateLodByDistance : public TerrainAutoUpdateLod
 	{
 	public:
-		void autoUpdateLod(Terrain *terrain, const String& filename, bool synchronous, const Any &data);
+		void autoUpdateLod(Terrain *terrain, bool synchronous, const Any &data);
 
 	protected:
 		/** Modifies Terrain's LOD level according to it's distance from camera.
 			@param holdDistance How far ahead of terrain's LOD level change this LOD level should be loaded.
 		*/
-		void autoUpdateLodByDistance(Terrain *terrain, const String& filename, bool synchronous, const Real holdDistance);
+		void autoUpdateLodByDistance(Terrain *terrain, bool synchronous, const Real holdDistance);
 		/// Traverse Terrain's QuadTree and calculate what LOD level is needed.
 		int traverseTreeByDistance(TerrainQuadTreeNode *node, const Camera *cam, Real cFactor, const Real holdDistance);
 	};

Components/Terrain/include/OgreTerrainLodManager.h

 	class _OgreTerrainExport TerrainLodManager : public WorkQueue::RequestHandler, public WorkQueue::ResponseHandler
 	{
 	public:
-        TerrainLodManager(Terrain* t);
+        TerrainLodManager(Terrain* t, const String& filename);
         ~TerrainLodManager();
 
 		static const uint16 WORKQUEUE_LOAD_DATA_REQUEST;
 		  @param filename File to read geometry data from
 		  @param synchronous Run synchronously
 		  */
-    	void increaseLodLevel(const String& filename, bool synchronous = false);
+    	void increaseLodLevel(bool synchronous = false);
 
 		/** Separate geometry data by LOD level
 		@param data A geometry data to separate i.e. mHeightData/mDeltaData
 		  */
 		float* readGeometryData(StreamSerialiser& stream, uint lodLevel);
 		/** Removes highest LOD level loaded
-		  @param deleteData Delete *ALL* geometry data afterwards
 		  @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.
 		  */
-		bool removeHighestLodLevel(bool deleteData, bool onlyLast = false);
+		bool removeHighestLodLevel(bool onlyLast = false);
 		/** Create CPU vertex data for given LOD level
 		  @param lodLevel A LOD level to prepare
-		  @param deleteData Delete *ALL* geometry data afterwards
 		  */
-		bool prepareLodLevel(uint lodLevel, bool deleteData);
+		bool prepareLodLevel(uint lodLevel);
 		/** Copy geometry data from buffer to mHeightData/mDeltaData
 		  @param lodLevel A LOD level to work with
 		  @param data Buffer which holds geometry data if separated form
 	public:
 		struct LoadLodRequest
 		{
-			String filename;
 			uint16 lodLevel;
 			bool readDone;
 			bool synchronous;
 	private:
 		uint16 mWorkQueueChannel;
 		Terrain* terrain;
+		String datafile;
 	};
 	/** @} */
 	/** @} */

Components/Terrain/src/OgreTerrain.cpp

 		, mIsPrepared(false)
 		, mAutoUpdateLod(0)
 		, mCustomTextureAllocator(0)
-		, mLodManager(this)
+		, mLodManager(0)
 
 	{
 		mRootNode = sm->getRootSceneNode()->createChildSceneNode();
 		WorkQueue* wq = Root::getSingleton().getWorkQueue();
 		wq->removeRequestHandler(mWorkQueueChannel, this);
 		wq->removeResponseHandler(mWorkQueueChannel, this);	
-		mAutoUpdateLod = 0;
 
 		freeTemporaryResources();
 		freeGPUResources();
 		stream.write(&mPos);
 
 		// write heights
-		mLodManager.writeGeometryData(mHeightData, stream);
+		mLodManager->writeGeometryData(mHeightData, stream);
 		// write deltas
-		mLodManager.writeGeometryData(mDeltaData, stream);
+		mLodManager->writeGeometryData(mDeltaData, stream);
 
 		writeLayerDeclaration(mLayerDecl, stream);
 
 	//---------------------------------------------------------------------
 	bool Terrain::prepare(const String& filename)
 	{
+		if(mLodManager)
+			OGRE_DELETE mLodManager;
+		mLodManager = OGRE_NEW TerrainLodManager( this, filename );
+
 		DataStreamPtr stream = Root::getSingleton().openFileStream(filename, 
 			_getDerivedResourceGroup());
 		
 		updateBaseScale();
 		determineLodLevels();
 
+		size_t numVertices = mSize * mSize;
+		mHeightData = OGRE_ALLOC_T(float, numVertices, MEMCATEGORY_GEOMETRY);
+		mDeltaData = OGRE_ALLOC_T(float, numVertices, MEMCATEGORY_GEOMETRY);
+
 		// skip height/delta data
 		for (int i = 0; i < mNumLodLevels; i++)
 		{
 		return true;
 	}
 
-	void Terrain::freeData()
-	{
-		if (mHeightData)
-		{
-			OGRE_FREE(mHeightData, MEMCATEGORY_GEOMETRY);
-			mHeightData = NULL;
-			OGRE_FREE(mDeltaData, MEMCATEGORY_GEOMETRY);
-			mDeltaData = NULL;
-
-			mLodManager.mHighestLodPrepared = -1;
-		}
-	}
-
 	bool Terrain::loadLodLevel(uint lodLevel)
-	{
+	{
+		if(!mLodManager)
+			return false;
 		if (!mIsLoaded)
 		{
 			checkLayers(true);
 		}
 
 		uint treeStart, treeEnd;
-		mLodManager.getVertexDataRange(lodLevel, &treeStart, &treeEnd);
+		mLodManager->getVertexDataRange(lodLevel, &treeStart, &treeEnd);
 
 		mQuadTree->load(treeStart, treeEnd);
 
 
 	bool Terrain::fillLodData(uint lodLevel, float* data)
 	{
-		if (!mHeightData)
-		{
-			mHeightData = OGRE_ALLOC_T(float, mSize * mSize, MEMCATEGORY_GEOMETRY);
-			mDeltaData = OGRE_ALLOC_T(float, mSize * mSize, MEMCATEGORY_GEOMETRY);
-		}
-		mLodManager.fillLodData(lodLevel,data,mHeightData,mDeltaData);
+		if(!mLodManager)
+			return false;
+		mLodManager->fillLodData(lodLevel,data,mHeightData,mDeltaData);
 		return true;
 	}
 	//---------------------------------------------------------------------
 		calculateHeightDeltas(rect);
 		finaliseHeightDeltas(rect, true);
 
-		mLodManager.mHighestLodPrepared = 0;
+		if(mLodManager)
+			mLodManager->mHighestLodPrepared = 0;
 
 		distributeVertexData();
 
 		if (mQuadTree)
 		{
 			mQuadTree->load(0, mTreeDepth);
-			mLodManager.mHighestLodLoaded = 0;
-			//mQuadTree->load();
+			if(mLodManager)
+				mLodManager->mHighestLodLoaded = 0;
 		}
 		
 		checkLayers(true);
 		mModified = false;
 		mHeightDataModified = false;
 
-		mLodManager.mTargetLodLevel = -1;
-		mLodManager.mHighestLodLoaded = -1;
+		if(mLodManager)
+		{
+			mLodManager->mTargetLodLevel = -1;
+			mLodManager->mHighestLodLoaded = -1;
+		}
 	}
 	//---------------------------------------------------------------------
 	void Terrain::unprepare()
 	//---------------------------------------------------------------------
 	float Terrain::getHeightAtPoint(long x, long y) const
 	{
-		return getHeightAtPointInterpolated(x,y);
-
-		/*
 		// clamp
 		x = std::min(x, (long)mSize - 1L);
 		x = std::max(x, 0L);
 		y = std::min(y, (long)mSize - 1L);
 		y = std::max(y, 0L);
 
+		if(mLodManager)//need interpolation
+		{
+			if (mLodManager->mHighestLodPrepared == -1)
+			{
+				LogManager::getSingleton().stream(LML_NORMAL) << "Warning: Trying to get nonpresent geometry data: returning 0.0";
+				return 0.0;
+			}
+
+			uint skip = 1 << mLodManager->mHighestLodPrepared;
+			if (x % skip == 0 && y % skip == 0)
+				return *getHeightData(x, y);
+
+			long x1 = std::min( (x / skip) * skip         , (long)mSize - 1L );
+			long x2 = std::min( ((x + skip) / skip) * skip, (long)mSize - 1L );
+			long y1 = std::min( (y / skip) * skip         , (long)mSize - 1L );
+			long y2 = std::min( ((y + skip) / skip) * skip, (long)mSize - 1L );
+
+			float rx = (float(x % skip) / skip);
+			float ry = (float(y % skip) / skip);
+
+			return mHeightData[y1 * mSize + x1] * (1.0 - rx) * (1.0 - ry) +
+				  mHeightData[y1 * mSize + x2] * rx * (1.0 - ry) +
+				  mHeightData[y2 * mSize + x1] * (1.0 - rx) * ry +
+				  mHeightData[y2 * mSize + x2] * rx * ry;
+		}
 		return *getHeightData(x, y);
-		*/
-	}
-	//---------------------------------------------------------------------
-	float Terrain::getHeightAtPointInterpolated(long x, long y) const
-	{
-		assert(mHeightData && "Height data not allocated");
-		if (mLodManager.mHighestLodPrepared == -1)
-		{
-			LogManager::getSingleton().stream(LML_NORMAL) << "Warning: Trying to get nonpresent geometry data: returning 0.0";
-			return 0.0;
-		}
-
-		// clamp
-		x = std::min(x, (long)mSize - 1L);
-		x = std::max(x, 0L);
-		y = std::min(y, (long)mSize - 1L);
-		y = std::max(y, 0L);
-
-		uint skip = 1 << mLodManager.mHighestLodPrepared;
-		if (x % skip == 0 && y % skip == 0)
-			return mHeightData[y * mSize + x];
-
-		float rx, ry, res;
-		long x1, x2, y1, y2;
-
-		x1 = std::min( (x / skip) * skip         , (long)mSize - 1L );
-		x2 = std::min( ((x + skip) / skip) * skip, (long)mSize - 1L );
-		y1 = std::min( (y / skip) * skip         , (long)mSize - 1L );
-		y2 = std::min( ((y + skip) / skip) * skip, (long)mSize - 1L );
-
-		rx = (float(x % skip) / skip);
-		ry = (float(y % skip) / skip);
-
-		res = mHeightData[y1 * mSize + x1] * (1.0 - rx) * (1.0 - ry) +
-			  mHeightData[y1 * mSize + x2] * rx * (1.0 - ry) +
-			  mHeightData[y2 * mSize + x1] * (1.0 - rx) * ry +
-			  mHeightData[y2 * mSize + x2] * rx * ry;
-
-		return res;
-
 	}
 	//---------------------------------------------------------------------
 	void Terrain::setHeightAtPoint(long x, long y, float h)
 		y = std::min(y, (long)mSize - 1L);
 		y = std::max(y, 0L);
 
-		if (mLodManager.mHighestLodPrepared != 0)
+		if (mLodManager && mLodManager->mHighestLodPrepared != 0)
 		{
 			LogManager::getSingleton().stream() << "Warning: can't set height data if they are not fully loaded yet!";
 			return ;
 	//---------------------------------------------------------------------
 	void Terrain::waitForDerivedProcesses()
 	{
-		while (mDerivedDataUpdateInProgress || mLodManager.mIncreaseLodLevelInProgress)
+		while (mDerivedDataUpdateInProgress || mLodManager->mIncreaseLodLevelInProgress)
 		{
 			// we need to wait for this to finish
 			OGRE_THREAD_SLEEP(50);
 
 	}
 	//---------------------------------------------------------------------
-	void Terrain::increaseLodLevel(const String& filename, bool synchronous /* = false */)
+	void Terrain::increaseLodLevel(bool synchronous /* = false */)
 	{
-		if (!mIsPrepared)
-			return ;
-		mLodManager.increaseLodLevel(filename,synchronous);
+		if (!mIsPrepared || !mLodManager)
+			return ;
+		mLodManager->increaseLodLevel(synchronous);
 	}
 	//---------------------------------------------------------------------
 	void Terrain::decreaseLodLevel()
 	{
 		// if not allocated
-		if (!mIsPrepared || mLodManager.mTargetLodLevel == -1)
+		if (!mIsPrepared || !mLodManager || mLodManager->mTargetLodLevel == -1)
 			return ;
 
-		if (mLodManager.mTargetLodLevel < mNumLodLevels)
+		if (mLodManager->mTargetLodLevel < mNumLodLevels)
 		{
-			mLodManager.removeHighestLodLevel(false, true);
+			mLodManager->removeHighestLodLevel(true);
 		}
 	}
 	//---------------------------------------------------------------------
-	void Terrain::autoUpdateLod(const String& filename, bool synchronous, const Any &data)
+	void Terrain::autoUpdateLod(bool synchronous, const Any &data)
 	{
 		if (mAutoUpdateLod)
-			mAutoUpdateLod->autoUpdateLod(this, filename, synchronous, data);
+			mAutoUpdateLod->autoUpdateLod(this, synchronous, data);
 	}
 	//---------------------------------------------------------------------
 	void Terrain::setTextureAllocator(TextureAllocator* alloc)
 		stream.skip(sizeof(mMaxBatchSize));
 		stream.skip(sizeof(mMinBatchSize));
 		stream.skip(sizeof(mPos));
-		float *out = mLodManager.readGeometryData(stream,lodLevel);
+		float *out = mLodManager->readGeometryData(stream,lodLevel);
 		stream.readChunkEnd(TERRAIN_CHUNK_ID);
 
 		return out;

Components/Terrain/src/OgreTerrainAutoUpdateLod.cpp

 
 namespace Ogre
 {
-	void TerrainAutoUpdateLodByDistance::autoUpdateLod(Terrain *terrain, const String& filename, bool synchronous, const Any &data)
+	void TerrainAutoUpdateLodByDistance::autoUpdateLod(Terrain *terrain, bool synchronous, const Any &data)
 	{
-		autoUpdateLodByDistance(terrain, filename, synchronous, any_cast<Real>(data));
+		autoUpdateLodByDistance(terrain, synchronous, any_cast<Real>(data));
 	}
 
-	void TerrainAutoUpdateLodByDistance::autoUpdateLodByDistance(Terrain *terrain, const String& filename, bool synchronous, const Real holdDistance)
+	void TerrainAutoUpdateLodByDistance::autoUpdateLodByDistance(Terrain *terrain, bool synchronous, const Real holdDistance)
 	{
 		// calculate error terms
 		const Viewport* vp = terrain->getSceneManager()->getCurrentViewport();
 
 		int maxLod;
 		if (!terrain->getQuadTree())
-			terrain->increaseLodLevel(filename, synchronous);
+			terrain->increaseLodLevel(synchronous);
 		else {
 			maxLod = traverseTreeByDistance(terrain->getQuadTree(), cam, cFactor, holdDistance);
 			if (maxLod == -1)
 			{
 				for (int i = lodHighest - 1; i >= maxLod; i--) // load
 				{
-					terrain->increaseLodLevel(filename, synchronous);
+					terrain->increaseLodLevel(synchronous);
 				}
 			}
 		}

Components/Terrain/src/OgreTerrainGroup.cpp

 		TerrainSlot* slot = getTerrainSlot(x, y, false);
 		if (slot)
 		{
-			slot->instance->increaseLodLevel(slot->def.filename, synchronous);
+			slot->instance->increaseLodLevel(synchronous);
 		}
 	}
 	void TerrainGroup::decreaseLodLevel(long x, long y)
 		if (slot)
 		{
 			if (!slot->def.filename.empty() && slot->instance)
-				slot->instance->autoUpdateLod(slot->def.filename, synchronous, data);
+				slot->instance->autoUpdateLod(synchronous, data);
 		}
 	}
 	//---------------------------------------------------------------------
 		{
 			TerrainSlot* slot = i->second;
 			if (!slot->def.filename.empty() && slot->instance)
-				slot->instance->autoUpdateLod(slot->def.filename, synchronous, data);
+				slot->instance->autoUpdateLod(synchronous, data);
 		}
 	}
 	//---------------------------------------------------------------------
 				}
 				else
 				{
-					terrain->increaseLodLevel(slot->def.filename, true);
+					terrain->increaseLodLevel(true);
 				}
 
 				// do final load now we've prepared in the background

Components/Terrain/src/OgreTerrainLodManager.cpp

 {
 	const uint16 TerrainLodManager::WORKQUEUE_LOAD_DATA_REQUEST = 1;
 
-	TerrainLodManager::TerrainLodManager(Terrain* t)
+	TerrainLodManager::TerrainLodManager(Terrain* t, const String& filename)
 		: mHighestLodPrepared(-1)
 		, mHighestLodLoaded(-1)
 		, mTargetLodLevel(-1)
 		, mIncreaseLodLevelInProgress(false)
 		, terrain(t)
+		, datafile(filename)
 	{
 		WorkQueue* wq = Root::getSingleton().getWorkQueue();
 		mWorkQueueChannel = wq->getChannel("Ogre/TerrainLodManager");
 		{
 			if (!lreq.readDone)
 				// read data from file into temporary height & delta buffer
-				mTempGeometryData = terrain->readGeometryData(lreq.filename, lreq.lodLevel);
+				mTempGeometryData = terrain->readGeometryData(datafile, lreq.lodLevel);
 			else
 				// create CPU vertex data
-				prepareLodLevel(lreq.lodLevel, false);
+				prepareLodLevel(lreq.lodLevel);
 
 			if (mTempGeometryData)
 				response = OGRE_NEW WorkQueue::Response(req, true, Any(mTempGeometryData));
 		return ret;
 	}
 	//---------------------------------------------------------------------
-	void TerrainLodManager::increaseLodLevel(const String& filename, bool synchronous /* = false */)
+	void TerrainLodManager::increaseLodLevel(bool synchronous /* = false */)
 	{
 		if ( mHighestLodLoaded == 0 || mTargetLodLevel == 0)
 			return ;
 
 			LoadLodRequest req;
 			req.lodLevel = mTargetLodLevel;
-			req.filename = filename;
 			req.synchronous = synchronous;
 			req.readDone = false;
 
 		return true;
 	}
 
-	bool TerrainLodManager::removeHighestLodLevel(bool deleteData, bool onlyLast /* = false */)
+	bool TerrainLodManager::removeHighestLodLevel(bool onlyLast /* = false */)
 	{
 		uint treeStart, treeEnd, lastLevel;
 		uint lodLevel = mTargetLodLevel;
 
-		if (deleteData)
-			terrain->freeData();
-
 		// TODO: remove all higher LODs as well? holes could start appearing
 
 		// not finished loading yet so just cancel load
 
 		return false;
 	}
-	bool TerrainLodManager::prepareLodLevel(uint lodLevel, bool deleteData)
+	bool TerrainLodManager::prepareLodLevel(uint lodLevel)
 	{
 		uint16 depth = terrain->getTreeDepth();
 		uint16 prevdepth = depth;
 				terrain->getQuadTree()->assignVertexData(0, 1, bakedresolution, bakedresolution);
 		}
 
-		if (deleteData)
-			terrain->freeData();
-
 		return true;
 	}
 }