CMS 3D CMS Logo

VisG4VisSceneHandler.h

Go to the documentation of this file.
00001 #ifndef VIS_G4_CORE_VIS_G4_VIS_SCENE_HANDLER_H
00002 # define VIS_G4_CORE_VIS_G4_VIS_SCENE_HANDLER_H
00003 
00004 //<<<<<< INCLUDES                                                       >>>>>>
00005 
00006 # include "VisGeant4/VisG4Core/interface/config.h"
00007 # include <G4VGraphicsScene.hh>
00008 # include <G4ViewParameters.hh>
00009 # include <G4VisExtent.hh>
00010 # include <G4Polymarker.hh>
00011 # include <G4VMarker.hh>
00012 # include <G4Material.hh>
00013 # include <stack>
00014 # include <map>
00015 
00016 //<<<<<< PUBLIC DEFINES                                                 >>>>>>
00017 //<<<<<< PUBLIC CONSTANTS                                               >>>>>>
00018 //<<<<<< PUBLIC TYPES                                                   >>>>>>
00019 
00020 class VisG4VisSystem;
00021 class VisG4Path;
00022 class G4Visible;
00023 class G4VisAttributes;
00024 class SoSeparator;
00025 class SoNode;
00026 class SoGroup;
00027 class SoDrawStyle;
00028 class SoResetTransform;
00029 class SoMarkerSet;
00030 class SoMaterial;
00031 class SoShape;
00032 class SbVec3f;
00033 
00034 //<<<<<< PUBLIC VARIABLES                                               >>>>>>
00035 //<<<<<< PUBLIC FUNCTIONS                                               >>>>>>
00036 //<<<<<< CLASS DECLARATIONS                                             >>>>>>
00037 
00038 /* A quick introduction to Geant 4 volumes
00039   
00040    A LOGICAL VOLUME has a SOLID (which could be a complex object, such
00041    as a boolean solid).  The logical volume also has a number of
00042    PHYSICAL daughter VOLUMEs, each of which has positions relative to
00043    the mother a logical volume.  A single logical volume can be placed
00044    several times via several physical volumes (see pictures below).
00045    Normally all daughters of a logical volume are replicated in all
00046    copies of that logical volume, but as an exception a physical
00047    daughter may also have a PHYSICAL MOTHER, meaning that the daughter
00048    is a daughter of its logical mother only when the logical mother is
00049    being positioned by the given physical mother.  (In other words, a
00050    daughter may appear in only one of the copies of its mother.)
00051    Finally, a physical daughter volume may be REPLICATED, resulting in
00052    multiple copies of its logical volume in several positions, or
00053    PARAMETRISED, resulting in a number of copies of the logical volume
00054    in arbitrary transforms and with arbitrary solids.  */
00055 
00056 /* This is essentially a rewrite of the G4 visualisation framework.
00057    The principal reason for this is that as of G4 version 4.3.2, the
00058    G4 visualisation framework is unsuitable for interactive use, for
00059    two major reasons.
00060 
00061    Firstly, the framework does not provide enough information about
00062    the processing of the volumes to allow the scene handler to map the
00063    representations it is creating to the original volume tree (it does
00064    provide information about the volumes it is processing, but not in
00065    a manner that allows the scene graph tree to be constructed).  As a
00066    consequence, picking is not possible.  It also makes it painful to
00067    try to reuse the representations like G4 does with logical volumes
00068    (but see below why we don't want to do this anyway).  This same
00069    issue applies also to the event content (hits and trajectories).
00070 
00071    Secondly, the G4 framework has not been designed for incremental
00072    rendering.  We need to allow users to choose which parts of the
00073    detector and event are to be visualised, and with what parameters;
00074    each change of settings ought to allow for immediate change of the
00075    representation.  With the existing support in G4 it is not easy to
00076    (re)process only a particular volume without disturbing the rest of
00077    the existing scene graph.
00078 
00079    Therefore we have rewritten parts of the G4 visualisation framework
00080    in a way that matches our needs.  */
00081 
00082 // FIXME: can't use G4 visualisation because the stuff below is far
00083 // too complicated to get to work reliably, and even then we can't do
00084 // things incrementally/interactively...
00085 
00086 /* Try to determine what is going on: reuse nodes for a logical volume
00087    if possible, and build a scene graph for the nodes.  For reuse,
00088    reposition the same solid representation several times (just as G4
00089    does with logical volumes).  It is safe to not get the replication
00090    completely right, we'll just end up doing more work.  However, the
00091    scene graph we do want to get right -- it is our primary output!
00092   
00093    We need to distinguish between two situations: 1) we are still
00094    building the solid representation for the logical volume and
00095    `AddThis' should append to the current definition, and 2) the
00096    logical volume solid is complete and we should remember the new
00097    positioning for it (new path, replica, ...) but ignore calls to
00098    `AddThis'.  For the latter case we need to be careful with
00099    boundaries so that we know when we should come out of the sharing
00100    mode (FIXME: just set CurtailDescent() to avoid processing the
00101    children!).
00102   
00103    This is not simple to achieve -- G4 visualisation architecture only
00104    gives us limited information of what is going on.  What we have is
00105    this: fpCurrentPV points to the current physical volume,
00106    fpCurrentLV to its logical volume, and PreAddThis, AddThis and
00107    PostAddThis are called for each solid in the logical volume.
00108    [FIXME: This ignores primitives drawn without solids, as
00109    G4VisManager::Draw via Begin/Add/EndPrimitives to draw event
00110    content (tracks and hits, with fReadyForTransients == true?), and
00111    stuff such as axes and text annotations.  Do we prefer to do these
00112    independent of G4 -- do we want to support full visualisation or
00113    only ``useful'' parts of it?]
00114   
00115    This method may be called several times in order to build the solid
00116    representation (without wrapping the calls in any way),
00117    unfortunately we cannot rely on recognising the last call to
00118    PostAddThis; this can happen for example with boolean solids.
00119    Replication has a similar issue: we are not being told when the
00120    logical volume of one replica ends and the next one begins; all we
00121    know is that we are still within the same physical/logical volume
00122    pair.  On the other hand, a logical volume may be repeated several
00123    times (via several physical volume paths).
00124   
00125    To deal with the above, we keep track of changes to the current
00126    physical volume.  We know a physical volume's relationship to its
00127    mother is unique: it is a child of any logical mother only once (it
00128    may appear several times during the processing as the logical
00129    mother volume may be repeated several times).  We also know that
00130    the solid of the logical mother is described fully before any of
00131    its daughters are described.  Therefore, we compare the previous
00132    fpCurrentPV with the current one.  If they are different, the
00133    previous solid has become complete and we've gone somewhere else in
00134    the tree; if we then re-encounter the logical volume, we should
00135    just reuse the old definition with a different transformation (and
00136    tell the processing to ignore the rest of the tree).  If they are
00137    the same, we are encountering one of the following cases: 1) we are
00138    being fed the solids of a composite solid and get first the
00139    constituents and then whole complex solid, and `AddThis' should
00140    append to the current representation; 2) we are being fed a
00141    replicated physical volume whose logical volume has no daughters,
00142    and we should reuse the existing solid representation for the
00143    logical volume (the solid may follow the previous case!); 3) we are
00144    being fed a parametrised physical volume whose logical volume has
00145    no daughters, but the solid changes from one replica to another
00146    (and may follow the first case!).  (NB: Not all combinations of
00147    parametrised volumes, solids and daughters are currently allowed,
00148    however the last case above already presents us one of the more
00149    difficult situations.)
00150   
00151    Note that a replicated and/or parametrised physical volume can
00152    point to a logical volume with daughters.  In that case the logical
00153    volume will be described in full for each replica, so we will see
00154    the current physical volume change; that is ok, we will
00155    automatically know to reuse the representations with new
00156    transformations.  (FIXME: For a parametrised physical volume we
00157    assume that the solids are not changing if the logical volume has
00158    daughters.  G4 does not seem to support parametrisations with
00159    daughters and varying solids anyway.)
00160   
00161    The primary problem we tackle is the building of scene graph once
00162    we've detected which physical volume owns the nodes.  Here we rely
00163    on the knowledge that the mother is always processed before its
00164    daughters.  There is however a twist: the mother may be invisible
00165    and the daughters (perhaps several levels down) visible -- and we
00166    will not get invoked for the intermediate visible mothers.
00167   
00168    If `fpCurrentPV' has changed, we discover exactly where it should
00169    be in the scene graph; we assume the client wants results organised
00170    by the volume tree.  We also know that {FIXME].
00171   
00172    For now, we do nothing about replicated/parametrised physical
00173    volumes -- we do not have enough information to reuse the solid
00174    representations.  We simply lump all the replicas together as the
00175    representation of the physical volume.
00176   
00177   
00178    [FIXME: this breaks with voxelisation?] [FIXME: what about
00179    end-of-event models (hits, trajectories) and axes?
00180   
00181    [FIXME: currently (G4.3.2) visualises physical daughters that have
00182    physical mothers wrong: it always renders them.  If corrected,
00183    would it change the logic here?]
00184   
00185    (FIXME: do we detect the stacking order correctly?  I.e. when to
00186    start and *stop* ignoring AddThis, once we've decided that we are
00187    ignoring a replica/already represented volume?)
00188 
00189 
00190    ------------------------------------------------------------
00191    ASCII art diagram for a scenario that matters (sharing):
00192   
00193    | LV 1 | -> / S 1 /
00194       |
00195       +- ( PV 1.1 ) --+> | LV 2 | -> / S 2 /
00196       +- ( PV 1.2 ) -'       |                  
00197                              +- ( PV 2.1 ) -> | LV 3 | -> / S 3 /
00198   
00199    Processing order (note the indentantation is not explicit in
00200    the calls we get in any way!):
00201       < PV 0.1 / LV 1 / S1 >
00202         < PV 1.1 / LV 2 / S2 >
00203           < PV 2.1 / LV 3 / S3 >
00204         < PV 1.2 / LV 2 / S2 >
00205           < PV 2.1 / LV 3 / S3 >
00206   
00207    DIAGNOSIS: *detectable*; note the change of PV and close the
00208    current representation when that happens.
00209   
00210 
00211    ------------------------------------------------------------
00212    ASCII art diagram for a scenario that matters (csg replication):
00213   
00214    | LV 1 | -> / S 1 /
00215       |
00216       +- ( PV 1.1 ) -(2x)-> | LV 2 | -> / S 2 / +-> / S 2.1 /
00217                                                 +-> / S 2.2 /
00218    Processing order:
00219       < PV 0.1 / LV 1 / S1 >
00220         < PV 1.1 / LV 2 / S2.1 >
00221         < PV 1.1 / LV 2 / S2.2 >
00222         < PV 1.1 / LV 2 / S2 >
00223         < PV 1.1 / LV 2 / S2.1 >
00224         < PV 1.1 / LV 2 / S2.2 >
00225         < PV 1.1 / LV 2 / S2 >
00226   
00227    DIAGNOSIS: *detectable*; note the call with the same solid as
00228    pointed to by LV (S2) to close the current replica rep.
00229    (FIXME: fragile -- what if the code changes!?)
00230   
00231 
00232    ------------------------------------------------------------
00233    ASCII art diagram for a scenario that matters (parametrisation):
00234   
00235    | LV 1 | -> / S 1 /
00236       |
00237       +- ( PV 1.1 ) -(2x)-> | LV 2 | -> / S 2 /
00238   
00239    Processing order (Sn, Sm CSG solids generated by parametrisation):
00240       < PV 0.1 / LV 1 / S1 >
00241         < PV 1.1 / LV 2 / Sn.1 >
00242         < PV 1.1 / LV 2 / Sn.2 >
00243         < PV 1.1 / LV 2 / Sn >
00244         < PV 1.1 / LV 2 / Sm.1 >
00245         < PV 1.1 / LV 2 / Sm.2 >
00246         < PV 1.1 / LV 2 / Sm >
00247   
00248    DIAGNOSIS: *undetectable*; merge all replicas together as the
00249    representation of the PV (if Sn == Sm == S2, this reduces to
00250    the previous case and is detectable).
00251   
00252    ------------------------------------------------------------
00253    FIXME: Can we prevent (or not support) the use of
00254    G4LogicalVolumeModel that causes the solid split?  */
00255 
00256 // G4VPhysicalVolumeModel and G4VSceneHandler maintain two useful pointers:
00257 // `fpCurrentPV' and `fpCurrentLV' (and `fpCurrentDepth'): the current
00258 // physical and logical volume, respectively.  We use these to map the
00259 // drawn primitives to the original volumes, and from there, the twig
00260 // representables.  Once the view has been drawn, clients can query
00261 // the map we've built.  (FIXME: Also use reuse replicated solids.)
00262 
00263 // FIXME: Abuse G4VSceneHandler to grab solid representations.
00264 
00265 // Note on the appearance and placement handling of primitives:
00266 //
00267 // Primitives may both be created from shape simplification and added
00268 // on their own right.  We ignore primitive appearance and assume the
00269 // caller will invoke AddMaterial() and AddStyle() as appropriate --
00270 // if the primitive is a result of shape simplification, this will
00271 // have happened; if the primitive is an object of its own, then the
00272 // caller must arrange for the suitable calls.  On the contrary, we do
00273 // translate to the primitive position: we assume the caller has made
00274 // a compatible invocation to AddTransform() (= no call for globally
00275 // positioned primitives, and when one has already been added for a
00276 // shape, then its primitives don't get an extra one).
00277 
00278 class VIS_G4_CORE_API VisG4VisSceneHandler : public G4VGraphicsScene
00279 {
00280 public:
00281     typedef G4ViewParameters::RepStyle          RepStyle;
00282     typedef G4ViewParameters::DrawingStyle      DrawStyle;
00283 
00284     // implicit copy constructor
00285     // implicit destructor
00286     // implicit assignment operator
00287 
00288     static VisG4VisSceneHandler *instance (void);
00289 
00290     // Various settings
00291     virtual void        defineFallback  (RepStyle style);
00292     virtual void        defineBounds    (G4VisExtent bbox);
00293     virtual void        defineNoOfSides (int sides);
00294 
00295     // Cache management
00296     virtual void        enableCache     (bool enabled);
00297     virtual void        clearCache      (void);
00298 
00299     // Delimiting objects.  Wrap various add*() and Add*() calls inside these
00300     virtual void        beginObject     (SoSeparator *node,const void *object);
00301     virtual void        endObject       (void);
00302 
00303     // Drawing attributes handling
00304     virtual void        addStyle        (const G4VisAttributes *from);
00305     virtual void        addStyle        (DrawStyle style);
00306     virtual void        addMaterial     (SoMaterial *mat);
00307     virtual void        addTransform    (const G4Transform3D &by);
00308 
00309     // Solid handling
00310     virtual void        AddSolid        (const G4Box       &solid);
00311     virtual void        AddSolid        (const G4Cons      &solid);
00312     virtual void        AddSolid        (const G4Tubs      &solid);
00313     virtual void        AddSolid        (const G4Trd       &solid);
00314     virtual void        AddSolid        (const G4Trap      &solid);
00315     virtual void        AddSolid        (const G4Sphere    &solid);
00316     virtual void        AddSolid        (const G4Para      &solid);
00317     virtual void        AddSolid        (const G4Torus     &solid);
00318     virtual void        AddSolid        (const G4Polycone  &solid);
00319     virtual void        AddSolid        (const G4Polyhedra &solid);
00320     virtual void        AddSolid        (const G4VSolid    &solid);
00321     virtual void        AddCompound     (const G4VTrajectory &trajectory);
00322     virtual void        AddCompound     (const G4VHit      &hit);
00323     
00324     // Solid expansion and primitives
00325     virtual void        AddPrimitive    (const G4Polyline   &object);
00326     virtual void        AddPrimitive    (const G4Scale      &object);
00327     virtual void        AddPrimitive    (const G4Text       &object);
00328     virtual void        AddPrimitive    (const G4Circle     &object);
00329     virtual void        AddPrimitive    (const G4Square     &object);
00330     virtual void        AddPrimitive    (const G4Polymarker &object);
00331     virtual void        AddPrimitive    (const G4Polyhedron &object);
00332     virtual void        AddPrimitive    (const G4NURBS      &object);
00333 
00334 private:
00335     typedef std::map<const void *, SoGroup *>   NodeCache;
00336     typedef std::map<const G4Material *, SoMaterial *>  MaterialCache;
00337     enum MarkerSizeType { world, screen };
00338 
00339     VisG4VisSceneHandler (void);
00340     virtual ~VisG4VisSceneHandler (void) {};
00341     
00342     void                addTranslation  (SoSeparator *to, const G4Point3D &center);
00343     void                addTranslation  (SoSeparator *to, SbVec3f center);
00344 
00345     void                RequestPrimitives (const G4VSolid &solid);
00346     double              GetMarkerSize   (const G4VMarker &mark);
00347     double              GetMarkerSize   (const G4VMarker &mark,
00348                                          MarkerSizeType &type);
00349     SoMarkerSet *       makeScreenMarker (G4Polymarker::MarkerType type,
00350                                           G4VMarker::FillStyle fill,
00351                                           double size);
00352     SoShape *           makeWorldMarker  (G4Polymarker::MarkerType type,
00353                                           double size);
00354     
00355     DrawStyle           GetDrawingStyle (const G4Visible &);
00356     DrawStyle           GetDrawingStyle (const G4VisAttributes *);
00357     // G4double GetMarkerDiameter (== Size), ...Radius (== Size/2)
00358 
00359     // G4Colour GetColour (const G4Visible &);
00360     // G4Colour GetTextColour (const G4Text &);
00361 
00362     void                cacheBegin (const void *object);
00363     bool                cached (void);
00364     void                cache (SoNode *node);
00365     void                cacheEnd (void);
00366 
00367     SoSeparator         *m_node;
00368 
00369     NodeCache           m_shapeCache;
00370     bool                m_caching;
00371     bool                m_cached;
00372     SoGroup             *m_cacheNodes;
00373     int                 m_cacheIndex;
00374 
00375     SoResetTransform    *m_reset;
00376     SoDrawStyle         *m_lines;
00377     SoDrawStyle         *m_solid;
00378     MaterialCache       m_materialCache;
00379 
00380     RepStyle            m_fallback;
00381     G4VisExtent         m_bbox;
00382     int                 m_sides;
00383     double              m_fontSize;
00384 
00385     // Unsupported but required to be implemented to keep G4 happy.
00386     // Never use these, use BeginObject() end EndObject() instead.
00387     // Calling these will cause immediate termination.
00388     virtual void        BeginPrimitives (const G4Transform3D &transform);
00389     virtual void        PreAddSolid     (const G4Transform3D &transform,
00390                                          const G4VisAttributes &attributes);
00391     virtual void        PostAddSolid    (void);
00392     virtual void        EndPrimitives   (void);
00393     virtual void BeginPrimitives2D () {}
00394     virtual void EndPrimitives2D (){}
00395 };
00396 
00397 //<<<<<< INLINE PUBLIC FUNCTIONS                                        >>>>>>
00398 //<<<<<< INLINE MEMBER FUNCTIONS                                        >>>>>>
00399 
00400 #endif // VIS_G4_CORE_VIS_G4_VIS_SCENE_HANDLER_H

Generated on Tue Jun 9 17:50:06 2009 for CMSSW by  doxygen 1.5.4