Ogre引擎源码——场景查询

http://blog.csdn.net/hunter8777/article/details/6249630

作为一个3D绘制引擎,3D场景的管理至关重要。最近在看这部分的源码,发现内容很多,打算从简单入手,逐一击破。

本文就来解读下场景查询SceneQuery。

相关头文件是OgreSceneQuery.h

先附上该类的UML图

Ogre引擎源码——场景查询

Ogre中将场景查询做成了一个单独的类,提供给SceneManager做相应的查询。

从UML图中可以看到,场景查询的基类是SceneQuery。它有三个直接子类,也就是Ogre直接的查询方式:区域查询、光线查询和求交查询。每种查询都有相应的查询结果结构,结果信息一般分为两类:objects和world geometry。前者是场景中可移动的物体元素(MovableObject),后者是世界信息(复杂场景中的地形等不变的元素)。由于场景管理方式可以不同(八叉树、BSP),所以同种查询在不同的场景管理器下,得到的结果也是不一样的。

(1)SceneQuery

该类成员变量如下:

  1. SceneManager*mParentSceneMgr;
  2. uint32mQueryMask;
  3. uint32mQueryTypeMask;
  4. set<WorldFragmentType>::typemSupportedWorldFragments;
  5. WorldFragmentTypemWorldFragmentType;
  1. SceneManager*mParentSceneMgr;
  2. uint32mQueryMask;
  3. uint32mQueryTypeMask;
  4. set<WorldFragmentType>::typemSupportedWorldFragments;
  5. WorldFragmentTypemWorldFragmentType;
SceneManager* mParentSceneMgr; uint32 mQueryMask; uint32 mQueryTypeMask; set<WorldFragmentType>::type mSupportedWorldFragments; WorldFragmentType mWorldFragmentType;

mParentSceneMgr用来指向当前使用该查询的场景管理器。

mQueryMask/mQueryTypeMask是一个32位掩码,用来过滤查询结果。前者对应单一场景元素,后者对应一类场景元素。

mSupportedWorldFragments表示该查询类支持的世界信息查询。

mWorldFragmentType表示当前世界信息的查询类型。

WorldFragmentType是一个枚举。

  1. enumWorldFragmentType{
  2. ///Returnnoworldgeometryhitsatall
  3. WFT_NONE,
  4. ///Returnpointerstoconvexplane-boundedregions
  5. WFT_PLANE_BOUNDED_REGION,
  6. ///Returnasingleintersectionpoint(typicallyRaySceneQueryonly)
  7. WFT_SINGLE_INTERSECTION,
  8. ///CustomgeometryasdefinedbytheSceneManager
  9. WFT_CUSTOM_GEOMETRY,
  10. ///GeneralRenderOperationstructure
  11. WFT_RENDER_OPERATION
  12. };
  1. enumWorldFragmentType{
  2. ///Returnnoworldgeometryhitsatall
  3. WFT_NONE,
  4. ///Returnpointerstoconvexplane-boundedregions
  5. WFT_PLANE_BOUNDED_REGION,
  6. ///Returnasingleintersectionpoint(typicallyRaySceneQueryonly)
  7. WFT_SINGLE_INTERSECTION,
  8. ///CustomgeometryasdefinedbytheSceneManager
  9. WFT_CUSTOM_GEOMETRY,
  10. ///GeneralRenderOperationstructure
  11. WFT_RENDER_OPERATION
  12. };
enum WorldFragmentType { /// Return no world geometry hits at all WFT_NONE, /// Return pointers to convex plane-bounded regions WFT_PLANE_BOUNDED_REGION, /// Return a single intersection point (typically RaySceneQuery only) WFT_SINGLE_INTERSECTION, /// Custom geometry as defined by the SceneManager WFT_CUSTOM_GEOMETRY, /// General RenderOperation structure WFT_RENDER_OPERATION };

这里的类对应不同查询类型的返回结果。

WFT_PLANE_BOUNDED_REGION对应查询类型中的区域查询;WFT_SINGLE_INTERSECTION对应求交查询;WFT_CUSTOM_GEOMETRY则是用户自定义的类型。

SceneQuery类的成员函数全是成员变量的getter/setter,都是虚函数。

(2)SceneQueryListener/RaySceneQueryListener/IntersectionSceneQueryListener

抽象类,负责场景查询时回调。

协作过程是将相应的Listener传入场景查询类,在查询类中完成回调。(一般查询类自身都继承Listener,所以在查询类中的执行函数execute也提供将自己作为Listener参数进行传递的重载)

这3个Listener分别对应三种查询:区域、光线、求交。其实这3个类提供的接口名称是一样的。

SceneQueryListener为例:

