source: trunk/documents/UserDoc/UsersGuides/ForToolkitDeveloper/latex/GuideToExtendFunctionality/Visualization/visualization.tex @ 1332

Last change on this file since 1332 was 1208, checked in by garnier, 15 years ago

CVS update

File size: 25.4 KB
Line 
1\newcommand{\Gfour}{{\sc Geant4}\xspace}
2\newcommand{\GI}{Graphics Interface\xspace}
3\newcommand{\GVS}{\Gfour Visualisation System\xspace}
4\newcommand{\GVM}{\Gfour Visualisation Manager\xspace}
5\newcommand{\gd}{graphics driver\xspace}
6\newcommand{\gds}{graphics drivers\xspace}
7\newcommand{\gs}{graphics system\xspace}
8\newcommand{\gss}{graphics systems\xspace}
9\newcommand{\vs}{visualisation system\xspace}
10\newcommand{\vm}{visualisation manager\xspace}
11\newcommand{\UGA}{User Guide for Application Developers\xspace}
12\newcommand{\UGT}{User Guide for Toolkit Developers\xspace}
13\newcommand{\SRM}{Software Reference Manual\xspace}
14
15\chapter{Visualisation}
16\label{ExtendChapVis}
17
18This Chapter is intended to be read after Chapter \ref{OOChapVis} on
19Visualisation object oriented design in Part II.  Many of the concepts
20used here are defined there, and it strongly recommended that a writer
21of a new visualisation driver or trajectory drawer reads Chapter
22\ref{OOChapVis} first.  The class structure described there is
23summarised in the Figure \ref{VisClassDiagram}.
24
25\begin{figure}
26\begin{center}
27\includegraphics[width=\linewidth]{GuideToExtendFunctionality/Visualization/visClassDiagram.eps}
28\caption{Geant Visualisation System Class Diagram}
29\label{VisClassDiagram}
30\end{center}
31\end{figure}
32
33\section{Creating a new \gd}
34
35To create a new \gd for {\sc Geant4}, it is necessary to implement a
36new set of three classes derived from the three base classes, {\tt
37G4VGraphicsSystem}, {\tt G4VSceneHandler} and {\tt G4VViewer}.
38
39\subsection{A useful place to start}
40
41A skeleton set of classes is included in the code distribution in the
42visualisation category under subdirectory {\tt visualisation/XXX} (but
43they are not default-registered graphics systems\footnote{To do this,
44simply instantiate and register, for example: {\tt
45visManager->\-RegisterGraphicsSystem(new G4XXX)} before {\tt
46visManager->Initialise()}.}).  There are several sets of classes,
47described in more detail below.  A recommended approach is to copy the
48files that best match your \gs to a new subdirectory with a name that
49suits your \gs.  Then
50\begin{enumerate}
51\item Change the name of the files (change the code -- {\tt XXX} or
52{\tt XXXFile}, etc., as chosen -- to something that suits your \gs).
53\item Change {\tt XXX} similarly in all files.
54\item Change {\tt XXX} similarly in {\tt name := G4XXX} in {\tt GNUmakefile}.
55\item Add your new subdirectory to {\tt SUBDIRS} and {\tt SUBLIBS} in
56{\tt visualisation/GNUmakefile}.
57\item Look at the code and use it to build your visualisation
58driver. You might also find it useful to look at {\tt ASCIITree} (and
59{\tt VTree}) as an example of a minimal \gd.  Look at
60{\tt FukuiRenderer} as an example of a driver which implements {\tt AddSolid}
61methods for some solids.  Look at {\tt OpenGL} as an example of a driver
62which implements a graphical database (display lists) and the
63machinery to decide when to rebuild.  (OpenGL is complicated by the
64proliferation of combinations of the use or not of display lists for
65three window systems, X-windows, X with motif (interactive), Microsoft
66Windows (Win32), a total of six combinations, and much use is made of
67inheritance to avoid code duplication.)
68\item If it requires external libraries, introduce two new environment
69   variables {\tt G4VIS\_BUILD\_XXX\_DRIVER} and {\tt G4VIS\_USE\_XXX}
70   (where {\tt XXX} is your choice as above) and make the modifications to:
71\begin{itemize}
72\item     {\tt source/visualization/management/include/G4VisExecutive.icc}
73\item     {\tt config/G4VIS\_BUILD.gmk}
74\item     {\tt config/G4VIS\_USE.gmk}
75\end{itemize}
76\end{enumerate}
77
78\subsubsection{Graphics driver templates in the {\tt XXX} sub-category}
79\label{XXXsub}
80
81You may use the following templates to help you get started writing a
82\gd.  (The word ``template'' is used in the ordinary sense of the
83word; they are not C++ templates.)
84
85\begin{itemize}
86
87\item{\tt G4XXX, G4XXXSceneHandler, G4XXXViewer} Templates for the
88simplest possible \gd. These would be suitable for an ``immediate''
89driver, i.e., one which renders each object immediately to a screen.
90Of course, if the view needs re-drawing, as, for example, after a
91change of viewpoint, the viewer requests a re-issue of drawn
92objects.
93
94\item{\tt G4XXXFile, G4XXXFileSceneHandler, G4XXXFileViewer} Templates
95for a file-writing graphics driver.  The particular features are:
96delayed opening of the file on receipt of the first item; rewinding
97file on ClearView (to simulate the clearing of views and prevent the
98duplication of material in the file); closing of the file on ShowView,
99which may also trigger the launch of a browser.  There are various
100degrees of sophistication in, for example, the allocation of filenames
101-- see {\tt FukuiRenderer} or {\tt HepRepFile}.
102
103These templates also show the use of a specific {\tt AddSolid} function
104whereby the specific parameters, for example, the dimensions of a {\tt
105G4Box}, can be accessed.
106
107\item{\tt G4XXXStored, G4XXXStoredSceneHandler, G4XXXStoredViewer}
108Templates for a graphics driver with a store/database.  The advantage
109of a store is that the view can be refreshed, for example, from a
110different viewpoint, without a need to recompute.  It is up to the
111viewer to decide when a re-computation is necessary.  They also show how
112to distinguish between permanent and transient objects -- see also
113Section \ref{Transients}.
114
115\item{\tt G4XXXSG, G4XXXSGSceneHandler, G4XXXSGViewer} Templates for a
116sophisticated \gd with a scene graph.  The scene graph, following Open
117Inventor parlance, is a tree of objects that dictates the order in
118which the objects are rendered.  It obviously lends itself to the
119rendering of the \Gfour geometry hierarchy.  For example, the Open
120Inventor driver draws only the top level volumes unless made invisible
121by picking.  Thus the user can unwrap a branch of the geometry level
122by level. This has performance benefits and gives the user significant
123and useful control over the view.  These classes show how to make a
124scene graph of {\em drawn} volumes, i.e., the set of volumes that have
125not been culled.  (Normally, volumes marked invisible are culled,
126i.e., not drawn.  Also, the user may wish to limit the number of drawn
127volumes for performance reasons.)  The drivers also have to process
128non-geometry items and distinguish between transient and permanent
129objects as above.
130\end{itemize}
131
132\subsection{Important Command Actions}
133\label{Actions}
134
135To help understand how the \GVS works, here are a few important
136function invocation sequences that follow user commands.  For an
137explanation of the commands themselves, see command guidance or the
138Control section of the Application Developers Guide.  For a
139fuller explanation of the functions, see appropriate base class head
140files or Software Reference Manual.
141
142\begin{itemize}
143
144\item{\tt /vis/viewer/clear}
145\begin{verbatim}
146    viewer->ClearView();   // Clears buffer or rewinds file.
147    viewer->FinishView();  // Swaps buffer (double buffer systems).
148\end{verbatim}
149
150\item{\tt /vis/viewer/flush}
151\begin{verbatim}
152    /vis/viewer/refresh
153    /vis/viewer/update
154\end{verbatim}
155
156\item{\tt /vis/viewer/rebuild}
157\begin{verbatim}
158    viewer->SetNeedKernelVisit(true);
159\end{verbatim}
160
161\item{\tt /vis/viewer/refresh} If the view is ``auto-refresh'', this
162command is also invoked after {\tt /vis/viewer/create}, {\tt
163/vis/viewer/rebuild} or a change of view parameters ({\tt
164/vis/viewer/set/}..., etc.).
165\begin{verbatim}
166    viewer->SetView();    // Sets camera position, etc.
167    viewer->ClearView();  // Clears buffer or rewinds file.
168    viewer->DrawView();   // Draws to screen or writes to
169                          // file/socket.
170\end{verbatim}
171
172\item{\tt /vis/viewer/update}
173\begin{verbatim}
174    viewer->ShowView();   // Activates interactive windows or
175                          // closes file and/or triggers
176                          // post-processing.
177\end{verbatim}
178
179\item{\tt /vis/scene/notifyHandlers} For each viewer of the current
180scene, the equivalent of
181\begin{verbatim}
182    /vis/viewer/refresh
183\end{verbatim}
184If ``flush'' is specified on the command line, the equivalent of
185\begin{verbatim}
186    /vis/viewer/update
187\end{verbatim}
188{\tt /vis/scene/notifyHandlers} is also invoked after a change
189of scene ({\tt /vis/scene/add/}..., etc.).
190
191\end{itemize}
192
193\subsection{What happens in {\tt DrawView}?}
194\label{DrawView}
195
196This depends on the viewer.  Those with their own graphical database,
197for example, OpenGL's display lists or Open Inventor's scene graph, do
198not need to re-traverse the scene unless there has been a significant
199change of view parameters.  For example, a mere change of viewpoint
200requires only a change of model-view matrix whilst a change of
201rendering mode from wireframe to surface might require a rebuild of
202the graphical database.  A rebuild of the run-duration (persistent)
203objects in the scene is called a ``kernel visit''; the viewer prints
204``Traversing scene data...''.
205
206Note that end-of-event (transient) objects are only rebuilt at the end
207of an event or run, under control of the visualisation manager.  Smart
208scene handlers keep them in separate display lists so that they can be
209rebuilt separately from the run-duration objects - see Section
210\ref{Transients}.
211
212\begin{itemize}
213
214\item{\bf Integrated viewers with no graphical database} For example,
215G4OpenGLImmediateXViewer::DrawView().
216\begin{verbatim}
217  NeedKernelVisit();  // Always need to visit G4 kernel.
218  ProcessView();
219  FinishView();
220\end{verbatim}
221
222\item{\bf Integrated viewers with graphical database} For example,\\
223G4OpenGLStoredXViewer::DrawView().
224\begin{verbatim}
225  KernelVisitDecision();  // Private function containing...
226    if significant change of view parameters...
227      NeedKernelVisit();
228  ProcessView();
229  FinishView();
230\end{verbatim}
231
232\item{\bf File-writing viewers} For example, G4DAWNFILEViewer::DrawView().
233\begin{verbatim}
234  NeedKernelVisit();
235  ProcessView();
236\end{verbatim}
237
238Note that viewers needing to invoke {\tt FinishView} must do it in
239{\tt DrawView}.
240
241\end{itemize}
242
243\subsection{What happens in {\tt ProcessView}?}
244
245{\tt ProcessView} is inherited from {\tt G4VViewer}:
246
247\begin{verbatim}
248void G4VViewer::ProcessView() {
249  // If ClearStore has been requested, e.g., if the scene has changed,
250  // of if the concrete viewer has decided that it necessary to visit
251  // the kernel, perhaps because the view parameters have changed
252  // drastically (this should be done in the concrete viewer's
253  // DrawView)...
254  if (fNeedKernelVisit) {
255    fSceneHandler.ProcessScene(*this);
256    fNeedKernelVisit = false;
257  }
258}
259\end{verbatim}
260
261\subsection{What happens in {\tt ProcessScene}?}
262\label{ProcessScene}
263
264ProcessScene is inherited from {\tt G4VSceneHandler}.  It causes a
265traversal of the run-duration models in the scene.  For drivers with
266graphical databases, it causes a rebuild ({\tt ClearStore}).  Then for
267the run-duration models:
268\begin{verbatim}
269    fReadyForTransients = false;
270    BeginModeling();
271    for each run-duration model...
272      pModel -> DescribeYourselfTo(*this);
273    EndModeling();
274    fReadyForTransients = true;
275\end{verbatim}
276(A second pass is made on request -- see {\tt
277G4VSceneHandler::ProcessScene}.)  The use of {\tt fReadyForTransients}
278is described in Section \ref{Transients}.
279
280What happens then depends on the type of model:
281
282\begin{itemize}
283
284\item{\tt G4AxesModel} {\tt G4AxesModel::DescribeYourselfTo} simply calls
285sceneHandler.AddPrimitive methods directly.
286\begin{verbatim}
287  sceneHandler.BeginPrimitives();
288  sceneHandler.AddPrimitive(x_axis);  // etc.
289  sceneHandler.EndPrimitives();
290\end{verbatim}
291
292Most other models are like this, except for the following...
293
294\item{\tt G4PhysicalVolumeModel} The geometry is descended
295  recursively, culling policy is enacted, and for each accepted (and
296  possibly, clipped) solid:
297\begin{verbatim}
298    sceneHandler.PreAddSolid(theAT, *pVisAttribs);
299    pSol->DescribeYourselfTo(sceneHandler);
300    // For example, if pSol points to a G4Box...
301    |-->G4Box::DescribeYourselfTo(G4VGraphicsScene& scene){
302         scene.AddSolid(*this);
303        }
304    sceneHandler.PostAddSolid();
305\end{verbatim}
306
307The scene handler may implement the virtual function {\tt
308AddSolid(const G4Box\&)}, or inherit:
309\begin{verbatim}
310void G4VSceneHandler::AddSolid(const G4Box& box) {
311  RequestPrimitives(box);
312}
313\end{verbatim}
314
315{\tt RequestPrimitives} converts the solid into primitives ({\tt G4Polyhedron})
316and invokes {\tt AddPrimitive}:
317\begin{verbatim}
318    BeginPrimitives(*fpObjectTransformation);
319    pPolyhedron = solid.GetPolyhedron();
320    AddPrimitive(*pPolyhedron);
321    EndPrimitives();
322\end{verbatim}
323
324The resulting default sequence for a {\tt G4PhysicalVolumeModel} is shown in
325Figure \ref{FigPVModel}.
326\begin{figure}[t]
327\begin{boxedverbatim}
328    DrawView();
329    |-->ProcessView();
330        |-->ProcessScene();
331            |-->BeginModeling();
332            |-->pModel -> DescribeYourselfTo(*this);
333            |   |-->sceneHandler.PreAddSolid(theAT, *pVisAttribs);
334            |   |-->pSol->DescribeYourselfTo(sceneHandler);
335            |   |   |-->sceneHandler.AddSolid(*this);
336            |   |       |-->RequestPrimitives(solid);
337            |   |           |-->BeginPrimitives (*fpObjectTransformation);
338            |   |           |-->pPolyhedron = solid.GetPolyhedron();
339            |   |           |-->AddPrimitive(*pPolyhedron);
340            |   |           |-->EndPrimitives();
341            |   |-->sceneHandler.PostAddSolid();
342            |-->EndModeling();
343\end{boxedverbatim}
344\caption{The default sequence for a {\tt G4PhysicalVolumeModel}}
345\label{FigPVModel}
346\end{figure}
347
348Note the sequence of calls at the core:
349\begin{verbatim}
350  sceneHandler.PreAddSolid(theAT, *pVisAttribs);
351  pSol->DescribeYourselfTo(sceneHandler);
352  |-->sceneHandler.AddSolid(*this);
353     |-->RequestPrimitives(solid);
354        |-->BeginPrimitives (*fpObjectTransformation);
355        |-->pPolyhedron = solid.GetPolyhedron();
356        |-->AddPrimitive(*pPolyhedron);
357        |-->EndPrimitives();
358  sceneHandler.PostAddSolid();
359\end{verbatim}
360is reduced to
361\begin{verbatim}
362  sceneHandler.PreAddSolid(theAT, *pVisAttribs);
363  pSol->DescribeYourselfTo(sceneHandler);
364  |-->sceneHandler.AddSolid(*this);
365  sceneHandler.PostAddSolid();
366\end{verbatim}
367if the scene handler implements its own {\tt AddSolid}.  Moreover, the sequence
368\begin{verbatim}
369  BeginPrimitives (*fpObjectTransformation);
370  AddPrimitive(*pPolyhedron);
371  EndPrimitives();
372\end{verbatim}
373can be invoked without a prior {\tt PreAddSolid}, etc.  The flag {\tt
374fProcessingSolid} will be false for the last case.  The possibility of
375any or all of these three scenarios occurring, for both permanent and
376transient objects, affects the implementation of a scene handler if
377there is any attempt to build a graphical database.  This is reflected
378in the templates {\tt XXXStored} and {\tt XXXSG} described in Section
379\ref{XXXsub}.  Transients are discussed in Section \ref{Transients}.
380
381\item{\tt G4TrajectoriesModel} At end of event, the trajectory
382container is unpacked and, for each trajectory,
383{\tt sceneHandler.AddCompound} called.  The scene handler may implement this
384virtual function or inherit:
385\begin{verbatim}
386void G4VSceneHandler::AddCompound (const G4VTrajectory& traj) {
387  traj.DrawTrajectory(((G4TrajectoriesModel*)fpModel)->GetDrawingMode());
388}
389\end{verbatim}
390Similarly, the user may implement {\tt DrawTrajectory} or inherit:
391\begin{verbatim}
392void G4VTrajectory::DrawTrajectory(G4int i_mode) const {
393  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
394  if (0 != pVVisManager) {
395    pVVisManager->DispatchToModel(*this, i_mode);
396  }
397}
398\end{verbatim}
399Thence, the {\tt Draw} method of the current trajectory model is invoked
400(see Section \ref{EnhancedTraj} for details on trajectory models),
401which in turn, invokes {\tt Draw} methods of the visualisation manager.
402The resulting default sequence for a {\tt G4TrajectoriesModel} is shown in
403Figure \ref{FigTrajsModel}.
404\begin{figure}[t]
405\begin{boxedverbatim}
406 DrawView();
407 |-->ProcessView();
408     |-->ProcessScene();
409         |-->BeginModeling();
410         |-->pModel -> DescribeYourselfTo(*this);
411         |   |-->AddCompound(trajectory);
412         |       |-->trajectory.DrawTrajectory(...);
413         |           |-->DispatchToModel(...);
414         |               |-->model->Draw(...);
415         |                   |-->G4VisManager::Draw(...);
416         |                       |-->BeginPrimitives(objectTransform);
417         |                       |-->AddPrimitive(...);
418         |                       |-->EndPrimitives();
419         |-->EndModeling();
420\end{boxedverbatim}
421\caption{The default sequence for a G4TrajectoriesModel}
422\label{FigTrajsModel}
423\end{figure}
424
425\end{itemize}
426
427
428\subsection{Dealing with transient objects}
429\label{Transients}
430
431Any visualisable object not defined in the run-duration part of a
432scene is treated as ``transient''.  This includes trajectories, hits
433or anything drawn by the user through the {\tt G4VVisManager}
434user-level interface (unless as part of a run-duration model
435implementation).  A flag, {\tt fReadyForTransients}, is maintained by
436the scene handler.  In fact, its normal state is {\tt true}, and only
437temporarily, during handling of the run-duration part of the scene, is
438it set to {\tt false} -- see description of ProcessScene, Section
439\ref{ProcessScene}.
440
441If the driver supports a graphical database, it is smart to
442distinguish transient and permanent objects.  In this case, every {\tt
443Add} method of the scene handler must be transient-aware.  In some
444cases, it is enough to open a graphical data base component in {\tt
445BeginPrimitives}, fill it in {\tt AddPrimitive} and close it
446appropriately in {\tt EndPrimitives}.  In others, initialisation is
447done in {\tt BeginModeling} and consolidation in {\tt EndModeling} --
448see {\tt G4OpenGLStoredSceneHandler}.  If any {\tt AddSolid} method is
449implemented, then the graphical data base component should be opened
450in {\tt PreAddSolid}, protecting against double opening, for example,
451\begin{verbatim}
452void G4XXXStoredSceneHandler::BeginPrimitives
453(const G4Transform3D& objectTransformation) {
454  G4VSceneHandler::BeginPrimitives(objectTransformation);
455  // If thread of control has already passed through PreAddSolid,
456  // avoid opening a graphical data base component again.
457  if (!fProcessingSolid) {
458\end{verbatim}
459for other solids.
460
461The reason for this distinction is that at end of run the user
462typically wants to display trajectories on a view of the detector,
463then, at the end of the next event\footnote{There is an option to
464accumulate trajectories across events and runs -- see commands {\tt
465/vis/scene/endOfEventAction} and {\tt /vis/scene/endOfRunAction}.},
466erase the old and see new trajectories.  The \vm messages the scene
467handler with {\tt ClearTransientStore} just before drawing the
468trajectories to achieve this.
469
470If the driver does not have a graphical database or does not
471distinguish between transient and persistent objects, it must emulate
472{\tt ClearTransientStore}.  Typically, it must erase everything, including
473the detector, and re-draw the detector and other run-duration objects,
474ready for the transients to be added.  File-writing drivers must
475rewind the output file.  Typically:
476\begin{verbatim}
477void G4HepRepFileSceneHandler::ClearTransientStore() {
478  G4VSceneHandler::ClearTransientStore();
479  // This is typically called after an update and before drawing hits
480  // of the next event.  To simulate the clearing of "transients"
481  // (hits, etc.) the detector is redrawn...
482  if (fpViewer) {
483    fpViewer -> SetView();
484    fpViewer -> ClearView();
485    fpViewer -> DrawView();
486  }
487}
488\end{verbatim}
489{\tt ClearView} rewinds the output file and {\tt DrawView} re-draws the
490detector, etc.  (For smart drivers, {\tt DrawView} is smart enough to
491know not to redraw the detector, etc., unless the view parameters have
492changed significantly -- see Section \ref{DrawView}.)
493
494
495\subsection{More about scene models}
496
497Scene models conform to the {\tt G4VModel} abstract interface.
498Available models are listed and described there in varying detail.
499Section \ref{ProcessScene} describes their use in some common command
500actions.
501
502In the design of a new model, care should be taken to handle the
503possibility that the {\tt G4ModelingParameters} pointer is zero.
504Currently the only use of the modeling parameters is to communicate
505the culling policy.  Most models, therefore, have no need for modeling
506parameters.
507
508
509\section{Enhanced Trajectory Drawing}
510\label{EnhancedTraj}
511\subsection{Creating a new trajectory model}
512New trajectory models must inherit from G4VTrajectoryModel and
513implement these pure virtual functions:
514
515\begin{verbatim}
516    virtual void Draw(const G4VTrajectory&, G4int i_mode = 0,
517                      const G4bool& visible = true) const = 0;
518    virtual void Print(std::ostream& ostr) const = 0;
519\end{verbatim}
520
521To use the new model directly in compiled code, simply
522register it with the G4VisManager, eg:
523
524\begin{verbatim}
525  G4VisManager* visManager = new G4VisExecutive;
526  visManager->Initialise();
527
528  // Create custom model
529  MyCustomTrajectoryModel* myModel =
530             new MyCustomTrajectoryModel("custom");
531
532  // Configure it if necessary then register with G4VisManager
533  ...
534  visManager->RegisterModel(myModel);
535\end{verbatim}
536
537\subsection{Adding interactive functionality}
538
539Additional classes need to be written if the new model is to
540be created and configured interactively:
541
542\begin{itemize}
543\item {\bf Messenger classes}
544
545 Messengers to configure the model should inherit from
546G4VModelCommand. The concrete trajectory model type should be
547used for the template parameter, eg:
548
549\begin{verbatim}
550  class G4MyCustomModelCommand
551        : public G4VModelCommand<G4TrajectoryDrawByParticleID> {
552  ...
553  };
554
555\end{verbatim}
556 
557A number of general use templated commands are available in
558G4ModelCommandsT.hh.
559
560\item {\bf Factory class}
561
562A factory class responsible for the model and associated messenger
563creation must also be written. The factory should inherit from
564G4VModelFactory. The abstract model type should be used for the
565template parameter, eg:
566\begin{verbatim}
567 class G4TrajectoryDrawByChargeFactory
568   : public G4VModelFactory<G4VTrajectoryModel> {
569  ...
570 };
571\end{verbatim}
572
573The model and associated messengers should be constructed in the Create
574method. Optionally, a context object can also be created, with its own
575associated messengers. For example:
576
577\begin{verbatim}
578ModelAndMessengers
579G4TrajectoryDrawByParticleIDFactory::
580    Create(const G4String& placement, const G4String& name)
581{ 
582  // Create default context and model
583  G4VisTrajContext* context = new G4VisTrajContext("default");
584  G4TrajectoryDrawByParticleID* model =
585              new G4TrajectoryDrawByParticleID(name, context);
586
587  // Create messengers for default context configuration
588  AddContextMsgrs(context, messengers, placement+"/"+name);
589
590 // Create messengers for drawer
591  messengers.push_back(new
592    G4ModelCmdSetStringColour<G4TrajectoryDrawByParticleID>
593                                           (model, placement));
594  messengers.push_back(new
595    G4ModelCmdSetDefaultColour<G4TrajectoryDrawByParticleID>
596                                           (model, placement));
597  messengers.push_back(new
598    G4ModelCmdVerbose<G4TrajectoryDrawByParticleID>
599                                           (model, placement));
600
601  return ModelAndMessengers(model, messengers);
602}
603\end{verbatim}
604
605\end{itemize}
606
607The new factory must then be registered with the visualisation manager.
608This should be done by overriding the G4VisManager::RegisterModelFactory
609method in a subclass. See, for example, the G4VisManager implementation:
610\begin{verbatim}
611G4VisExecutive::RegisterModelFactories()
612{
613   ...
614   RegisterModelFactory(new G4TrajectoryDrawByParticleIDFactory());
615}
616\end{verbatim}
617
618
619\section{Trajectory Filtering}
620\label{TrajFilter}
621\subsection{Creating a new trajectory filter model}
622New trajectory filters must inherit at least from G4VFilter. The
623models supplied with the Geant4 distribution inherit from
624G4SmartFilter, which implements some specialisations on top of
625G4VFilter. The models implement these pure virtual functions:
626
627\begin{verbatim}
628  // Evaluate method implemented in subclass
629  virtual G4bool Evaluate(const T&) = 0;
630
631  // Print subclass configuration
632  virtual void Print(std::ostream& ostr) const = 0;
633\end{verbatim}
634
635To use the new filter model directly in compiled code, simply
636register it with the G4VisManager, eg:
637
638\begin{verbatim}
639  G4VisManager* visManager = new G4VisExecutive;
640  visManager->Initialise();
641
642  // Create custom model
643  MyCustomTrajectoryFilterModel* myModel =
644        new MyCustomTrajectoryFilterModel("custom");
645
646  // Configure it if necessary then register with G4VisManager
647  ...
648  visManager->RegisterModel(myModel);
649\end{verbatim}
650
651\subsection{Adding interactive functionality}
652 
653Additional classes need to be written if the new model is to
654be created and configured interactively. The mechanism is exactly
655the same as that used to create enchanced trajectory drawing
656models and associated messengers. See the filter factories in
657G4TrajectoryFilterFactories for example implementations.
658
659\section{Other Resources}
660The following sections contain various information for extending
661other class functionalities of {\sc Geant4} visualisation:
662\begin{itemize}
663\item User's Guide for Application Developers, Chapter 8 - Visualization
664\item User's Guide for Toolkit Developers, Object-oriented Analysis
665      and Design of {\sc Geant4} Classes, Chapter \ref{OOChapVis} -
666      Visualisation
667\end{itemize}
668
669\section{Status of this chapter}
670
67103.12.05 ``Enhanced Trajectory Drawing'' added by Jane Tinsley.\\
67203.12.05 ``Creating a new visualisation driver'' (from Part II) by John Allison.\\
67309.01.06 ``Creating a new visualisation driver'' considerably expanded by John Allison.\\
67420.06.06 Some sections improved or added from draft vis paper.  John Allison.
Note: See TracBrowser for help on using the repository browser.