// @(#)root/gl:$Name:  $:$Id: TGLPhysicalShape.cxx,v 1.15 2005/11/22 18:05:46 brun Exp $
// Author:  Richard Maunder  25/05/2005

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

#include "TGLPhysicalShape.h"
#include "TGLLogicalShape.h"
#include "TGLIncludes.h"

// For debug tracing
#include "TClass.h" 
#include "TError.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGLPhysicalShape                                                     //
//                                                                      //
// Concrete physical shape - a GL drawable. Physical shapes are the     //
// objects the user can actually see, select, move in the viewer. It is //
// a placement of the associated local frame TGLLogicaShape into the    //
// world frame. The draw process is:                                    //
//                                                                      // 
// Load attributes - material colors etc                                // 
// Load translation matrix - placement                                  //
// Load gl name (for selection)                                         //
// Call our associated logical shape Draw() to draw placed shape        //
//                                                                      //
// The physical shape supports translation, scaling and rotation,       //
// selection, color changes, and permitted modification flags etc.      //
// A physical shape cannot modify or be bound to another (or no)        //
// logical shape - hence const & handle. It can perform mutable         //
// reference counting on the logical to enable purging.                 //
//                                                                      //
// See base/src/TVirtualViewer3D for description of common external 3D  //
// viewer architecture and how external viewer clients use it.          //
//////////////////////////////////////////////////////////////////////////

ClassImp(TGLPhysicalShape)

//______________________________________________________________________________
 TGLPhysicalShape::TGLPhysicalShape(ULong_t ID, const TGLLogicalShape & logicalShape,
                                   const TGLMatrix & transform, Bool_t invertedWind,
                                   const Float_t rgba[4]) :
   TGLDrawable(ID, kFALSE), // Physical shapes not DL cached by default
   fLogicalShape(logicalShape),
   fTransform(transform),
   fSelected(kFALSE),
   fInvertedWind(invertedWind),
   fModified(kFALSE), 
   fManip(kManipAll)
{
   // Construct a physical shape using arguments:
   //    ID             - unique drawable id.
   //    logicalShape   - bound logical shape
   //    transform      - transform for placement of logical drawing 
   //    invertedWind   - use inverted face polygon winding?
   //    rgba           - basic four component (RGBA) diffuse color 
   fLogicalShape.AddRef();
   UpdateBoundingBox();

   // Initialise color
   InitColor(rgba);
}

//______________________________________________________________________________
 TGLPhysicalShape::TGLPhysicalShape(ULong_t ID, const TGLLogicalShape & logicalShape,
                                   const Double_t * transform, Bool_t invertedWind,
                                   const Float_t rgba[4]) :
   TGLDrawable(ID, kFALSE), // Physical shapes not DL cached by default
   fLogicalShape(logicalShape),
   fTransform(transform),
   fSelected(kFALSE),
   fInvertedWind(invertedWind),
   fModified(kFALSE),
   fManip(kManipAll)
{
   // Construct a physical shape using arguments:
   //    ID             - unique drawable id.
   //    logicalShape   - bound logical shape
   //    transform      - 16 Double_t component transform for placement of logical drawing 
   //    invertedWind   - use inverted face polygon winding?
   //    rgba           - basic four component (RGBA) diffuse color 
   
   fLogicalShape.AddRef();
   // Temporary hack - invert the 3x3 part of martix as TGeo sends this
   // in opp layout to shear/translation parts. Speak to Andrei about best place
   // to fix - probably when filling TBuffer3D - should always be OGL convention?
   fTransform.Transpose3x3();
   UpdateBoundingBox();

   // Initialise color
   InitColor(rgba);
}

//______________________________________________________________________________
 TGLPhysicalShape::~TGLPhysicalShape()
{
   // Destroy logical shape
   fLogicalShape.SubRef();
}

//______________________________________________________________________________
 void TGLPhysicalShape::UpdateBoundingBox() 
{
   // Update our internal bounding box (in global frame)
   fBoundingBox.Set(fLogicalShape.BoundingBox());
   fBoundingBox.Transform(fTransform);
}

//______________________________________________________________________________
 void TGLPhysicalShape::InitColor(const Float_t rgba[4])
{
   // Initialise the colors, using basic RGBA diffuse material color supplied
   
   // TODO: Make a color class
   fColor[0] = rgba[0];
   fColor[1] = rgba[1];
   fColor[2] = rgba[2];
   fColor[3] = rgba[3];

   //ambient
   fColor[4] = fColor[5] = fColor[6] = 0.0f;
   //specular
   fColor[8] = fColor[9] = fColor[10] = 0.7f;
   //emission
   fColor[12] = fColor[13] = fColor[14] = 0.f;
   //alpha
   fColor[7] = fColor[11] = fColor[15] = 1.f;
   //shininess
   fColor[16] = 60.f;

   // Modified flag not set - just initialising
}