  1. /**CalledwhenaMovableObjectisreturnedbyaquery.*/
  2. virtualboolqueryResult(MovableObject*object)=0;
  3. /**CalledwhenaWorldFragmentisreturnedbyaquery.*/
  4. virtualboolqueryResult(SceneQuery::WorldFragment*fragment)=0;
  1. /**CalledwhenaMovableObjectisreturnedbyaquery.*/
  2. virtualboolqueryResult(MovableObject*object)=0;
  3. /**CalledwhenaWorldFragmentisreturnedbyaquery.*/
  4. virtualboolqueryResult(SceneQuery::WorldFragment*fragment)=0;
/** Called when a MovableObject is returned by a query.*/ virtual bool queryResult(MovableObject* object) = 0; /** Called when a WorldFragment is returned by a query.*/ virtual bool queryResult(SceneQuery::WorldFragment* fragment) = 0;

提供两个接口分别对应的就是两种不同的查询结果:可移动的物体元素和世界信息。

分别对三种查询提供三种Listener的原因是后两种需要一些附加的信息。RaySceneQueryListener需要返回Ray上的距离信息;IntersectionSceneQueryListener则是以相交的成对场景元素返回。

(3)SceneQueryResult/RaySceneQueryResultEntry/IntersectionSceneQueryResult

结构体,用来作为查询结果返回。以SceneQueryResult为例:

  1. ///Listofmovableobjectsinthequery(entities,particlesystemsetc)
  2. SceneQueryResultMovableListmovables;
  3. ///Listofworldfragments
  4. SceneQueryResultWorldFragmentListworldFragments;
  1. ///Listofmovableobjectsinthequery(entities,particlesystemsetc)
  2. SceneQueryResultMovableListmovables;
  3. ///Listofworldfragments
  4. SceneQueryResultWorldFragmentListworldFragments;
/// List of movable objects in the query (entities, particle systems etc) SceneQueryResultMovableList movables; /// List of world fragments SceneQueryResultWorldFragmentList worldFragments;

如前多次所述,所有的查询结果都分为两类:可移动的物体元素和世界信息。

分别对应三种查询提供三种结果结构,理由和Listener一样。

(4)RegionSceneQuery/RaySceneQuery/IntersectionSceneQuery

抽象类,继承自相应的SceneQuery和Listener类。该类主要有两个作用:保存查询结果、提供外部执行查询的接口。

以RegionSceneQuery为例:

它所对应的查询结果是SceneQueryResult,成员变量也就仅此一个。

  1. SceneQueryResult*mLastResult;
  1. SceneQueryResult*mLastResult;
SceneQueryResult* mLastResult;

最重要的两个执行函数就是

  1. /**Executesthequery,returningtheresultsbackinonelist.*/
  2. virtualSceneQueryResult&execute(void);
  3. /**Executesthequeryandreturnseachmatchthroughalistenerinterface.*/
  4. virtualvoidexecute(SceneQueryListener*listener)=0;
  1. /**Executesthequery,returningtheresultsbackinonelist.*/
  2. virtualSceneQueryResult&execute(void);
  3. /**Executesthequeryandreturnseachmatchthroughalistenerinterface.*/
  4. virtualvoidexecute(SceneQueryListener*listener)=0;
/** Executes the query, returning the results back in one list. */ virtual SceneQueryResult& execute(void); /** Executes the query and returns each match through a listener interface. */ virtual void execute(SceneQueryListener* listener) = 0;

这才是真正做查询的接口。

第二个execute函数一般会将查询类自身作为参数传入(因为查询类继承自Listener)。无参数的exectue函数通常会调用有参数的execute重载版本。

RegionSceneQuery还分别派生了AxisAlignedBoxSceneQuery/SphereSceneQuery/PlaneBoundedVolumeListSceneQuery。

这三个类中还会保存有相应的区域结构(如AAB就存有一个AxisAlignedBox类等),用来设定相应的区域。

http://blog.csdn.net/hunter8777/article/details/6249630

作为一个3D绘制引擎,3D场景的管理至关重要。最近在看这部分的源码,发现内容很多,打算从简单入手,逐一击破。

本文就来解读下场景查询SceneQuery。

相关头文件是OgreSceneQuery.h

先附上该类的UML图

Ogre引擎源码——场景查询

Ogre中将场景查询做成了一个单独的类,提供给SceneManager做相应的查询。

从UML图中可以看到,场景查询的基类是SceneQuery。它有三个直接子类,也就是Ogre直接的查询方式:区域查询、光线查询和求交查询。每种查询都有相应的查询结果结构,结果信息一般分为两类:objects和world geometry。前者是场景中可移动的物体元素(MovableObject),后者是世界信息(复杂场景中的地形等不变的元素)。由于场景管理方式可以不同(八叉树、BSP),所以同种查询在不同的场景管理器下,得到的结果也是不一样的。

(1)SceneQuery

该类成员变量如下:

