// @(#)root/gl:$Id$
// Author:  Richard Maunder  25/05/2005
// Parts taken from original TGLSceneObject Timur Pocheptsov

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TGLPhysicalShape
#define ROOT_TGLPhysicalShape

//#ifndef ROOT_TGLLogicalShape
//#include "TGLLogicalShape.h"
//#endif
#ifndef ROOT_TGLBoundingBox
#include "TGLBoundingBox.h"
#endif
#ifndef ROOT_TGLUtil
#include "TGLUtil.h" // For TGLMatrix
#endif

class TGLPShapeRef;
class TGLLogicalShape;
class TGLRnrCtx;

class TContextMenu;


class TGLPhysicalShape
{
   friend class TGLLogicalShape; // for replica-list management

private:
   TGLPhysicalShape(const TGLPhysicalShape&);            // Not implemented
   TGLPhysicalShape& operator=(const TGLPhysicalShape&); // Not implemented

public:
   // Flags for permitted manipulation of object
   enum EManip  { kTranslateX   = 1 << 0,
                  kTranslateY   = 1 << 1,
                  kTranslateZ   = 1 << 2,
                  kTranslateAll = kTranslateX | kTranslateY | kTranslateZ,
                  kScaleX       = 1 << 3,
                  kScaleY       = 1 << 4,
                  kScaleZ       = 1 << 5,
                  kScaleAll     = kScaleX | kScaleY | kScaleZ,
                  kRotateX      = 1 << 6,
                  kRotateY      = 1 << 7,
                  kRotateZ      = 1 << 8,
                  kRotateAll    = kRotateX | kRotateY | kRotateZ,
                  kManipAll     = kTranslateAll | kScaleAll | kRotateAll
                };
private:
   // Fields
   const TGLLogicalShape * fLogicalShape; //! the associated logical shape
         TGLPhysicalShape* fNextPhysical; //! pointer to next replica
         TGLPShapeRef    * fFirstPSRef;   //! pointer to first reference

   UInt_t                  fID;           //! unique physical ID within containing scene
   TGLMatrix               fTransform;    //! transform (placement) of physical instance
   TGLBoundingBox          fBoundingBox;  //! bounding box of the physical (transformed)
   Float_t                 fColor[17];    //! GL color array
   EManip                  fManip;        //! permitted manipulation bitflags - see EManip
   UChar_t                 fSelected;     //! selected state
   Bool_t                  fInvertedWind; //! face winding TODO: can get directly from fTransform?
   Bool_t                  fModified;     //! has been modified - retain across scene rebuilds
   Bool_t                  fIsScaleForRnr;//! cache

   // Methods
   void            UpdateBoundingBox();
   void            InitColor(const Float_t rgba[4]);

public:
   TGLPhysicalShape(UInt_t ID, const TGLLogicalShape & logicalShape,
                    const TGLMatrix & transform, Bool_t invertedWind,
                    const Float_t rgba[4]);
   TGLPhysicalShape(UInt_t ID, const TGLLogicalShape & logicalShape,
                    const double * transform, Bool_t invertedWind,
                    const Float_t rgba[4]);
   virtual ~TGLPhysicalShape();

   void   AddReference   (TGLPShapeRef* ref);
   void   RemoveReference(TGLPShapeRef* ref);

   UInt_t                 ID()          const { return fID; }
   const TGLBoundingBox & BoundingBox() const { return fBoundingBox; }

   virtual void CalculateShapeLOD(TGLRnrCtx & rnrCtx, Float_t& pixSize, Short_t& shapeLOD) const;
   virtual void QuantizeShapeLOD (Short_t shapeLOD, Short_t combiLOD, Short_t& quantLOD) const;

   void SetupGLColors(TGLRnrCtx & rnrCtx, const Float_t* color=0) const;
   virtual void Draw(TGLRnrCtx & rnrCtx) const;

   const TGLLogicalShape  * GetLogical()      const { return fLogicalShape; }
   const TGLPhysicalShape * GetNextPhysical() const { return fNextPhysical; }

