場景查詢
創建查詢的代價比較大,而執行不是。SceneQueryResualt只定義了兩種成員:movables與worldFragments.
掩碼也需要自己定義,自己解釋。在一個軸對齊盒子中查詢燈光的例子如下:
const unsigned int LIGHT_QUERY_MASK = 0x00000001; //掩碼定義
Light* light1 = mSceneMgr->createLight("Light1");
Light* light2 = mSceneMgr->createLight("Light2");
light1->setPosition(12, 12, 12);
light2->setPosition(5, 5, 5);
light1->setQueryFlags(LIGHT_QUERY_MASK);
light2->setQueryFlags(LIGHT_QUERY_MASK);
AxisAlignedBoxSceneQuery* lightQuery =
mSceneMgr->createAABBQuery(
AxisAlignedBox(0, 0, 0, 10, 10, 10), LIGHT_QUERY_MASK);
// sometime later in the application's code, find out what lights are in the box
SceneQueryResult& results = lightQuery->execute(); //查詢
// iterate through the list of items returned; there should only be one, and it
// should be light2 created above. The list iterator is MovableObject type.
SceneQueryResultMovableList::iterator it = results.movables.begin();
for (; it != results.movables.end(); it++)
{
// act only on the lights, which should be all we have
assert ((*it)->getQueryFlags() & LIGHT_QUERY_MASK) != 0);
// do whatever it was we needed to do with the lights
}
// destroy the query when we are done with it
mSceneMgr->destroyQuery(lightQuery);
我們知道地形總是起伏不平的,當主角在上面行走時需要根據地形的高度調整,可以光線查詢來實現。
原理比較簡單:向主角腳下執行光線查詢,與地形有一個交點,根據交點的高度調整主角位置。
Terrain Clamping
void Entity::clampToTerrain() {
static Ogre::Ray updateRay;
updateRay.setOrigin(m_controlledNode->getPosition() + Ogre::Vector3(0, 15, 0));
updateRay.setDirection(Ogre::Vector3::NEGATIVE_UNIT_Y);
m_raySceneQuery->setRay(updateRay);
Ogre::RaySceneQueryResult& qryResult = m_raySceneQuery->execute();
if (qryResult.size() == 0) {
// then we are under the terrain and need to pop above it
updateRay.setOrigin(m_controlledNode->getPosition());
updateRay.setDirection(Ogre::Vector3::UNIT_Y);
m_raySceneQuery->setRay(updateRay);
}
qryResult = m_raySceneQuery->execute();
Ogre::RaySceneQueryResult::iterator i = qryResult.begin();
if (i != qryResult.end() && i->worldFragment)
{
Ogre::SceneQuery::WorldFragment* wf = i->worldFragment;
m_controlledNode->setPosition(m_controlledNode->getPosition().x,
i->worldFragment->singleIntersection.y,
m_controlledNode->getPosition().z);
}
}
void Entity::init()
{
// lots of other irrelevant entity init stuff goes here
m_raySceneQuery = sm->createRayQuery(
Ogre::Ray(m_controlledNode->getPosition(),
Ogre::Vector3::NEGATIVE_UNIT_Y));
// move this node is such a way that it is above the terrain
clampToTerrain();
}