source: GTP/trunk/Lib/Vis/Preprocessing/manual/integration.tex @ 2104

Revision 2104, 14.0 KB checked in by mattausch, 17 years ago (diff)
Line 
1\section{Introduction}
2\label{sec:introduction}
3
4This manual provides a guide to apply preprocessed visibility in a particular target engine. It
5will start with instruction for building the preprocessor, describes the integration of the
6preprocessor and the generated visibility solution, and last but not least the usage of
7the view cells within the target engine.
8
9\section{Build Project}
10\label{sec:build}
11
12Open the {\em GtpVisibility.sln} with {\em Visual Studio 2003} (2005 might work, but we did not test it recently).
13Set the build target to {\em Release}. Build the project {\em TestPreprocessor}. Now there should be a newly built
14executable {\em Preprocessor.exe} in {\em bin{/}release} and a library {\em Preprocessor.lib}
15in {\em lib{/}release}.
16
17\section{Generate Visibility Solution}
18\label{sec:visibility}
19
20All necessary scripts are located in the {\em Preprocessor/scripts} directory.
21The easiest way to use the scripts is with Cygwin.
22First some meaningful view cells must be generated for the current scene.
23The script {\em generate\_viewcells.sh} is responsible for view cell generation.
24It takes the parameters from the file {\em generate\_viewcells.env}.
25To specify the input scene, the parameter
26
27\begin{verbatim}Scene.filename\end{verbatim}
28
29must be set to the file name of the new scene. Our preprocessor supports the formats obj and x3d.
30Important options for performance are
31
32%\begin{verbatim}
33%VspBspTree.Construction.samples
34%VspBspTree.Termination.maxViewCells
35%\end{verbatim}
36
37\begin{verbatim}
38Hierarchy.Construction.samples
39VspTree.Termination.maxLeaves
40\end{verbatim}
41
42The first parameter sets the number of samples that is used for view cell construction. Less samples
43means faster computation, but maybe slightly less optimized view cells. The second
44parameter sets the maximal number of view cells.
45%The easiest way to use the file is with Cygwin, but a windows command line will also do the job
46
47Running the script will generate a visibility solution with empty view cells.
48Now we must compute visibility for these view cells.
49In the preprocessor script {\em generate\_visibility.sh}, set the following parameter to the
50newly generated visibility solution.
51
52\begin{verbatim}ViewCells.filename\end{verbatim}
53
54This script starts the preprocessor and generates the full visibility solution. This solution contains
55view cells and the corresponding Potentially Visible Set (PVS). Next we explain how this visibility
56solution can be used in a target engine.
57
58 
59\section{Integration of Preprocessed Visibility}
60\label{sec:integration}
61
62\subsection{Requirements}
63\label{sec:requirements}
64
65Add the following libraries to your application.
66
67\begin{itemize}
68\item {\em Preprocessor.lib }
69\item {\em zdll.lib }
70\item {\em zziplib.lib }
71\item {\em xerces\-c\_2.lib }
72\item {\em devil.lib }
73\item {\em glut32.lib }
74\item {\em OpenGL32.Lib }
75\item {\em glu32.lib }
76\item {\em glew32.lib }
77\item {\em glew32s.lib }
78\end{itemize}
79
80The libraries can be found in the following directories.
81
82\begin{itemize}
83\item {\em trunk/Lib/Vis/Preprocessing/lib/Release }
84\item {\em GTP/trunk/Lib/Vis/Preprocessing/src/GL }
85\item {\em NonGTP/Xerces/xercesc/lib }
86\item {\em NonGTP/Zlib/lib }
87\end{itemize}
88
89This include directory must be added to your Solution.
90
91\begin{itemize}
92\item {\em GTP/trunk/Lib/Vis/Preprocessing/src }
93\end{itemize}
94
95In order to employ the preprocessor in a target engine we must make
96the visibility solution (PVS data) available in the engine.
97For this purpose we associate the entities of the engine with the PVS
98entries from the visibility solution.
99For this purposse the user must implement a small number of interface classes
100of the preprocessor.
101We demonstrate this on a small example, which shows how to access preprocessed visibility
102in the popular rendering engine Ogre3D. Of course, the implementation has to be adapted
103to the requirements of a particular target engine.
104
105\begin{verbatim}
106// this class associates PVS entries
107// with the entities of the engine.
108OctreeBoundingBoxConverter bconverter(this);
109         
110// a vector of intersectables
111ObjectContainer objects;
112
113// load the view cells and their PVS
114GtpVisibilityPreprocessor::ViewCellsManager *viewCellsManager =
115         GtpVisibilityPreprocessor::ViewCellsManager::LoadViewCells
116                                   (filename, &objects, &bconverter);
117\end{verbatim}
118
119This piece of code is loading the view cells into the engine.
120Let's analyze this code. There are two constructs that need explanation, the
121BoundingBoxConverter and the ObjectContainer, and the view cells manager.
122
123\paragraph{BoundingBoxConverter}
124\label{sec:BoundingBoxConverter}
125
126This is one of the interfaces that must be implemented
127In this case, we implemented an OctreeBoundingBoxConverter for the Ogre OctreeSceneManager.
128The bounding box converter is used to associate one or more entities (objects)
129in the engine with each pvs entry of the visibility solution. This is done by
130geometric comparison of the bounding boxes.
131
132In the current setting we compare not for equality but for intersection.
133All entities of the engine intersecting a bounding box of a PVS entry are
134associated with this PVS entry. This means that often more than one entity in the
135engine will map to a particular pvs entry. This gives a slight overestimation of
136PVS but yields a very robust solution.
137
138\paragraph{ObjectContainer}
139\label{sec:ObjectContainer}
140
141The object container is basicly a vector of {\em Intersectable *}. It contains all
142static entities of the scene.
143A PVS entry must be derived from this class. To get access to the PVS of a view cell,
144the user must implement this interface as a wrapper for the entities in the
145particular engine.
146
147\paragraph{ViewCellsManager}
148\label{sec:Loading}
149
150A view cells manager is returned from the loading call. It will be used to access and
151manage the view cells from now on. For example, it can be applied to locate the current view cell.
152For loading, the user has to provide the filename of the visibility solution, an ObjectContainer
153containing all the static entities of the scene, and a bounding box converter.
154After this step the view cells should be loaded and accessable in the engine.
155
156\section{Example Implementation}
157\label{sec:implementation}
158
159In this section we show an example implementation for the interface classes in Ogre3D.
160
161\subsection{Intersectable}
162\label{sec:intersectable}
163
164In our current setting we said that we test for intersection other than equality when
165assigning the pvs entries to engine entites. Hence there can be more than one matching object
166per PVS entry, and there is a 1:n relationship. The typical wrapper for
167an {\em Intersectable} will therefore contain an array of entities corresponding to this PVS entry.
168In order to use the entities of the target engine instead of Ogre3D entities,
169replace {\em Entity} with the entity representation of the target engine.
170
171\begin{verbatim}
172
173// a vector of engine entities
174typedef vector<Entity *> EntityContainer;
175
176class EngineIntersectable: public GtpVisibilityPreprocessor::
177                                IntersectableWrapper<EntityContainer *>
178{
179public:
180   EngineIntersectable(EntityContainer *item): GtpVisibilityPreprocessor::
181      IntersectableWrapper<EntityContainer *>(item)
182   {}
183
184   EngineIntersectable::~EngineIntersectable()
185   {
186       delete mItem;
187   }
188
189   int Type() const
190   {
191       return Intersectable::ENGINE_INTERSECTABLE;
192   }
193};
194
195\end{verbatim}
196
197
198\subsection{Bounding Box Converter}
199\label{sec:Converter}
200
201This is maybe the most tricky part of the integration. The bounding box converter
202is necessary because we have to associate the objects of the visibility solution with
203the objects from the engine without having unique ids.
204
205We give an example for a Bounding Box Converter
206for Ogre. It is templated in order to works with any Ogre SceneManager.
207Again, the implementation of this interface must be adapted for the requirements
208of the particular engine.
209
210\begin{verbatim}
211
212/**     Class which converts preprocessor entites to Ogre3D entities
213*/
214template<typename T> PlatFormBoundingBoxConverter:
215    public GtpVisibilityPreprocessor::BoundingBoxConverter
216{
217public:
218  PlatFormBoundingBoxConverter(T *sm);
219       
220  /** Takes a vector of indexed bounding boxes and uses it to
221      identify objects with a similar bounding box
222      and assigns them the proper index (id).
223      The objects are returned in the object container.
224               
225      @returns true if conversion was successful
226  */
227  bool IdentifyObjects(const GtpVisibilityPreprocessor::
228         IndexedBoundingBoxContainer &iboxes,
229               GtpVisibilityPreprocessor::ObjectContainer &objects) const;
230
231protected:
232
233  /** find objects which are intersected by this box
234  */
235  void FindIntersectingObjects(const AxisAlignedBox &box,
236                               vector<Entity *> &objects) const;
237
238  T *mSceneMgr;
239};
240
241typedef PlatFormBoundingBoxConverter<OctreeSceneManager>
242          OctreeBoundingBoxConverter;
243
244\end{verbatim}
245
246This class is inherited from {\em BoundingBoxConverter}.
247{\em BoundingBoxConverters} has only one virtual function {\em IdentifyObjects} that must
248be implemented. Additionally we
249use a helper function {\em FindIntersectingObjects} that is responsible for locating the
250corresponding objects in the scene. Let's now have a look at the
251implementation of {\em IdentifyObjects} for Ogre3D.
252
253\begin{verbatim}
254template<typename T>
255bool PlatFormBoundingBoxConverter<T>::IdentifyObjects(
256       const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes,
257       GtpVisibilityPreprocessor::ObjectContainer &objects) const
258{
259  GtpVisibilityPreprocessor::IndexedBoundingBoxContainer::
260          const_iterator iit, iit_end = iboxes.end();
261 
262  for (iit = iboxes.begin(); iit != iit_end; ++ iit)
263  {
264    const AxisAlignedBox box =
265      OgreTypeConverter::ConvertToOgre((*iit).second);
266               
267    EntityContainer *entryObjects = new EntityContainer();
268
269    // find all objects that intersect the bounding box
270    FindIntersectingObjects(box, *entryObjects);
271
272    EngineIntersectable *entry = new EngineIntersectable(entryObjects);
273    entry->SetId((*iit).first);
274
275    objects.push_back(entry);
276  }
277  return true;
278}
279\end{verbatim}
280
281The function just loops over the bounding boxes of the PVS entries and finds the entities that
282are intersected by the bouding boxes. Let's have a look now at the function {\em FindIntersectingObjects}, which
283is searching the intersections for each individual box.
284
285
286\begin{verbatim}
287template<typename T>
288void PlatFormBoundingBoxConverter<T>::FindIntersectingObjects(
289       const AxisAlignedBox &box,
290       EntityContainer &objects) const
291{
292  list<SceneNode *> sceneNodeList;
293                       
294  // find intersecting scene nodes to get candidates for intersection
295  // note: this function has to be provided by scene manager
296  mSceneMgr->findNodesIn(box, sceneNodeList, NULL);
297
298  // convert the bounding box to preprocessor format
299  GtpVisibilityPreprocessor::AxisAlignedBox3 nodeBox =
300    OgreTypeConverter::ConvertFromOgre(box);
301       
302  // loop through the intersecting scene nodes
303  for (sit = sceneNodeList.begin(); sit != sceneNodeList.end(); ++ sit)
304  {
305    SceneNode *sn = *sit;
306    SceneNode::ObjectIterator oit = sn->getAttachedObjectIterator();
307
308    // find the objects that intersect the box
309    while (oit.hasMoreElements())
310    {
311      MovableObject *mo = oit.getNext();
312
313      // we are only interested in scene entities
314      if (mo->getMovableType() != "Entity")
315        continue;
316                       
317      // get the bounding box of the objects
318      AxisAlignedBox bbox = mo->getWorldBoundingBox();
319                       
320      // test for intersection (note: function provided of preprocessor)
321      if (Overlap(nodeBox, OgreTypeConverter::ConvertFromOgre(bbox)))
322      {
323        objects.push_back(static_cast<Entity *>(mo));
324      }
325    }
326  }
327}
328\end{verbatim}
329
330Note that the implementation of this function is maybe the one that differs the most
331for another engine, as it is highly depending on the particular engine design.
332For the Ogre3D implementation, we use a two stage approach. First we find the intersecting scene nodes.
333We apply a search function that is optimized for this engine.
334In the Ogre3D case, this is the function {\em findNodesIn}.
335The engine is responsible to provide a function for fast geometric search in the scene,
336in order to quickly find the objects intersecting the bounding box of a PVS entry.
337A spatial data structure like Octree or Kd tree is very useful in this regard.
338Second we traverse through the list of entities attached to the scene node. The intersection
339test is then applied for each indiviual bounding box.
340
341\section{View Cells Usage}
342\label{sec:usage}
343
344By now the view cells should be accessible within the target engine. This happens through
345the view cells manager. In order to query the current view cell, use the following code.
346
347\begin{verbatim}
348ViewCell *currentViewCell = viewCellsManager->GetViewCell(viewPoint);
349
350\end{verbatim}
351
352where {\em viewPoint} contains the current location of the player. It must be of type
353{\em GtpVisibilityPreprocessor::Vector3}. In order to traverse the PVS of this view cell, we
354apply a PVS iterator, like in the following example.
355For the implementation in another engine, { \em Entity} from Ogre3D must be replaced by the
356target engine entities.
357
358\begin{verbatim}
359GtpVisibilityPreprocessor::ObjectPvsIterator pit =
360  currentViewCell->GetPvs().GetIterator();
361                       
362while (pit.HasMoreEntries())
363{               
364  GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
365  GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
366
367  EngineIntersectable *oi = static_cast<EngineIntersectable *>(obj);
368  EntityContainer *entries = oi->GetItem();
369 
370  EntityContainer::const_iterator eit, eit_end = entries->end();
371
372  for (eit = entries->begin(); eit != eit_end; ++ eit)
373  {
374    Entity *ent = *eit;
375                   
376    // do something, e.g., set objects visible
377  }     
378}
379
380\end{verbatim}
381
Note: See TracBrowser for help on using the repository browser.