在场景动态角色非常多的情况下, 使用假影子可以大大提高速度.
当前游戏中影子效果图如下:
将一个Faked Shadow封装成一个对象, 继承与 Ogre::Node::Listener,
实现其 nodeUpate(const Node* node) 成员函数.
让其在场景节点坐标改变时通知你,
以更新影子平面的方位.
代码如下:
{
//如果位置没有被改变则不需要重新得到地面的法线
if(m_LastPos != node->getPosition())
{
m_LastPos = node->getPosition();
m_pSceneNode->setPosition(node->getPosition()+Ogre::Vector3(0, 0.05, 0));
Ogre::Vector3 newNormal = getTerrainNormal(node);
//将影子片面旋转到朝向法线
Ogre::Vector3 s(0, 1, 0);
Ogre::Quaternion quat = s.getRotationTo(newNormal);
m_pSceneNode->setOrientation(quat);
}
}
Ogre::Vector3 FakeShadow::getTerrainNormal(const Ogre::Node* node)
{
//得到法线策略如下
//从当前位置周围放出三条射线(近似构成正三角形)
//得到三个点交点,其构成三角形
//求其三角形的法线,即位当前位置地形的法线
Ogre::Vector3 originPos1 = node->getPosition() + Ogre::Vector3(0, 1000, 0.5);
Ogre::Vector3 originPos2 = node->getPosition() + Ogre::Vector3(0.3, 1000, -0.15);
Ogre::Vector3 originPos3 = node->getPosition() + Ogre::Vector3(-0.3, 1000, -0.15);
Ogre::Vector3 intersectP1 = originPos1;
Ogre::Vector3 intersectP2 = originPos2;
Ogre::Vector3 intersectP3 = originPos3;
intersectP1.y = node->getPosition().y;
intersectP2.y = node->getPosition().y;
intersectP3.y = node->getPosition().y;
m_pDScene->intersectWithRay(Ogre::Ray(originPos1, Ogre::Vector3::NEGATIVE_UNIT_Y), intersectP1);
m_pDScene->intersectWithRay(Ogre::Ray(originPos2, Ogre::Vector3::NEGATIVE_UNIT_Y), intersectP2);
m_pDScene->intersectWithRay(Ogre::Ray(originPos3, Ogre::Vector3::NEGATIVE_UNIT_Y), intersectP3);
return Ogre::Math::calculateBasicFaceNormal(intersectP1, intersectP2, intersectP3);
}