构建一个场景一般都是比较复杂的,像这样一个复杂的场景我们是不会直接拿去渲染的,这就涉及到我们为了达到各种目的对现有的场景各种目的进行切割,最终我们会使用我们切割的这部分内容。
SceneQuery:
这个类里面需要关注的是它定义的一个WorldFragment的结构体,这个结果体描述的是世界整体的一个部分。
enum WorldFragmentType { // WorldFragment的类型
WFT_NONE,
WFT_PLANE_BOUNDED_REGION, // 对应查询类型中的区域查询
WFT_SINGLE_INTERSECTION, // 对应求交查询
WFT_CUSTOM_GEOMETRY, // 用户自定义的类型
WFT_RENDER_OPERATION
};
struct WorldFragment {
WorldFragmentType fragmentType; // 与上面对应
Vector3 singleIntersection; // WFT_SINGLE_INTERSECTION
list<Plane>::type* planes; // WFT_PLANE_BOUNDED_REGION
void* geometry; // WFT_CUSTOM_GEOMETRY
RenderOperation* renderOp;
};
虽然现在还不清楚这每种类型具体针对什么结构,但是为啥WorldFragment不是联合体而是结构体呢?
SceneManager* mParentSceneMgr;
uint32 mQueryMask; //过滤查询结果,对应单一场景元素
uint32 mQueryTypeMask; //过滤查询结果,对应一类场景元素
set<WorldFragmentType>::type mSupportedWorldFragments;
WorldFragmentType mWorldFragmentType;
这里的过滤掩码在SceneManager中被定义。
IntersectionSceneQuery:(相交查询,变量所有对象,找出其中两两相交的对值)
typedef std::pair<MovableObject*, MovableObject*> SceneQueryMovableObjectPair;
typedef std::pair<MovableObject*, SceneQuery::WorldFragment*> SceneQueryMovableObjectWorldFragmentPair;
typedef list<SceneQueryMovableObjectPair>::type SceneQueryMovableIntersectionList;
typedef list<SceneQueryMovableObjectWorldFragmentPair>::type SceneQueryMovableWorldFragmentIntersectionList;
/** Holds the results of an intersection scene query (pair values). */
struct _OgreExport IntersectionSceneQueryResult : public SceneMgtAlloc
{
/// List of movable / movable intersections (entities, particle systems etc)
SceneQueryMovableIntersectionList movables2movables;
/// List of movable / world intersections
SceneQueryMovableWorldFragmentIntersectionList movables2world;
};
execute :
IntersectionSceneQuery::execute(void)
{
clearResults();
mLastResult = OGRE_NEW IntersectionSceneQueryResult();
// Call callback version with self as listener
execute(this);
return *mLastResult;
}
这个方法会查询所有满足相交的结果,但是呢这里没有实现,也就是说它的具体的子类会实现具体的碰撞规则。
这个,父类就是比较抽象,没有什么真本事。
RaySceneQuery :(沿射线方向的碰撞检测,获取相应的查询结果)
struct _OgreExport RaySceneQueryResultEntry // 存储查询结果的结构体
{
Real distance; // 射线的起点到物体的距离
MovableObject* movable; //
SceneQuery::WorldFragment* worldFragment; //
bool operator < (const RaySceneQueryResultEntry& rhs) const
{
return this->distance < rhs.distance;
}
};
typedef vector<RaySceneQueryResultEntry>::type RaySceneQueryResult;
Ray mRay; // 射线
RaySceneQueryResultEntry存储射线碰结果的结构体,每个结果体里面保存模型和之间的距离。
RegionSceneQuery :(区域检测,只要是锁定区域的全部查询出来)
typedef list<MovableObject*>::type SceneQueryResultMovableList;
typedef list<SceneQuery::WorldFragment*>::type SceneQueryResultWorldFragmentList;
/** Holds the results of a scene query. */
struct _OgreExport SceneQueryResult : public SceneMgtAlloc
{
/// List of movable objects in the query (entities, particle systems etc)
SceneQueryResultMovableList movables;
/// List of world fragments
SceneQueryResultWorldFragmentList worldFragments;
}
SceneQueryResult* mLastResult;
这是个抽象类,它只是描述了记录结果的方式。
RegionSceneQuery的子类:AxisAlignedBoxSceneQuery(边界盒查询,不规则矩形内所有对象),SphereSceneQuery(查询球状区域内的所有对象),PlaneBoundedVolumeListSceneQuery(查询一个平面上所有对象)
// 1.边界盒:利用mAABB判断边界
AxisAlignedBox mAABB;
// 2.球 :利用球体判断边界
Sphere mSphere;
// 3.平面上 :这是一个list是多个平面
PlaneBoundedVolumeList mVolumes;
我看到所有官方提供的SceneQuery类里面的void execute(SceneQueryListener* listener);都没有实现,是否以为着这个判定的规则由我们自己来实现?这样的花我们在使用的时候需要扩展自己的SceneQuery。