现在的位置: 首页 > 综合 > 正文

OGRESE LOD 源码全部转自OGRESE

2013年12月02日 ⁄ 综合 ⁄ 共 4855字 ⁄ 字号 评论关闭

OGRESE没有采用四叉树管理LOD。而是计算每个地形Tile每等级lod 改变最小距离的平方 存储在了std::vector<Ogre::Real> m_LODChangeMinDistSqr;

然后根据摄像机的位置实时计算出来地形Tile的当前LOD的值。

OGRESE中对于这两个函数的注释比较少 以下是注释

//-----------------------------------------------------根据相机计算当前LOD的值
void TerrainTile::_notifyCurrentCamera(Ogre::Camera* cam)
{
	MovableObject::_notifyCurrentCamera(cam);
	if (!mVisible)//如果不可见 则返回
		return;
//
	Ogre::Vector3 cpos = cam->getDerivedPosition();//得到摄像机的位置
//
	const Ogre::AxisAlignedBox& aabb = getWorldBoundingBox(true);
	Ogre::Vector3 diff(0, 0, 0);
	Ogre::Vector3 temp1=cpos-aabb.getMaximum();
	Ogre::Vector3 temp2=cpos-aabb.getMinimum();
	diff.makeFloor(cpos - aabb.getMinimum());
	diff.makeCeil(cpos - aabb.getMaximum());
	float L = diff.squaredLength();
//
	// 找出当前lod	
	m_nLOD = m_pOwner->GetMaxLod();
	unsigned short nMaxLod = m_nLOD+1;
	for (unsigned short i = 1; i < nMaxLod; ++i)
	{
		if (m_LODChangeMinDistSqr[i] > L)//每等级lod 改变最小距离的平方 大于 L
		{
			m_nLOD = i - 1;//那么就得到了当前的LOD m_nLod  对于平整的地形 那么就会这个选择最大的LOD
			break;
		}
	}

	if (m_pOwner->GetLODMorphEnabled())
	{
		// 找出下一级lod
		unsigned short nextLevel = m_nLOD + 1;//下一集的LOD m_nLOD+1
		for (unsigned short i = nextLevel; i < nMaxLod; ++i)
		{
			if (m_LODChangeMinDistSqr[i] > m_LODChangeMinDistSqr[m_nLOD])
			{
				nextLevel = i;
				break;
			}
		}

		// 计算两个lod等级间的变形因子
		if (nextLevel == nMaxLod)
		{
			m_fLODMorphFactor = 0;
		}
		else
		{
			float range = m_LODChangeMinDistSqr[nextLevel] - m_LODChangeMinDistSqr[m_nLOD];
			float percent = (L - m_LODChangeMinDistSqr[m_nLOD]) / range;
			float rescale = 1.0f / (1.0f - m_pOwner->GetLodMorphStart());
			m_fLODMorphFactor = __max((percent - m_pOwner->GetLodMorphStart()) * rescale, 0.0f);
		}
//最近一次计算的下一级 lod m_nLastNextLOD
		if (m_nLastNextLOD != nextLevel)
		{
			if (nextLevel != nMaxLod)
			{
				m_pVertexData->vertexBufferBinding->setBinding(DELTA_BINDING, m_DeltaBuffers[nextLevel-1]);
			}
			else
			{
				// bind dummy
				m_pVertexData->vertexBufferBinding->setBinding(DELTA_BINDING, m_DeltaBuffers[0]);
			}
		}
		m_nLastNextLOD = nextLevel;
	}
}
//***************************************************************************************
// 功能:	计算每两级间的最小距离,用来作为选择当前LOD的标准
void TerrainTile::_CalculateMinLevelDist2()
{
	using namespace Ogre;

	Real CSquare = m_pOwner->m_fFactorC * m_pOwner->m_fFactorC;//基准系数

	// LOD 0 has no distance LOD0 没有距离
	m_LODChangeMinDistSqr[0] = 0.0f;//每等级lod 改变最小距离的平方
//从LOD1到LODMAX
	for (unsigned short level = 1; level <= m_pOwner->GetMaxPossibleLod(); ++level)
	{
		m_LODChangeMinDistSqr[level] = 0.0f;//每等级lod 改变最小距离的平方

		unsigned short step = 1 << level;//左移level位  下一级的step
		unsigned short higherstep = step >> 1;//step右移一位  当前这一级的step

		float* pDeltas = 0;
		// for LOD morphing, lock the according delta buffer now
		if (m_pOwner->GetLODMorphEnabled())
		{
			// indexed at LOD-1, because there are only maxLOD transitions between LODs...
			_EmptyBuffer(m_DeltaBuffers[level-1]);//硬件缓存
			pDeltas = static_cast<float*>(m_DeltaBuffers[level-1]->lock(HardwareBuffer::HBL_NORMAL));
		}

		// for every vertex that is not used in the current LOD we calculate its interpolated
		// height and compare against its actual height. the largest difference of a vertex
		// is then used to determine the minimal distance for this LOD.
		for (unsigned short j = 0; j <= m_nSize - step; j += step)//该块的大小, 2^n m_nSIze
		{
			for (unsigned short i = 0; i <= m_nSize - step; i += step)
			{
				Vector3 v1 = m_pOwner->m_pData->PixelToWorld(m_nStartX + i,		m_nStartZ + j);//	// 功能:	得到结点 xz 点的world坐标
				Vector3 v2 = m_pOwner->m_pData->PixelToWorld(m_nStartX + i + step,m_nStartZ + j);
				Vector3 v3 = m_pOwner->m_pData->PixelToWorld(m_nStartX + i,		m_nStartZ + j+ step);
				Vector3 v4 = m_pOwner->m_pData->PixelToWorld(m_nStartX + i + step,m_nStartZ + j+ step);//对应于地形tile的某个栅格的四个坐标(v1,v2,v4,v3)
				Plane t1 (v1, v3, v2);//上三角
				Plane t2 (v2, v3, v4); //下三角

				unsigned short zubound = (j == (m_nSize + 1 - step) ? step : step - 1);//z轴的界限  指的是z轴在某个step中的栅格栅格的界限[0,step-1],最后一个比较特殊
				for (unsigned short z = 0; z <= zubound; ++z)
				{
					unsigned short xubound = (i == (m_nSize + 1 - step) ? step : step - 1);//x轴的界限
					for (unsigned short x = 0; x < xubound; ++x)
					{
						unsigned short fulldetailx = i + x; //真实的栅格号码
						unsigned short fulldetailz = j + z; //真实的栅格号码
						if (fulldetailx % step == 0 && fulldetailz % step == 0)//这是由于要内插 所以不能选择边界点
						{
							continue;
						}

						Real zpct = Real(z) / Real(step);//内插的点在四边形中的z比例
						Real xpct = Real(x) / Real(step);//内插的点在四边形中的x比例

						//真实的点
						Vector3 actualPos = m_pOwner->m_pData->PixelToWorld(fulldetailx + m_nStartX, fulldetailz + m_nStartZ);
						Real interp_h;//内插高度
						if (xpct + zpct <= 1.0f)//在上三角
						{
							float temp1=t1.normal.x;
							temp1=actualPos.x;
							temp1=t1.normal.z;
							temp1=actualPos.z;
							temp1=t1.d;
							temp1=t1.normal.y;
							interp_h = (
								-(t1.normal.x * actualPos.x)
								- t1.normal.z * actualPos.z
								- t1.d) / t1.normal.y;
						}
						else
						{
							interp_h = (
								-(t2.normal.x * actualPos.x)
								- t2.normal.z * actualPos.z
								- t2.d) / t2.normal.y;
						}

						Real actual_h = actualPos.y;
						Real delta = fabs(interp_h - actual_h);

						Real D2 = delta * delta * CSquare;

						if (m_LODChangeMinDistSqr[level] < D2)
							m_LODChangeMinDistSqr[level] = D2;

						// for LOD morphing(LOD变形), store the difference in the delta buffer
						if (m_pOwner->GetLODMorphEnabled() &&
							fulldetailx != 0 && fulldetailx != m_nSize &&
							fulldetailz != 0 && fulldetailz != m_nSize)
						{
							pDeltas[fulldetailx + fulldetailz * (m_nSize + 1)] = interp_h - actual_h;
						}
					}
				}
			}
		}

		// unlock delta buffers
		if (m_pOwner->GetLODMorphEnabled())
			m_DeltaBuffers[level-1]->unlock();
	}


	// post validate
	for (unsigned short i = 1; i <= m_pOwner->GetMaxPossibleLod(); ++i)
	{
		// ensure level distances are increasing
		if (m_LODChangeMinDistSqr[i] < m_LODChangeMinDistSqr[i-1])
			m_LODChangeMinDistSqr[i] = m_LODChangeMinDistSqr[i-1];

	}
}

 

抱歉!评论已关闭.