OGRE 查询遮罩

来源:互联网 发布:python爬虫scrapy 编辑:程序博客网 时间:2024/04/29 11:58

查询遮罩

所有的MovableObject允许你为它们设置一个遮罩,然后SceneQueries使你能够根据这个遮罩来过滤你的结果。所有的遮罩都是通过二进制“AND”操作来实现的

 

我们要做的第一件事就是创建这个遮罩值。本节利用手札22的代码

找到MouseQueryListener类的最开始,将这些添加到public声明后面:

      enum QueryFlags
  {
      NINJA_MASK = 1<<0,
      ROBOT_MASK = 1<<1
  };

每当我们创建一个机器人实体,我们调用它的"setMask"方法将这个查询标记设置为ROBOT_MASK。

在忍者模式下,我们将使RaySceneQuery仅考虑带有NINJA_MASK标记的物体。而在机器人模式里,我们将使它仅考虑ROBOT_MASK。
在onLeftPressed找到:

              if (mRobotMode)
              {
                  sprintf(name, "Robot%d", mCount++);
                  ent = mSceneMgr->createEntity(name, "robot.mesh");
              } // if
              else
              {
                  sprintf(name, "Ninja%d", mCount++);
                  ent = mSceneMgr->createEntity(name, "ninja.mesh");
              } // else

替换为:
  if (mRobotMode)
              {
                  sprintf(name, "Robot%d", mCount++);
                  ent = mSceneMgr->createEntity(name, "robot.mesh");
                  ent->setQueryFlags(ROBOT_MASK);
              } // if
              else
              {
                  sprintf(name, "Ninja%d", mCount++);
                  ent = mSceneMgr->createEntity(name, "ninja.mesh");
                  ent->setQueryFlags(NINJA_MASK);
              } // else
我们还需要做到,当我们处于其之一种模式中时,我们只能点击和拖拽当前类型的物体。我们需要设置这个查询标记,使得只有正确的物体类型才被选择。为此,在机器人模式中,我们设置RaySceneQuery的查询标记为ROBOT_MASK,而在忍者模式里设置为NINJA_MASK。
在onLeftPressed函数里,找到这个代码:
 
mRaySceneQuery->setSortByDistance(true);
在这一行后面加上一行:
mRaySceneQuery->setQueryMask(mRobotMode ? ROBOT_MASK : NINJA_MASK);
这句修改过后,你会发现在机器人状态下,你无法选中忍者,同样在忍者状态下,你无法选中机器人。
————————————————————————————————————————————

查询类型遮罩

当使用场景查询时还有一件事需要考虑。假设你在上面的场景里加入了一个公告板或者粒子系统,并且你想要移动它。我会发现查询不会返回你点击的公告板。这是因为SceneQuery还存在另外一个遮罩,查询类型遮罩(QueryTypeMask),它限制了你只能选择这个标记指定的类型。默认情况是,当你作一个查询时,它只返回实体类型的物体。

在你的代码里,如果想要查询返回公告板或者粒子系统,则你要在执行查询之前这么做:

mRaySceneQuery->setQueryTypeMask(SceneManager::FX_TYPE_MASK);

现在查询将只返回公告板或者粒子系统作为结果。

在SceneManager类里面,已经定义了6种类型的QueryTypeMask作为静态成员:

WORLD_GEOMETRY_TYPE_MASK // 返回世界几何
ENTITY_TYPE_MASK // 返回实体
FX_TYPE_MASK // 返回公告板/粒子系统
STATICGEOMETRY_TYPE_MASK // 返回静态几何
LIGHT_TYPE_MASK // 返回光源
USER_TYPE_MASK_LIMIT // 用户类型遮罩限制

没有手工设置这个属性时,QueryTypeMask的默认值是ENTITY_TYPE_MASK。

 


设置MovableObject的遮罩


每当我们创建一个新的遮罩,它的二进制表示必须只包含一个“1”。即,这些是合法的遮罩:
00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000

等等。我们通过使用一个“1”并按位移动它,能够轻松地创建一个值。即:
00000001 = 1<<0 00000010 = 1<<1 00000100 = 1<<2 00001000 = 1<<3 00010000 = 1<<4 00100000 = 1<<5 01000000 = 1<<6 10000000 = 1<<7

直到1<<31。这样我们就有了32种不同的遮罩,可以用在MovableObject对象上。

有多个遮罩的查询

我们能使用“OR”操作符,来为多个遮罩进行查询。比如说,在游戏里我们有三个不同组的对象:

enum QueryFlags { FRIENDLY_CHARACTERS = 1<<0, ENEMY_CHARACTERS = 1<<1, STATIONARY_OBJECTS = 1<<2 };

现在,如果我们只要查询friendly characters,可以这么做:

mRaySceneQuery->setQueryMask(FRIENDLY_CHARACTERS);

如果我们要同时查询enemy characters和stationary objects,可以这么做:

mRaySceneQuery->setQueryMask(ENEMY_CHARACTERS | STATIONARY_OBJECTS);

如果你有很多这一类的查询,你可以把它们定义到枚举类型里去:

OBJECTS_ENEMIES = ENEMY_CHARACTERS | STATIONARY_OBJECTS

然后只使用OBJECTS_ENEMIES作查询。

查询遮罩以外的所有东西

你还可以使用按位反转操作,来查询除了遮罩的所有事物,就像这样:

mRaySceneQuery->setQueryMask(~FRIENDLY_CHARACTERS);

这样返回所有事物,除了friendly characters。对于多个遮罩,你也能这么做:

mRaySceneQuery->setQueryMask(~(FRIENDLY_CHARACTERS | STATIONARY_OBJECTS));

这样返回所有物体,除了friendly characters和stationary objects。

 

选取所有物体或者不选取任何物体

你还以用遮罩干一些有趣的事情。请记住,如果你为场景查询把查询遮罩设置成QM,MovableObject的遮罩为OM,如果QM & OM 包含至少一个“1”,则表示符合。因此,为场景查询把查询遮罩设置成0,将会使它不返回任何MovableObject。把查询遮罩设置成1,则返回所有查询遮罩不为0的MovableObject。

使用为0的查询遮罩有时是非常有用的。比如,当只需要返回worldFragment时,TerrainSceneManager不必使用QueryMasks。可以这么做:

mRaySceneQuery->setQueryMask(0);

在你的场景管理器的RaySceneQueries里,你就只能得到worldFragment。如果你的屏幕里有很多物体,由于你只要地形的交点而不想浪费时间循环遍历所有的东西,这样做是很有用的。

 

 

这部分并不很理解,先放着吧,理解了我在提炼