   // Modification and manipulation
   EManip  GetManip()   const      { return fManip;  }
   void    SetManip(EManip manip)  { fManip = manip; }

   // Modified - treated as temporary modification
   void    Modified();
   Bool_t  IsModified() const      { return fModified; }

   // Selection
   Bool_t  IsSelected()  const    { return fSelected != 0; }
   UChar_t GetSelected() const    { return fSelected; }
   void    Select(UChar_t select) { fSelected = select; }

   // Color
   const Float_t  * Color() const                      { return fColor; }
   Bool_t           IsTransparent() const              { return fColor[3] < 1.f; }
   Bool_t           IsInvisible() const                { return fColor[3] == 0.f; }
   void             SetColor(const Float_t rgba[17]);
   void             SetColorOnFamily(const Float_t rgba[17]);
   void             SetDiffuseColor(const Float_t rgba[4]);
   void             SetDiffuseColor(const UChar_t rgba[4]);
   void             SetDiffuseColor(Color_t ci, UChar_t transparency);

   // Geometry
   TGLVector3       GetScale() const;
   TGLVertex3       GetTranslation() const;

   void             SetTransform(const TGLMatrix & transform);
   void             SetTransform(const Double_t vals[16]);
   void             SetTranslation(const TGLVertex3 & translation);
   void             Translate(const TGLVector3 & vect);
   void             Scale(const TGLVector3 & scale);
   void             Rotate(const TGLVertex3 & pivot, const TGLVector3 & axis, Double_t angle);

   // Context menu
   void             InvokeContextMenu(TContextMenu & menu, UInt_t x, UInt_t y) const;

   ClassDef(TGLPhysicalShape,0) // a physical (placed, global frame) drawable object
};


//______________________________________________________________________________
inline TGLVector3 TGLPhysicalShape::GetScale() const
{
   return fTransform.GetScale();
}

//______________________________________________________________________________
inline TGLVertex3 TGLPhysicalShape::GetTranslation() const
{
   return fTransform.GetTranslation();
}

//______________________________________________________________________________
inline void TGLPhysicalShape::SetTransform(const TGLMatrix & transform)
{
   fTransform = transform;
   UpdateBoundingBox();
   Modified();
}

//______________________________________________________________________________
inline void TGLPhysicalShape::SetTransform(const Double_t vals[16])
{
   fTransform.Set(vals);
   UpdateBoundingBox();
   Modified();
}

//______________________________________________________________________________
inline void TGLPhysicalShape::SetTranslation(const TGLVertex3 & translation)
{
   fTransform.SetTranslation(translation);
   UpdateBoundingBox();
   Modified();
}

//______________________________________________________________________________
inline void TGLPhysicalShape::Translate(const TGLVector3 & vect)
{
   fTransform.Translate(vect);
   UpdateBoundingBox();
   Modified();
}

//______________________________________________________________________________
inline void TGLPhysicalShape::Scale(const TGLVector3 & scale)
{
   TGLVertex3 origCenter = fBoundingBox.Center();
   fTransform.Scale(scale);
   UpdateBoundingBox();
   TGLVector3 shift = fBoundingBox.Center() - origCenter;
   Translate(-shift);
   UpdateBoundingBox();
   Modified();
}

//______________________________________________________________________________
inline void TGLPhysicalShape::Rotate(const TGLVertex3 & pivot, const TGLVector3 & axis, Double_t angle)
{
   TGLVertex3 c = BoundingBox().Center();
   fTransform.Rotate(pivot, axis, angle);
   UpdateBoundingBox();
   Modified();
}