  1. SceneManager*mParentSceneMgr;
  2. uint32mQueryMask;
  3. uint32mQueryTypeMask;
  4. set<WorldFragmentType>::typemSupportedWorldFragments;
  5. WorldFragmentTypemWorldFragmentType;
  1. SceneManager*mParentSceneMgr;
  2. uint32mQueryMask;
  3. uint32mQueryTypeMask;
  4. set<WorldFragmentType>::typemSupportedWorldFragments;
  5. WorldFragmentTypemWorldFragmentType;
SceneManager* mParentSceneMgr; uint32 mQueryMask; uint32 mQueryTypeMask; set<WorldFragmentType>::type mSupportedWorldFragments; WorldFragmentType mWorldFragmentType;

mParentSceneMgr用来指向当前使用该查询的场景管理器。

mQueryMask/mQueryTypeMask是一个32位掩码,用来过滤查询结果。前者对应单一场景元素,后者对应一类场景元素。

mSupportedWorldFragments表示该查询类支持的世界信息查询。

mWorldFragmentType表示当前世界信息的查询类型。

WorldFragmentType是一个枚举。

  1. enumWorldFragmentType{
  2. ///Returnnoworldgeometryhitsatall
  3. WFT_NONE,
  4. ///Returnpointerstoconvexplane-boundedregions
  5. WFT_PLANE_BOUNDED_REGION,
  6. ///Returnasingleintersectionpoint(typicallyRaySceneQueryonly)
  7. WFT_SINGLE_INTERSECTION,
  8. ///CustomgeometryasdefinedbytheSceneManager
  9. WFT_CUSTOM_GEOMETRY,
  10. ///GeneralRenderOperationstructure
  11. WFT_RENDER_OPERATION
  12. };
  1. enumWorldFragmentType{
  2. ///Returnnoworldgeometryhitsatall
  3. WFT_NONE,
  4. ///Returnpointerstoconvexplane-boundedregions
  5. WFT_PLANE_BOUNDED_REGION,
  6. ///Returnasingleintersectionpoint(typicallyRaySceneQueryonly)
  7. WFT_SINGLE_INTERSECTION,
  8. ///CustomgeometryasdefinedbytheSceneManager
  9. WFT_CUSTOM_GEOMETRY,
  10. ///GeneralRenderOperationstructure
  11. WFT_RENDER_OPERATION
  12. };
enum WorldFragmentType { /// Return no world geometry hits at all WFT_NONE, /// Return pointers to convex plane-bounded regions WFT_PLANE_BOUNDED_REGION, /// Return a single intersection point (typically RaySceneQuery only) WFT_SINGLE_INTERSECTION, /// Custom geometry as defined by the SceneManager WFT_CUSTOM_GEOMETRY, /// General RenderOperation structure WFT_RENDER_OPERATION };

这里的类对应不同查询类型的返回结果。

WFT_PLANE_BOUNDED_REGION对应查询类型中的区域查询;WFT_SINGLE_INTERSECTION对应求交查询;WFT_CUSTOM_GEOMETRY则是用户自定义的类型。

SceneQuery类的成员函数全是成员变量的getter/setter,都是虚函数。

(2)SceneQueryListener/RaySceneQueryListener/IntersectionSceneQueryListener

抽象类,负责场景查询时回调。

协作过程是将相应的Listener传入场景查询类,在查询类中完成回调。(一般查询类自身都继承Listener,所以在查询类中的执行函数execute也提供将自己作为Listener参数进行传递的重载)

这3个Listener分别对应三种查询:区域、光线、求交。其实这3个类提供的接口名称是一样的。

SceneQueryListener为例:

