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

战场地图上的 Faked Shadow 基本实现

2013年11月29日 ⁄ 综合 ⁄ 共 1582字 ⁄ 字号 评论关闭
Faked Shadow (假影子) 即用一个平面代表影子, 且紧贴地面, 其朝向与地面的法线一致.
在场景动态角色非常多的情况下, 使用假影子可以大大提高速度.

当前游戏中影子效果图如下:

uploads/200706/15_192655_fakeshadow.jpg

将一个Faked Shadow封装成一个对象, 继承与 Ogre::Node::Listener,
实现其 nodeUpate(const Node* node) 成员函数.
让其在场景节点坐标改变时通知你,
以更新影子平面的方位.

代码如下:

void FakeShadow::nodeUpdated(const Ogre::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);
}

抱歉!评论已关闭.