#endif // ROOT_TGLPhysicalShape
 TGLPhysicalShape.h:1
 TGLPhysicalShape.h:2
 TGLPhysicalShape.h:3
 TGLPhysicalShape.h:4
 TGLPhysicalShape.h:5
 TGLPhysicalShape.h:6
 TGLPhysicalShape.h:7
 TGLPhysicalShape.h:8
 TGLPhysicalShape.h:9
 TGLPhysicalShape.h:10
 TGLPhysicalShape.h:11
 TGLPhysicalShape.h:12
 TGLPhysicalShape.h:13
 TGLPhysicalShape.h:14
 TGLPhysicalShape.h:15
 TGLPhysicalShape.h:16
 TGLPhysicalShape.h:17
 TGLPhysicalShape.h:18
 TGLPhysicalShape.h:19
 TGLPhysicalShape.h:20
 TGLPhysicalShape.h:21
 TGLPhysicalShape.h:22
 TGLPhysicalShape.h:23
 TGLPhysicalShape.h:24
 TGLPhysicalShape.h:25
 TGLPhysicalShape.h:26
 TGLPhysicalShape.h:27
 TGLPhysicalShape.h:28
 TGLPhysicalShape.h:29
 TGLPhysicalShape.h:30
 TGLPhysicalShape.h:31
 TGLPhysicalShape.h:32
 TGLPhysicalShape.h:33
 TGLPhysicalShape.h:34
 TGLPhysicalShape.h:35
 TGLPhysicalShape.h:36
 TGLPhysicalShape.h:37
 TGLPhysicalShape.h:38
 TGLPhysicalShape.h:39
 TGLPhysicalShape.h:40
 TGLPhysicalShape.h:41
 TGLPhysicalShape.h:42
 TGLPhysicalShape.h:43
 TGLPhysicalShape.h:44
 TGLPhysicalShape.h:45
 TGLPhysicalShape.h:46
 TGLPhysicalShape.h:47
 TGLPhysicalShape.h:48
 TGLPhysicalShape.h:49
 TGLPhysicalShape.h:50
 TGLPhysicalShape.h:51
 TGLPhysicalShape.h:52
 TGLPhysicalShape.h:53
 TGLPhysicalShape.h:54
 TGLPhysicalShape.h:55
 TGLPhysicalShape.h:56
 TGLPhysicalShape.h:57
 TGLPhysicalShape.h:58
 TGLPhysicalShape.h:59
 TGLPhysicalShape.h:60
 TGLPhysicalShape.h:61
 TGLPhysicalShape.h:62
 TGLPhysicalShape.h:63
 TGLPhysicalShape.h:64
 TGLPhysicalShape.h:65
 TGLPhysicalShape.h:66
 TGLPhysicalShape.h:67
 TGLPhysicalShape.h:68
 TGLPhysicalShape.h:69
 TGLPhysicalShape.h:70
 TGLPhysicalShape.h:71
 TGLPhysicalShape.h:72
 TGLPhysicalShape.h:73
 TGLPhysicalShape.h:74
 TGLPhysicalShape.h:75
 TGLPhysicalShape.h:76
 TGLPhysicalShape.h:77
 TGLPhysicalShape.h:78
 TGLPhysicalShape.h:79
 TGLPhysicalShape.h:80
 TGLPhysicalShape.h:81
 TGLPhysicalShape.h:82
 TGLPhysicalShape.h:83
 TGLPhysicalShape.h:84
 TGLPhysicalShape.h:85
 TGLPhysicalShape.h:86
 TGLPhysicalShape.h:87
 TGLPhysicalShape.h:88
 TGLPhysicalShape.h:89
 TGLPhysicalShape.h:90
 TGLPhysicalShape.h:91
 TGLPhysicalShape.h:92
 TGLPhysicalShape.h:93
 TGLPhysicalShape.h:94
 TGLPhysicalShape.h:95
 TGLPhysicalShape.h:96
 TGLPhysicalShape.h:97
 TGLPhysicalShape.h:98
 TGLPhysicalShape.h:99
 TGLPhysicalShape.h:100
 TGLPhysicalShape.h:101
 TGLPhysicalShape.h:102
 TGLPhysicalShape.h:103
 TGLPhysicalShape.h:104
 TGLPhysicalShape.h:105
 TGLPhysicalShape.h:106
 TGLPhysicalShape.h:107
 TGLPhysicalShape.h:108
 TGLPhysicalShape.h:109
 TGLPhysicalShape.h:110
 TGLPhysicalShape.h:111
 TGLPhysicalShape.h:112
 TGLPhysicalShape.h:113
 TGLPhysicalShape.h:114
 TGLPhysicalShape.h:115
 TGLPhysicalShape.h:116
 TGLPhysicalShape.h:117
 TGLPhysicalShape.h:118
 TGLPhysicalShape.h:119
 TGLPhysicalShape.h:120
 TGLPhysicalShape.h:121
 TGLPhysicalShape.h:122
 TGLPhysicalShape.h:123
 TGLPhysicalShape.h:124
 TGLPhysicalShape.h:125
 TGLPhysicalShape.h:126
 TGLPhysicalShape.h:127
 TGLPhysicalShape.h:128
 TGLPhysicalShape.h:129
 TGLPhysicalShape.h:130
 TGLPhysicalShape.h:131
 TGLPhysicalShape.h:132
 TGLPhysicalShape.h:133
 TGLPhysicalShape.h:134
 TGLPhysicalShape.h:135
 TGLPhysicalShape.h:136
 TGLPhysicalShape.h:137
 TGLPhysicalShape.h:138
 TGLPhysicalShape.h:139
 TGLPhysicalShape.h:140
 TGLPhysicalShape.h:141
 TGLPhysicalShape.h:142
 TGLPhysicalShape.h:143
 TGLPhysicalShape.h:144
 TGLPhysicalShape.h:145
 TGLPhysicalShape.h:146
 TGLPhysicalShape.h:147
 TGLPhysicalShape.h:148
 TGLPhysicalShape.h:149
 TGLPhysicalShape.h:150
 TGLPhysicalShape.h:151
 TGLPhysicalShape.h:152
 TGLPhysicalShape.h:153
 TGLPhysicalShape.h:154
 TGLPhysicalShape.h:155
 TGLPhysicalShape.h:156
 TGLPhysicalShape.h:157
 TGLPhysicalShape.h:158
 TGLPhysicalShape.h:159
 TGLPhysicalShape.h:160
 TGLPhysicalShape.h:161
 TGLPhysicalShape.h:162
 TGLPhysicalShape.h:163
 TGLPhysicalShape.h:164
 TGLPhysicalShape.h:165
 TGLPhysicalShape.h:166
 TGLPhysicalShape.h:167
 TGLPhysicalShape.h:168
 TGLPhysicalShape.h:169
 TGLPhysicalShape.h:170
 TGLPhysicalShape.h:171
 TGLPhysicalShape.h:172
 TGLPhysicalShape.h:173
 TGLPhysicalShape.h:174
 TGLPhysicalShape.h:175
 TGLPhysicalShape.h:176
 TGLPhysicalShape.h:177
 TGLPhysicalShape.h:178
 TGLPhysicalShape.h:179
 TGLPhysicalShape.h:180
 TGLPhysicalShape.h:181
 TGLPhysicalShape.h:182
 TGLPhysicalShape.h:183
 TGLPhysicalShape.h:184
 TGLPhysicalShape.h:185
 TGLPhysicalShape.h:186
 TGLPhysicalShape.h:187
 TGLPhysicalShape.h:188
 TGLPhysicalShape.h:189
 TGLPhysicalShape.h:190
 TGLPhysicalShape.h:191
 TGLPhysicalShape.h:192
 TGLPhysicalShape.h:193
 TGLPhysicalShape.h:194
 TGLPhysicalShape.h:195
 TGLPhysicalShape.h:196
 TGLPhysicalShape.h:197
 TGLPhysicalShape.h:198
 TGLPhysicalShape.h:199
 TGLPhysicalShape.h:200
 TGLPhysicalShape.h:201
 TGLPhysicalShape.h:202
 TGLPhysicalShape.h:203
 TGLPhysicalShape.h:204
 TGLPhysicalShape.h:205
 TGLPhysicalShape.h:206
 TGLPhysicalShape.h:207