  1. /**CalledwhenaMovableObjectisreturnedbyaquery.*/
  2. virtualboolqueryResult(MovableObject*object)=0;
  3. /**CalledwhenaWorldFragmentisreturnedbyaquery.*/
  4. virtualboolqueryResult(SceneQuery::WorldFragment*fragment)=0;
  1. /**CalledwhenaMovableObjectisreturnedbyaquery.*/
  2. virtualboolqueryResult(MovableObject*object)=0;
  3. /**CalledwhenaWorldFragmentisreturnedbyaquery.*/
  4. virtualboolqueryResult(SceneQuery::WorldFragment*fragment)=0;
/** Called when a MovableObject is returned by a query.*/ virtual bool queryResult(MovableObject* object) = 0; /** Called when a WorldFragment is returned by a query.*/ virtual bool queryResult(SceneQuery::WorldFragment* fragment) = 0;

提供两个接口分别对应的就是两种不同的查询结果:可移动的物体元素和世界信息。

分别对三种查询提供三种Listener的原因是后两种需要一些附加的信息。RaySceneQueryListener需要返回Ray上的距离信息;IntersectionSceneQueryListener则是以相交的成对场景元素返回。

(3)SceneQueryResult/RaySceneQueryResultEntry/IntersectionSceneQueryResult

结构体,用来作为查询结果返回。以SceneQueryResult为例:

  1. ///Listofmovableobjectsinthequery(entities,particlesystemsetc)
  2. SceneQueryResultMovableListmovables;
  3. ///Listofworldfragments
  4. SceneQueryResultWorldFragmentListworldFragments;
  1. ///Listofmovableobjectsinthequery(entities,particlesystemsetc)
  2. SceneQueryResultMovableListmovables;
  3. ///Listofworldfragments
  4. SceneQueryResultWorldFragmentListworldFragments;
/// List of movable objects in the query (entities, particle systems etc) SceneQueryResultMovableList movables; /// List of world fragments SceneQueryResultWorldFragmentList worldFragments;

如前多次所述,所有的查询结果都分为两类:可移动的物体元素和世界信息。

分别对应三种查询提供三种结果结构,理由和Listener一样。

(4)RegionSceneQuery/RaySceneQuery/IntersectionSceneQuery

抽象类,继承自相应的SceneQuery和Listener类。该类主要有两个作用:保存查询结果、提供外部执行查询的接口。

以RegionSceneQuery为例:

它所对应的查询结果是SceneQueryResult,成员变量也就仅此一个。

  1. SceneQueryResult*mLastResult;
  1. SceneQueryResult*mLastResult;
SceneQueryResult* mLastResult;

最重要的两个执行函数就是

  1. /**Executesthequery,returningtheresultsbackinonelist.*/
  2. virtualSceneQueryResult&execute(void);
  3. /**Executesthequeryandreturnseachmatchthroughalistenerinterface.*/
  4. virtualvoidexecute(SceneQueryListener*listener)=0;
  1. /**Executesthequery,returningtheresultsbackinonelist.*/
  2. virtualSceneQueryResult&execute(void);
  3. /**Executesthequeryandreturnseachmatchthroughalistenerinterface.*/
  4. virtualvoidexecute(SceneQueryListener*listener)=0;
/** Executes the query, returning the results back in one list. */ virtual SceneQueryResult& execute(void); /** Executes the query and returns each match through a listener interface. */ virtual void execute(SceneQueryListener* listener) = 0;

这才是真正做查询的接口。

第二个execute函数一般会将查询类自身作为参数传入(因为查询类继承自Listener)。无参数的exectue函数通常会调用有参数的execute重载版本。

RegionSceneQuery还分别派生了AxisAlignedBoxSceneQuery/SphereSceneQuery/PlaneBoundedVolumeListSceneQuery。

这三个类中还会保存有相应的区域结构(如AAB就存有一个AxisAlignedBox类等),用来设定相应的区域。

作为一个3D绘制引擎,3D场景的管理至关重要。最近在看这部分的源码,发现内容很多,打算从简单入手,逐一击破。

本文就来解读下场景查询SceneQuery。

相关头文件是OgreSceneQuery.h

先附上该类的UML图

Ogre引擎源码——场景查询

Ogre中将场景查询做成了一个单独的类,提供给SceneManager做相应的查询。

从UML图中可以看到,场景查询的基类是SceneQuery。它有三个直接子类,也就是Ogre直接的查询方式:区域查询、光线查询和求交查询。每种查询都有相应的查询结果结构,结果信息一般分为两类:objects和world geometry。前者是场景中可移动的物体元素(MovableObject),后者是世界信息(复杂场景中的地形等不变的元素)。由于场景管理方式可以不同(八叉树、BSP),所以同种查询在不同的场景管理器下,得到的结果也是不一样的。

(1)SceneQuery

该类成员变量如下:

