コード例 #1
0
void RenderTerrainNode::updateVertexBuffer( RenderVertexBuffer* posbuf,const Rect& rect )
{
	ph_assert (rect.left >= m_offsetX && rect.right <= m_boundaryX && 
		rect.top >= m_offsetY && rect.bottom <= m_boundaryY);

	resetBounds(rect);

	long destOffsetX = rect.left <= m_offsetX ? 0 : (rect.left - m_offsetX);
	long destOffsetY = rect.top	 <= m_offsetY ? 0 : (rect.top  - m_offsetY);

	scalar uvScale = 1.0f / (m_terrain->getSize() - 1);
	const float* pBaseHeight = m_terrain->getHeightData(rect.left, rect.top);
	uint16 rowskip = m_terrain->getSize();
	uint16 destPosRowSkip = 0, destDeltaRowSkip = 0;
	unsigned char* pRootPosBuf	= 0;
	unsigned char* pRowPosBuf	= 0;

	if (posbuf)
	{
		destPosRowSkip	= m_terrain->getBatchSize() * posbuf->getVertexSize();
		pRootPosBuf		= static_cast<unsigned char*>(posbuf->lock());
		pRowPosBuf		= pRootPosBuf;
		pRowPosBuf		+= destOffsetY * destPosRowSkip + destOffsetX * posbuf->getVertexSize();
	}

	Vector3 pos;
	bool vcompress = m_terrain->getUseVertexCompression();

	for (long y = rect.top; y < rect.bottom; y ++)
	{
		const float* pHeight = pBaseHeight;
		float* pPosBuf = static_cast<float*>(static_cast<void*>(pRowPosBuf));
		for (long x = rect.left; x < rect.right; x ++)
		{
			if (pPosBuf)
			{
				m_terrain->getPoint(x, y, *pHeight, &pos);

				mergeIntoBounds(x, y, pos);
				//pos -= m_localCentre;

				writePosVertex(vcompress, (uint16)x, (uint16)y, *pHeight, pos, uvScale, &pPosBuf);
				pHeight ++;
			}
		}
		pBaseHeight += rowskip;
		if (pRowPosBuf)
		{
			pRowPosBuf += destPosRowSkip;
		}
	}

	if (posbuf)
	{
		posbuf->unlock();
	}
}
コード例 #2
0
	//----------------------------------------------------------------------
	void TerrainQuadTreeNode::updateVertexBuffer(const Rect& rect)
	{
		_AST (rect.left >= mOffsetX && rect.right <= mBoundaryX && 
			rect.top >= mOffsetY && rect.bottom <= mBoundaryY);

		// potentially reset our bounds depending on coverage of the update
		resetBounds(rect);

		// Main data
		uint16 inc = (mTerrain->getSize()-1) / (mVertexDataRecord->resolution-1);
		long destOffsetX = rect.left <= mOffsetX ? 0 : (rect.left - mOffsetX) / inc;
		long destOffsetY = rect.top <= mOffsetY ? 0 : (rect.top - mOffsetY) / inc;

		// Fill the buffers
		float uvScale = 1.0f / (mTerrain->getSize() - 1);
		const float* pBaseHeight = mTerrain->getHeightData(rect.left, rect.top);
		const float* pBaseDelta = mTerrain->getDeltaData(rect.left, rect.top);
		uint16 rowskip = mTerrain->getSize() * inc;
		uint16 destPosRowSkip = 0, destDeltaRowSkip = 0;
		unsigned char* pRootPosBuf = 0;
		unsigned char* pRootDeltaBuf = 0;
		unsigned char* pRowPosBuf = 0;
		unsigned char* pRowDeltaBuf = 0;
		const uint32 nVertSizePos = sizeof(uint16) * 2 + sizeof(float);
		const uint32 nVertSizeDelta = sizeof(float) * 2;

		if (mVertexDataRecord->cpuVertexPosData)
		{
			destPosRowSkip = mVertexDataRecord->size * nVertSizePos;
			pRootPosBuf = static_cast<unsigned char*>(mVertexDataRecord->cpuVertexPosData);
			pRowPosBuf = pRootPosBuf;
			// skip dest buffer in by left/top
			pRowPosBuf += destOffsetY * destPosRowSkip + destOffsetX * nVertSizePos;
		}
		if (mVertexDataRecord->cpuVertexDeltaData)
		{
			destDeltaRowSkip = mVertexDataRecord->size * nVertSizeDelta;
			pRootDeltaBuf = static_cast<unsigned char*>(mVertexDataRecord->cpuVertexDeltaData);
			pRowDeltaBuf = pRootDeltaBuf;
			// skip dest buffer in by left/top
			pRowDeltaBuf += destOffsetY * destDeltaRowSkip + destOffsetX * nVertSizeDelta;
		}
		VEC3 pos;
		
		for (uint16 y = rect.top; y < rect.bottom; y += inc)
		{
			const float* pHeight = pBaseHeight;
			const float* pDelta = pBaseDelta;
			float* pPosBuf = static_cast<float*>(static_cast<void*>(pRowPosBuf));
			float* pDeltaBuf = static_cast<float*>(static_cast<void*>(pRowDeltaBuf));
			for (uint16 x = rect.left; x < rect.right; x += inc)
			{
				if (pPosBuf)
				{
					mTerrain->getPoint(x, y, *pHeight, &pos);

					// Update bounds *before* making relative
					mergeIntoBounds(x, y, pos);
					// relative to local centre
					pos -= mLocalCentre;
			
					writePosVertex(x, y, *pHeight, pos, uvScale, &pPosBuf);
					pHeight += inc;
					

				}

				if (pDeltaBuf)
				{
					// delta, and delta LOD threshold
					// we want delta to apply to LODs no higher than this value
					// at runtime this will be combined with a per-renderable parameter
					// to ensure we only apply morph to the correct LOD
					writeDeltaVertex(x, y, *pDelta, 
						(float)mTerrain->getLODLevelWhenVertexEliminated(x, y) - 1.0f, 
						&pDeltaBuf);
					pDelta += inc;

				}

				
			}
			pBaseHeight += rowskip;
			pBaseDelta += rowskip;
			if (pRowPosBuf)
				pRowPosBuf += destPosRowSkip;
			if (pRowDeltaBuf)
				pRowDeltaBuf += destDeltaRowSkip;

		}

		// Skirts now
		// skirt spacing based on top-level resolution (* inc to cope with resolution which is not the max)
		uint16 skirtSpacing = mVertexDataRecord->skirtRowColSkip * inc;
		VEC3 skirtOffset;
		mTerrain->getVector(0, 0, -mTerrain->getSkirtSize(), &skirtOffset);

		// skirt rows
		// clamp rows to skirt spacing (round up)
		long skirtStartX = rect.left;
		long skirtStartY = rect.top;
		// for rows, clamp Y to skirt frequency, X to inc (LOD resolution vs top)
		if (skirtStartY % skirtSpacing)
			skirtStartY += skirtSpacing - (skirtStartY % skirtSpacing);
		if (skirtStartX % inc)
			skirtStartX += inc - (skirtStartX % inc);
		skirtStartY = std::max(skirtStartY, (long)mOffsetY);
		pBaseHeight = mTerrain->getHeightData(skirtStartX, skirtStartY);

		if (mVertexDataRecord->cpuVertexPosData)
		{
			// position dest buffer just after the main vertex data
			pRowPosBuf = pRootPosBuf + nVertSizePos * mVertexDataRecord->size * mVertexDataRecord->size;
			// move it onwards to skip the skirts we don't need to update
			pRowPosBuf += destPosRowSkip * ((skirtStartY - mOffsetY) / skirtSpacing);
			pRowPosBuf += nVertSizePos * (skirtStartX - mOffsetX) / inc;
		}
		if (mVertexDataRecord->cpuVertexDeltaData)
		{
			// position dest buffer just after the main vertex data
			pRowDeltaBuf = pRootDeltaBuf + nVertSizeDelta * mVertexDataRecord->size * mVertexDataRecord->size;
			// move it onwards to skip the skirts we don't need to update
			pRowDeltaBuf += destDeltaRowSkip * (skirtStartY - mOffsetY) / skirtSpacing;
			pRowDeltaBuf += nVertSizeDelta * (skirtStartX - mOffsetX) / inc;
		}
		for (uint16 y = skirtStartY; y < rect.bottom; y += skirtSpacing)
		{
			const float* pHeight = pBaseHeight;
			float* pPosBuf = static_cast<float*>(static_cast<void*>(pRowPosBuf));
			float* pDeltaBuf = static_cast<float*>(static_cast<void*>(pRowDeltaBuf));
			for (uint16 x = skirtStartX; x < rect.right; x += inc)
			{
				if (mVertexDataRecord->cpuVertexPosData)
				{
					mTerrain->getPoint(x, y, *pHeight, &pos);
					// relative to local centre
					pos -= mLocalCentre;
					pos += skirtOffset;
					writePosVertex(x, y, *pHeight - mTerrain->getSkirtSize(), pos, uvScale, &pPosBuf);

					pHeight += inc;

					

				}

				if (mVertexDataRecord->cpuVertexDeltaData)
				{
					// delta (none)
					// delta threshold (irrelevant)
					writeDeltaVertex(x, y, 0, 99, &pDeltaBuf);
				}
			}
			pBaseHeight += mTerrain->getSize() * skirtSpacing;
			if (pRowPosBuf)
				pRowPosBuf += destPosRowSkip;
			if (pRowDeltaBuf)
				pRowDeltaBuf += destDeltaRowSkip;
		}

		// skirt cols
		// clamp cols to skirt spacing (round up)
		skirtStartX = rect.left;
		if (skirtStartX % skirtSpacing)
			skirtStartX += skirtSpacing - (skirtStartX % skirtSpacing);
		// clamp Y to inc (LOD resolution vs top)
		skirtStartY = rect.top;
		if (skirtStartY % inc)
			skirtStartY += inc - (skirtStartY % inc);
		skirtStartX = std::max(skirtStartX, (long)mOffsetX);

		if (mVertexDataRecord->cpuVertexPosData)
		{
			// position dest buffer just after the main vertex data and skirt rows
			pRowPosBuf = pRootPosBuf + nVertSizePos * mVertexDataRecord->size * mVertexDataRecord->size;
			// skip the row skirts
			pRowPosBuf += mVertexDataRecord->numSkirtRowsCols * mVertexDataRecord->size * nVertSizePos;
			// move it onwards to skip the skirts we don't need to update
			pRowPosBuf += destPosRowSkip * (skirtStartX - mOffsetX) / skirtSpacing;
			pRowPosBuf += nVertSizePos * (skirtStartY - mOffsetY) / inc;
		}
		if (mVertexDataRecord->cpuVertexDeltaData)
		{
			// Delta dest buffer just after the main vertex data and skirt rows
			pRowDeltaBuf = pRootDeltaBuf + nVertSizeDelta * mVertexDataRecord->size * mVertexDataRecord->size;
			// skip the row skirts
			pRowDeltaBuf += mVertexDataRecord->numSkirtRowsCols * mVertexDataRecord->size * nVertSizeDelta;
			// move it onwards to skip the skirts we don't need to update
			pRowDeltaBuf += destDeltaRowSkip * (skirtStartX - mOffsetX) / skirtSpacing;
			pRowDeltaBuf += nVertSizeDelta * (skirtStartY - mOffsetY) / inc;
		}
		
		for (uint16 x = skirtStartX; x < rect.right; x += skirtSpacing)
		{
			float* pPosBuf = static_cast<float*>(static_cast<void*>(pRowPosBuf));
			float* pDeltaBuf = static_cast<float*>(static_cast<void*>(pRowDeltaBuf));
			for (uint16 y = skirtStartY; y < rect.bottom; y += inc)
			{
				if (mVertexDataRecord->cpuVertexPosData)
				{
					float height = mTerrain->getHeightAtPoint(x, y);
					mTerrain->getPoint(x, y, height, &pos);
					// relative to local centre
					pos -= mLocalCentre;
					pos += skirtOffset;
					
					writePosVertex(x, y, height - mTerrain->getSkirtSize(), pos, uvScale, &pPosBuf);

				}
				if (mVertexDataRecord->cpuVertexDeltaData)
				{
					// delta (none)
					// delta threshold (irrelevant)
					writeDeltaVertex(x, y, 0, 99, &pDeltaBuf);
				}
			}
			if (pRowPosBuf)
				pRowPosBuf += destPosRowSkip;
			if (pRowDeltaBuf)
				pRowDeltaBuf += destDeltaRowSkip;
		}
	}