//______________________________________________________________________________
 void TGLPhysicalShape::SetColor(const Float_t color[17])
{
   // Set full color attributes - see OpenGL material documentation
   // for full description
   //
   // 0...3  - diffuse
   // 4...7  - ambient
   // 8...11 - specular
   // 12..15 - emission
   // 16     - shininess
   
   // TODO: Make a color class
   for (UInt_t i = 0; i < 17; i++) {
      fColor[i] = color[i];
   }
   fModified = kTRUE;
}

//______________________________________________________________________________
 void TGLPhysicalShape::Draw(UInt_t LOD) const
{
   // Draw physical shape, using LOD flags, potential from display list cache
   
   // Debug tracing
   if (gDebug > 4) {
      Info("TGLPhysicalShape::Draw", "this %d (class %s) LOD %d", this, IsA()->GetName(), LOD);
   }

   // Setup current colors
   // TODO: Can these be moved to DirectDraw - does DL capture draw attributes
   // to investigate
   // TODO: Sorting - Min. state swap for attributes
   glColor4fv(fColor);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, fColor);
   glMaterialfv(GL_FRONT, GL_AMBIENT, fColor + 4);
   glMaterialfv(GL_FRONT, GL_SPECULAR, fColor + 8);
   glMaterialfv(GL_FRONT, GL_EMISSION, fColor + 12);
   glMaterialf(GL_FRONT, GL_SHININESS, fColor[16]);

   // Do base work with potential DL caching
   TGLDrawable::Draw(LOD);
}

//______________________________________________________________________________
 void TGLPhysicalShape::DirectDraw(UInt_t LOD) const
{
   // Draw physical shape, using LOD flags - can be captured into display list cache
   //
   // Load gl name (for selection)
   // Load translation matrix - placement                                  
   // Call associated fLogicalShape Draw() method

   // Debug tracing
   if (gDebug > 4) {
      Info("TGLPhysicalShape::DirectDraw", "this %d (class %s) LOD %d", this, IsA()->GetName(), LOD);
   }

   glPushMatrix();
   glLoadName(ID());
   glMultMatrixd(fTransform.CArr());
   if (fInvertedWind) {
      glFrontFace(GL_CW);
   }
   fLogicalShape.Draw(LOD);
   if (fInvertedWind) {
      glFrontFace(GL_CCW);
   }
   glPopMatrix();
}

//______________________________________________________________________________
 void TGLPhysicalShape::DrawWireFrame(UInt_t lod) const
{
   // Draw physical shape in wireframe style
   glPushMatrix();
   glLoadName(ID());
   glMultMatrixd(fTransform.CArr());
   
   glColor4fv(fColor);

   if (fInvertedWind) glFrontFace(GL_CW);
   fLogicalShape.DrawWireFrame(lod);
   if (fInvertedWind) glFrontFace(GL_CCW);
   
   glPopMatrix();
}

//______________________________________________________________________________
 void TGLPhysicalShape::DrawOutline(UInt_t LOD) const
{
   // Draw physical shape in outline style
   
   // Debug tracing
   if (gDebug > 4) {
      Info("TGLPhysicalShape::Draw", "this %d (class %s) LOD %d", this, IsA()->GetName(), LOD);
   }

   glPushMatrix();
   glLoadName(ID());
   glMultMatrixd(fTransform.CArr());
   
   //TODO: Sorting - Min. state swap for attributes
   glMaterialfv(GL_FRONT, GL_DIFFUSE, fColor);
   glMaterialfv(GL_FRONT, GL_AMBIENT, fColor + 4);
   glMaterialfv(GL_FRONT, GL_SPECULAR, fColor + 8);
   glMaterialfv(GL_FRONT, GL_EMISSION, fColor + 12);
   glMaterialf(GL_FRONT, GL_SHININESS, fColor[16]);

   if (fInvertedWind) glFrontFace(GL_CW);
   fLogicalShape.DrawOutline(LOD);
   if (fInvertedWind) glFrontFace(GL_CCW);
   
   glPopMatrix();
}

//______________________________________________________________________________
 void TGLPhysicalShape::InvokeContextMenu(TContextMenu & menu, UInt_t x, UInt_t y) const
{
   // Request creation of context menu on shape, attached to 'menu' at screen position
   // 'x' 'y'
   
   // Just defer to our logical at present
   fLogicalShape.InvokeContextMenu(menu, x, y);
}



ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.