  1. SceneManager*mParentSceneMgr;
  2. uint32mQueryMask;
  3. uint32mQueryTypeMask;
  4. set<WorldFragmentType>::typemSupportedWorldFragments;
  5. WorldFragmentTypemWorldFragmentType;
  1. SceneManager*mParentSceneMgr;
  2. uint32mQueryMask;
  3. uint32mQueryTypeMask;
  4. set<WorldFragmentType>::typemSupportedWorldFragments;
  5. WorldFragmentTypemWorldFragmentType;
SceneManager* mParentSceneMgr; uint32 mQueryMask; uint32 mQueryTypeMask; set<WorldFragmentType>::type mSupportedWorldFragments; WorldFragmentType mWorldFragmentType;

mParentSceneMgr用来指向当前使用该查询的场景管理器。

mQueryMask/mQueryTypeMask是一个32位掩码,用来过滤查询结果。前者对应单一场景元素,后者对应一类场景元素。

mSupportedWorldFragments表示该查询类支持的世界信息查询。

mWorldFragmentType表示当前世界信息的查询类型。

WorldFragmentType是一个枚举。

  1. enumWorldFragmentType{
  2. ///Returnnoworldgeometryhitsatall
  3. WFT_NONE,
  4. ///Returnpointerstoconvexplane-boundedregions
  5. WFT_PLANE_BOUNDED_REGION,
  6. ///Returnasingleintersectionpoint(typicallyRaySceneQueryonly)
  7. WFT_SINGLE_INTERSECTION,
  8. ///CustomgeometryasdefinedbytheSceneManager
  9. WFT_CUSTOM_GEOMETRY,
  10. ///GeneralRenderOperationstructure
  11. WFT_RENDER_OPERATION
  12. };
  1. enumWorldFragmentType{
  2. ///Returnnoworldgeometryhitsatall
  3. WFT_NONE,
  4. ///Returnpointerstoconvexplane-boundedregions
  5. WFT_PLANE_BOUNDED_REGION,
  6. ///Returnasingleintersectionpoint(typicallyRaySceneQueryonly)
  7. WFT_SINGLE_INTERSECTION,
  8. ///CustomgeometryasdefinedbytheSceneManager
  9. WFT_CUSTOM_GEOMETRY,
  10. ///GeneralRenderOperationstructure
  11. WFT_RENDER_OPERATION
  12. };
enum WorldFragmentType { /// Return no world geometry hits at all WFT_NONE, /// Return pointers to convex plane-bounded regions WFT_PLANE_BOUNDED_REGION, /// Return a single intersection point (typically RaySceneQuery only) WFT_SINGLE_INTERSECTION, /// Custom geometry as defined by the SceneManager WFT_CUSTOM_GEOMETRY, /// General RenderOperation structure WFT_RENDER_OPERATION };

这里的类对应不同查询类型的返回结果。

WFT_PLANE_BOUNDED_REGION对应查询类型中的区域查询;WFT_SINGLE_INTERSECTION对应求交查询;WFT_CUSTOM_GEOMETRY则是用户自定义的类型。

SceneQuery类的成员函数全是成员变量的getter/setter,都是虚函数。

(2)SceneQueryListener/RaySceneQueryListener/IntersectionSceneQueryListener

抽象类,负责场景查询时回调。

协作过程是将相应的Listener传入场景查询类,在查询类中完成回调。(一般查询类自身都继承Listener,所以在查询类中的执行函数execute也提供将自己作为Listener参数进行传递的重载)

这3个Listener分别对应三种查询:区域、光线、求交。其实这3个类提供的接口名称是一样的。

SceneQueryListener为例:

