TGLClip.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLClip.cxx 33627 2010-05-27 19:19:58Z matevz $
00002 // Author:  Richard Maunder  16/09/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TGLClip.h"
00013 #include "TGLIncludes.h"
00014 #include "TGLRnrCtx.h"
00015 #include "TGLManipSet.h"
00016 
00017 #include "TGLFaceSet.h"
00018 #include "TBuffer3D.h"
00019 #include "TBuffer3DTypes.h"
00020 
00021 namespace
00022 {
00023 
00024 class TGLClipPlaneLogical : public TGLLogicalShape
00025 {
00026 protected:
00027    virtual void DirectDraw(TGLRnrCtx & rnrCtx) const
00028    {
00029       glBegin(rnrCtx.IsDrawPassFilled() ? GL_QUADS : GL_LINE_LOOP);
00030       glNormal3d (0.0, 0.0, 1.0);
00031       glVertex3dv(fBoundingBox[4].CArr());
00032       glVertex3dv(fBoundingBox[7].CArr());
00033       glVertex3dv(fBoundingBox[6].CArr());
00034       glVertex3dv(fBoundingBox[5].CArr());
00035       glEnd();
00036    }
00037 
00038 public:
00039    TGLClipPlaneLogical() : TGLLogicalShape() { fDLCache = kFALSE; }
00040    virtual ~TGLClipPlaneLogical() {}
00041 
00042    void Resize(Double_t ext)
00043    {
00044       fBoundingBox.SetAligned(TGLVertex3(-ext, -ext, 0),
00045                               TGLVertex3( ext,  ext, 0));
00046       UpdateBoundingBoxesOfPhysicals();
00047    }
00048 
00049 };
00050 
00051 
00052 class TGLClipBoxLogical : public TGLLogicalShape
00053 {
00054 protected:
00055    virtual void DirectDraw(TGLRnrCtx & rnrCtx) const
00056    {
00057       glEnable(GL_NORMALIZE);
00058       fBoundingBox.Draw(rnrCtx.IsDrawPassFilled());
00059       glDisable(GL_NORMALIZE);
00060    }
00061 
00062 public:
00063    TGLClipBoxLogical() : TGLLogicalShape() { fDLCache = kFALSE; }
00064    virtual ~TGLClipBoxLogical() {}
00065 
00066    void Resize(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
00067    {
00068       fBoundingBox.SetAligned(lowVertex, highVertex);
00069       UpdateBoundingBoxesOfPhysicals();
00070    }
00071 };
00072 
00073 }
00074 
00075 
00076 //////////////////////////////////////////////////////////////////////////
00077 //                                                                      //
00078 // TGLClip                                                              //
00079 //                                                                      //
00080 // Abstract clipping shape - derives from TGLPhysicalShape              //
00081 // Adds clip mode (inside/outside) and pure virtual method to           //
00082 // approximate shape as set of planes. This plane set is used to perform//
00083 // interactive clipping using OpenGL clip planes.                       //
00084 //////////////////////////////////////////////////////////////////////////
00085 
00086 ClassImp(TGLClip);
00087 
00088 //______________________________________________________________________________
00089 TGLClip::TGLClip(const TGLLogicalShape & logical, const TGLMatrix & transform, const float color[4]) :
00090    TGLPhysicalShape(0, logical, transform, kTRUE, color),
00091    fMode      (kInside),
00092    fTimeStamp (1),
00093    fValid     (kFALSE)
00094 {
00095    // Construct a stand-alone physical clipping object.
00096 
00097    logical.StrongRef(kTRUE);
00098 }
00099 
00100 //______________________________________________________________________________
00101 TGLClip::~TGLClip()
00102 {
00103    // Destroy clip object.
00104 }
00105 
00106 //______________________________________________________________________________
00107 void TGLClip::Setup(const TGLVector3&, const TGLVector3&)
00108 {
00109    // Setup the clipping object with two vectors.
00110    // The interpretation of the two is different for plane and box
00111    // clipping objects.
00112 
00113    Warning("TGLClip::Setup", "Called on base-class -- should be re-implemented in derived class.");
00114    
00115 }
00116 
00117 //______________________________________________________________________________
00118 void TGLClip::Draw(TGLRnrCtx & rnrCtx) const
00119 {
00120    // Draw out clipping object with blending and back + front filling.
00121    // Some clip objects are single face which we want to see both sides of.
00122 
00123    glDepthMask(GL_FALSE);
00124    glEnable(GL_BLEND);
00125    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00126    glDisable(GL_CULL_FACE);
00127    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00128 
00129    TGLPhysicalShape::Draw(rnrCtx);
00130 
00131    glPolygonMode(GL_FRONT, GL_FILL);
00132    glEnable(GL_CULL_FACE);
00133    glDisable(GL_BLEND);
00134    glDepthMask(GL_TRUE);
00135 }
00136 
00137 //////////////////////////////////////////////////////////////////////////
00138 //                                                                      //
00139 // TGLClipPlane                                                         //
00140 //                                                                      //
00141 // Concrete clip plane object. This can be translated in all directions //
00142 // rotated about the Y/Z local axes (the in-plane axes). It cannot be   //
00143 // scaled.                                                              //
00144 //                                                                      //
00145 //////////////////////////////////////////////////////////////////////////
00146 
00147 ClassImp(TGLClipPlane);
00148 
00149 const float TGLClipPlane::fgColor[4] = { 1.0, 0.6, 0.2, 0.5 };
00150 
00151 //______________________________________________________________________________
00152 TGLClipPlane::TGLClipPlane() :
00153    TGLClip(* new TGLClipPlaneLogical, TGLMatrix(), fgColor)
00154 {
00155    // Construct a clip plane object, based on supplied 'plane', with
00156    // initial manipulation pivot at 'center', with drawn extents (in
00157    // local x/y axes) of 'extents'
00158    //
00159    // Plane can have center pivot translated in all directions, and
00160    // rotated round center in X/Y axes , the in-plane axes. It cannot
00161    // be scaled
00162    //
00163    // Note theorectically a plane is of course infinite - however we
00164    // want to draw the object in viewer - so we fake it with a single
00165    // GL face (polygon) - extents defines the width/depth of this -
00166    // should be several times scene extents - see Setup().
00167 
00168    SetManip(EManip(kTranslateAll | kRotateX | kRotateY));
00169 
00170    TGLPlane plane(0.0, -1.0, 0.0, 0.0);
00171    Set(plane);
00172    fValid = kFALSE;
00173 }
00174 
00175 //______________________________________________________________________________
00176 TGLClipPlane::~TGLClipPlane()
00177 {
00178    // Destroy clip plane object
00179 }
00180 
00181 //______________________________________________________________________________
00182 void TGLClipPlane::Setup(const TGLBoundingBox & bbox)
00183 {
00184    // Setup the clip object for scene encompassed by bbox.
00185 
00186    Double_t extents = bbox.Extents().Mag();
00187    TGLClipPlaneLogical* cpl = (TGLClipPlaneLogical*) GetLogical();
00188    cpl->Resize(extents);
00189    if (!fValid) {
00190       SetTransform(TGLMatrix(bbox.Center(), BoundingBox().GetNearPlane().Norm()));
00191    }
00192    IncTimeStamp();
00193    fValid = kTRUE;
00194 }
00195 
00196 //______________________________________________________________________________
00197 void TGLClipPlane::Setup(const TGLVector3& point, const TGLVector3& normal)
00198 {
00199    // Setup the clipping plane by point and normal.
00200    // Length of the normal determines the size of the plane drawn in
00201    // GL viewer. The normal points into the direction of visible half-plane.
00202    //
00203    // This only makes sense if you disable auto-update of the
00204    // clip-object:
00205    //   gl_viewer->SetClipAutoUpdate(kFALSE).
00206    // After calling this also call gl_viewer->RefreshPadEditor(gl_viewer)
00207    // and gl_viewer->RequestDraw().
00208 
00209    TGLVector3 n(normal);
00210    Double_t extents = n.Mag();
00211    if (extents > 0)
00212    {
00213       n /= extents;
00214       TGLClipPlaneLogical* cpl = (TGLClipPlaneLogical*) GetLogical();
00215       cpl->Resize(extents);
00216       SetTransform(TGLMatrix(point, n));
00217 
00218       IncTimeStamp();
00219       fValid = kTRUE;
00220    }
00221    else
00222    {
00223       Warning("TGLClipPlane::Setup", "Normal with zero length passed.");
00224    }
00225 }
00226 
00227 //______________________________________________________________________________
00228 void TGLClipPlane::Set(const TGLPlane& plane)
00229 {
00230    // Update clip plane object to follow passed 'plane' equation. Center pivot
00231    // is shifted to nearest point on new plane.
00232 
00233    TGLVertex3 oldCenter = BoundingBox().Center();
00234    TGLVertex3 newCenter = plane.NearestOn(oldCenter);
00235    SetTransform(TGLMatrix(newCenter, plane.Norm()));
00236    IncTimeStamp();
00237    fValid = kTRUE;
00238 }
00239 
00240 //______________________________________________________________________________
00241 void TGLClipPlane::PlaneSet(TGLPlaneSet_t& set) const
00242 {
00243    // Return set of planes (actually a single one) describing this clip plane.
00244 
00245    set.resize(1);
00246    set[0] = BoundingBox().GetNearPlane();
00247    set[0].Negate();
00248 }
00249 
00250 //////////////////////////////////////////////////////////////////////////
00251 //
00252 // TGLClipBox
00253 //
00254 // Concrete clip box object. Can be translated, rotated and scaled in
00255 // all (xyz) axes. By default inside of the box is clipped away.
00256 //
00257 //////////////////////////////////////////////////////////////////////////
00258 
00259 ClassImp(TGLClipBox);
00260 
00261 const float TGLClipBox::fgColor[4] = { 1.0, 0.6, 0.2, 0.3 };
00262 
00263 //______________________________________________________________________________
00264 TGLClipBox::TGLClipBox() :
00265    TGLClip(* new TGLClipBoxLogical, TGLMatrix(), fgColor)
00266 {
00267    // Construct an (initially) axis aligned clip pbox object, extents
00268    // 'halfLengths', centered on 'center' vertex.
00269    // Box can be translated, rotated and scaled in all (xyz) local axes.
00270 }
00271 
00272 //______________________________________________________________________________
00273 TGLClipBox::~TGLClipBox()
00274 {
00275    // Destroy clip box object.
00276 }
00277 
00278 //______________________________________________________________________________
00279 void TGLClipBox::Setup(const TGLBoundingBox& bbox)
00280 {
00281    // Setup the clip object for scene encompassed by bbox.
00282 
00283    TGLVector3 halfLengths = bbox.Extents() * 0.2501;
00284    TGLVertex3 center      = bbox.Center() + halfLengths;
00285 
00286    TGLClipBoxLogical* cbl = (TGLClipBoxLogical*) GetLogical();
00287    cbl->Resize(center - halfLengths, center + halfLengths);
00288 
00289    IncTimeStamp();
00290    fValid = kTRUE;
00291 }
00292 
00293 //______________________________________________________________________________
00294 void TGLClipBox::Setup(const TGLVector3& min_point, const TGLVector3& max_point)
00295 {
00296    // Setup the clip box with min/max points directly.
00297    //
00298    // This only makes sense if you disable auto-update of the
00299    // clip-object:
00300    //   gl_viewer->SetClipAutoUpdate(kFALSE).
00301    // After calling this also call gl_viewer->RefreshPadEditor(gl_viewer)
00302    // and gl_viewer->RequestDraw().
00303 
00304    TGLClipBoxLogical* cbl = (TGLClipBoxLogical*) GetLogical();
00305    cbl->Resize(min_point, max_point);
00306 
00307    IncTimeStamp();
00308    fValid = kTRUE; 
00309 }
00310 
00311 //______________________________________________________________________________
00312 void TGLClipBox::PlaneSet(TGLPlaneSet_t& set) const
00313 {
00314    // Return set of 6 planes describing faces of the box but invert them
00315    // so that they point inside of box.
00316 
00317    BoundingBox().PlaneSet(set);
00318    TGLPlaneSet_i i = set.begin();
00319    while (i != set.end()) {
00320       i->Negate();
00321       ++i;
00322    }
00323 }
00324 
00325 
00326 //////////////////////////////////////////////////////////////////////////
00327 //
00328 // TGLClipSet
00329 //
00330 // A collection of concrete TGLClip objects to be selected from.
00331 //
00332 //////////////////////////////////////////////////////////////////////////
00333 
00334 
00335 ClassImp(TGLClipSet);
00336 
00337 //______________________________________________________________________________
00338 TGLClipSet::TGLClipSet() :
00339    TGLOverlayElement(kViewer), 
00340    fClipPlane   (new TGLClipPlane),
00341    fClipBox     (new TGLClipBox),
00342    fCurrentClip (0),
00343    fAutoUpdate  (kTRUE),
00344    fShowClip    (kFALSE),
00345    fShowManip   (kFALSE),
00346    fManip       (new TGLManipSet)
00347 {
00348    // Constructor.
00349 }
00350 
00351 //______________________________________________________________________________
00352 TGLClipSet::~TGLClipSet()
00353 {
00354    // Destructor.
00355 
00356    delete fClipPlane;
00357    delete fClipBox;
00358    delete fManip;
00359 }
00360 
00361 //______________________________________________________________________
00362 Bool_t TGLClipSet::MouseEnter(TGLOvlSelectRecord& selRec)
00363 {
00364    // Mouse has enetered this element.
00365    // Forward to ManipSet.
00366 
00367    return fManip->MouseEnter(selRec);
00368 }
00369 
00370 Bool_t TGLClipSet::MouseStillInside(TGLOvlSelectRecord& selRec)
00371 {
00372    // A new overlay hit is about to be processed.
00373    // Forward to ManipSet.
00374 
00375    return fManip->MouseStillInside(selRec);
00376 }
00377 
00378 //______________________________________________________________________
00379 Bool_t TGLClipSet::Handle(TGLRnrCtx& rnrCtx, TGLOvlSelectRecord& selRec,
00380                           Event_t* event)
00381 {
00382    // Handle overlay event.
00383    // Forward to ManipSet.
00384 
00385    return fManip->Handle(rnrCtx, selRec, event);
00386 }
00387 
00388 //______________________________________________________________________
00389 void TGLClipSet::MouseLeave()
00390 {
00391    // Mouse has left the element.
00392    // Forward to ManipSet.
00393 
00394    return fManip->MouseLeave();
00395 }
00396 
00397 //______________________________________________________________________________
00398 void TGLClipSet::Render(TGLRnrCtx& rnrCtx)
00399 {
00400    // Render clip-shape and manipulator.
00401 
00402    if (!fCurrentClip) return;
00403 
00404    rnrCtx.SetShapeLOD(TGLRnrCtx::kLODHigh);
00405    rnrCtx.SetDrawPass(TGLRnrCtx::kPassFill);
00406    if (fShowClip && ! rnrCtx.Selection())
00407    {
00408       fCurrentClip->Draw(rnrCtx);
00409    }
00410    if (fShowManip)
00411    {
00412       fManip->Render(rnrCtx);
00413    }
00414 }
00415 
00416 //______________________________________________________________________________
00417 void TGLClipSet::FillPlaneSet(TGLPlaneSet_t& set) const
00418 {
00419    // Forward request to fill the plane-set to the current clip.
00420 
00421    if (fCurrentClip)
00422       fCurrentClip->PlaneSet(set);
00423 }
00424 
00425 //______________________________________________________________________________
00426 void TGLClipSet::SetupClips(const TGLBoundingBox& sceneBBox)
00427 {
00428    // Setup clipping objects for given scene bounding box.
00429 
00430    fLastBBox = sceneBBox;
00431    fClipPlane->Setup(sceneBBox);
00432    fClipBox  ->Setup(sceneBBox);
00433 }
00434 
00435 //______________________________________________________________________________
00436 void TGLClipSet::SetupCurrentClip(const TGLBoundingBox& sceneBBox)
00437 {
00438    // Setup current clipping object for given scene bounding box.
00439 
00440    fLastBBox = sceneBBox;
00441    if (fCurrentClip)
00442       fCurrentClip->Setup(sceneBBox);
00443 }
00444 
00445 //______________________________________________________________________________
00446 void TGLClipSet::SetupCurrentClipIfInvalid(const TGLBoundingBox& sceneBBox)
00447 {
00448    // Setup current clipping object for given scene bounding box.
00449 
00450    fLastBBox = sceneBBox;
00451    if (fCurrentClip && ! fCurrentClip->IsValid())
00452       fCurrentClip->Setup(sceneBBox);
00453 }
00454 
00455 //______________________________________________________________________________
00456 void TGLClipSet::InvalidateClips()
00457 {
00458    // Invalidate clip objects.
00459 
00460    fClipPlane->Invalidate();
00461    fClipBox  ->Invalidate();
00462 }
00463 
00464 //______________________________________________________________________________
00465 void TGLClipSet::InvalidateCurrentClip()
00466 {
00467    // Invalidate current clip object.
00468 
00469    if (fCurrentClip)
00470       fCurrentClip->Invalidate();
00471 }
00472 
00473 //______________________________________________________________________________
00474 void TGLClipSet::GetClipState(EClipType type, Double_t data[6]) const
00475 {
00476    // Get state of clip object 'type' into data vector:
00477    //
00478    // 'type' requested - 'data' contents returned
00479    // kClipPlane   4 components - A,B,C,D - of plane eq : Ax+By+CZ+D = 0
00480    // kBoxPlane    6 components - Box Center X/Y/Z - Box Extents X/Y/Z
00481 
00482    switch (type)
00483    {
00484       case kClipNone:
00485          break;
00486 
00487       case kClipPlane:
00488       {
00489          if (!fClipPlane->IsValid())
00490             fClipPlane->Setup(fLastBBox);
00491          TGLPlaneSet_t planes;
00492          fClipPlane->PlaneSet(planes);
00493          data[0] = planes[0].A();
00494          data[1] = planes[0].B();
00495          data[2] = planes[0].C();
00496          data[3] = planes[0].D();
00497          break;
00498       }
00499       case kClipBox:
00500       {
00501          if (!fClipBox->IsValid())
00502             fClipBox->Setup(fLastBBox);
00503          const TGLBoundingBox & box = fClipBox->BoundingBox();
00504          TGLVector3 ext = box.Extents();
00505          data[0] = box.Center().X();
00506          data[1] = box.Center().Y();
00507          data[2] = box.Center().Z();
00508          data[3] = box.Extents().X();
00509          data[4] = box.Extents().Y();
00510          data[5] = box.Extents().Z();
00511          break;
00512       }
00513       default:
00514          Error("TGLClipSet::GetClipState", "invalid clip type '%d'.", type);
00515          break;
00516    }
00517 }
00518 
00519 //______________________________________________________________________________
00520 void TGLClipSet::SetClipState(EClipType type, const Double_t data[6])
00521 {
00522    // Set state of clip object 'type' into data vector:
00523    //
00524    // 'type' specified        'data' contents interpretation
00525    // kClipNone               ignored
00526    // kClipPlane              4 components - A,B,C,D - of plane eq : Ax+By+CZ+D = 0
00527    // kBoxPlane               6 components - Box Center X/Y/Z - Box Extents X/Y/Z
00528 
00529    switch (type) {
00530       case kClipNone: {
00531          break;
00532       }
00533       case kClipPlane: {
00534          TGLPlane newPlane(-data[0], -data[1], -data[2], -data[3]);
00535          fClipPlane->Set(newPlane);
00536          break;
00537       }
00538       case kClipBox: {
00539          //TODO: Pull these inside TGLPhysicalShape
00540          // Update clip box center
00541          const TGLBoundingBox & currentBox = fClipBox->BoundingBox();
00542          TGLVector3 shift(data[0] - currentBox.Center().X(),
00543                           data[1] - currentBox.Center().Y(),
00544                           data[2] - currentBox.Center().Z());
00545          fClipBox->Translate(shift);
00546          // Update clip box extents
00547 
00548          TGLVector3 currentScale = fClipBox->GetScale();
00549          TGLVector3 newScale(data[3] / currentBox.Extents().X() * currentScale.X(),
00550                              data[4] / currentBox.Extents().Y() * currentScale.Y(),
00551                              data[5] / currentBox.Extents().Z() * currentScale.Z());
00552 
00553          fClipBox->Scale(newScale);
00554          break;
00555       }
00556    }
00557 }
00558 
00559 //______________________________________________________________________________
00560 EClipType TGLClipSet::GetClipType() const
00561 {
00562    // Get current type active in viewer - returns one of kClipNone
00563    // kClipPlane or kClipBox.
00564 
00565    EClipType type;
00566    if (fCurrentClip == 0) {
00567       type = kClipNone;
00568    } else if (fCurrentClip == fClipPlane) {
00569       type = kClipPlane;
00570    } else if (fCurrentClip == fClipBox) {
00571       type = kClipBox;
00572    } else {
00573       Error("TGLClipSet::GetClipType" , "Unknown clip type");
00574       type = kClipNone;
00575    }
00576    return type;
00577 }
00578 
00579 //______________________________________________________________________________
00580 void TGLClipSet::SetClipType(EClipType type)
00581 {
00582    // Set current clip active in viewer - 'type' is one of kClipNone
00583    // kClipPlane or kClipBox.
00584 
00585    switch (type) {
00586       case kClipNone: {
00587          fCurrentClip = 0;
00588          break;
00589       }
00590       case kClipPlane: {
00591          fCurrentClip = fClipPlane;
00592          break;
00593       }
00594       case kClipBox: {
00595          fCurrentClip = fClipBox;
00596          break;
00597       }
00598       default: {
00599          Error("TGLClipSet::SetClipType" , "Unknown clip type");
00600          break;
00601       }
00602    }
00603    fManip->SetPShape(fCurrentClip);
00604 }

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1