  1. /**CalledwhenaMovableObjectisreturnedbyaquery.*/
  2. virtualboolqueryResult(MovableObject*object)=0;
  3. /**CalledwhenaWorldFragmentisreturnedbyaquery.*/
  4. virtualboolqueryResult(SceneQuery::WorldFragment*fragment)=0;
  1. /**CalledwhenaMovableObjectisreturnedbyaquery.*/
  2. virtualboolqueryResult(MovableObject*object)=0;
  3. /**CalledwhenaWorldFragmentisreturnedbyaquery.*/
  4. virtualboolqueryResult(SceneQuery::WorldFragment*fragment)=0;
/** Called when a MovableObject is returned by a query.*/ virtual bool queryResult(MovableObject* object) = 0; /** Called when a WorldFragment is returned by a query.*/ virtual bool queryResult(SceneQuery::WorldFragment* fragment) = 0;

提供两个接口分别对应的就是两种不同的查询结果:可移动的物体元素和世界信息。

分别对三种查询提供三种Listener的原因是后两种需要一些附加的信息。RaySceneQueryListener需要返回Ray上的距离信息;IntersectionSceneQueryListener则是以相交的成对场景元素返回。

(3)SceneQueryResult/RaySceneQueryResultEntry/IntersectionSceneQueryResult

结构体,用来作为查询结果返回。以SceneQueryResult为例:

  1. ///Listofmovableobjectsinthequery(entities,particlesystemsetc)
  2. SceneQueryResultMovableListmovables;
  3. ///Listofworldfragments
  4. SceneQueryResultWorldFragmentListworldFragments;
  1. ///Listofmovableobjectsinthequery(entities,particlesystemsetc)
  2. SceneQueryResultMovableListmovables;
  3. ///Listofworldfragments
  4. SceneQueryResultWorldFragmentListworldFragments;
/// List of movable objects in the query (entities, particle systems etc) SceneQueryResultMovableList movables; /// List of world fragments SceneQueryResultWorldFragmentList worldFragments;

如前多次所述,所有的查询结果都分为两类:可移动的物体元素和世界信息。

分别对应三种查询提供三种结果结构,理由和Listener一样。

(4)RegionSceneQuery/RaySceneQuery/IntersectionSceneQuery

抽象类,继承自相应的SceneQuery和Listener类。该类主要有两个作用:保存查询结果、提供外部执行查询的接口。

以RegionSceneQuery为例:

它所对应的查询结果是SceneQueryResult,成员变量也就仅此一个。

  1. SceneQueryResult*mLastResult;
  1. SceneQueryResult*mLastResult;
SceneQueryResult* mLastResult;

最重要的两个执行函数就是

  1. /**Executesthequery,returningtheresultsbackinonelist.*/
  2. virtualSceneQueryResult&execute(void);
  3. /**Executesthequeryandreturnseachmatchthroughalistenerinterface.*/
  4. virtualvoidexecute(SceneQueryListener*listener)=0;
  1. /**Executesthequery,returningtheresultsbackinonelist.*/
  2. virtualSceneQueryResult&execute(void);
  3. /**Executesthequeryandreturnseachmatchthroughalistenerinterface.*/
  4. virtualvoidexecute(SceneQueryListener*listener)=0;
/** Executes the query, returning the results back in one list. */ virtual SceneQueryResult& execute(void); /** Executes the query and returns each match through a listener interface. */ virtual void execute(SceneQueryListener* listener) = 0;

这才是真正做查询的接口。

第二个execute函数一般会将查询类自身作为参数传入(因为查询类继承自Listener)。无参数的exectue函数通常会调用有参数的execute重载版本。

RegionSceneQuery还分别派生了AxisAlignedBoxSceneQuery/SphereSceneQuery/PlaneBoundedVolumeListSceneQuery。

这三个类中还会保存有相应的区域结构(如AAB就存有一个AxisAlignedBox类等),用来设定相应的区域。