Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLScaleManip.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Richard Maunder 16/09/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TGLScaleManip.h"
13 #include "TGLPhysicalShape.h"
14 #include "TGLCamera.h"
15 #include "TGLIncludes.h"
16 
17 /** \class TGLScaleManip
18 \ingroup opengl
19 Scale manipulator - attaches to physical shape and draws local axes
20 widgets with box heads. User can mouse over (turns yellow) and L
21 click/drag to scale along this axis.
22 */
23 
24 ClassImp(TGLScaleManip);
25 
26 ////////////////////////////////////////////////////////////////////////////////
27 /// Construct scale manipulator not bound to any physical shape.
28 
29 TGLScaleManip::TGLScaleManip()
30 {
31 }
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// Construct scale manipulator bound to TGLPhysicalShape 'shape'.
35 
36 TGLScaleManip::TGLScaleManip(TGLPhysicalShape * shape) :
37  TGLManip(shape)
38 {
39 }
40 
41 ////////////////////////////////////////////////////////////////////////////////
42 /// Destroy the scale manipulator
43 
44 TGLScaleManip::~TGLScaleManip()
45 {
46 }
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Draw scale manipulator - tubes with box heads, in local axes of
50 /// attached shape, in red(X), green(Y) and blue(Z), with white center sphere.
51 /// If selected widget (mouse over) this is drawn in active colour (yellow).
52 
53 void TGLScaleManip::Draw(const TGLCamera & camera) const
54 {
55  if (!fShape) {
56  return;
57  }
58 
59  // Get draw scales
60  const TGLBoundingBox & box = fShape->BoundingBox();
61  Double_t baseScale;
62  TGLVector3 axisScale[3];
63  CalcDrawScale(box, camera, baseScale, axisScale);
64 
65  // Get permitted manipulations on shape
66  TGLPhysicalShape::EManip manip = fShape->GetManip();
67 
68  glEnable(GL_BLEND);
69  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
70  glDisable(GL_CULL_FACE);
71 
72  // Draw three axis widgets out of bounding box where permitted
73  // Not drawing will prevent interaction
74  // GL name loading for hit testing - 0 reserved for no selection
75  if (manip & TGLPhysicalShape::kScaleX) {
76  glPushName(1);
77  TGLUtil::DrawLine(box.Center(), axisScale[0], TGLUtil::kLineHeadBox,
78  baseScale, ColorFor(1));
79  glPopName();
80  } else {
81  TGLUtil::DrawLine(box.Center(), axisScale[0], TGLUtil::kLineHeadBox,
82  baseScale, TGLUtil::fgGrey);
83  }
84  if (manip & TGLPhysicalShape::kScaleY) {
85  glPushName(2);
86  TGLUtil::DrawLine(box.Center(), axisScale[1], TGLUtil::kLineHeadBox,
87  baseScale, ColorFor(2));
88  glPopName();
89  } else {
90  TGLUtil::DrawLine(box.Center(), axisScale[1], TGLUtil::kLineHeadBox,
91  baseScale, TGLUtil::fgGrey);
92  }
93  if (manip & TGLPhysicalShape::kScaleZ) {
94  glPushName(3);
95  TGLUtil::DrawLine(box.Center(), axisScale[2], TGLUtil::kLineHeadBox,
96  baseScale, ColorFor(3));
97  glPopName();
98  } else {
99  TGLUtil::DrawLine(box.Center(), axisScale[2], TGLUtil::kLineHeadBox,
100  baseScale, TGLUtil::fgGrey);
101  }
102  // Draw white center sphere
103  TGLUtil::DrawSphere(box.Center(), baseScale/2.0, TGLUtil::fgWhite);
104 
105  glEnable(GL_CULL_FACE);
106  glDisable(GL_BLEND);
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Handle mouse button event over manipulator - returns kTRUE if
111 /// redraw required kFALSE otherwise.
112 
113 Bool_t TGLScaleManip::HandleButton(const Event_t & event,
114  const TGLCamera & camera)
115 {
116  if (event.fType == kButtonPress && fSelectedWidget != 0) {
117  fStartScale = fShape->GetScale();
118  }
119 
120  return TGLManip::HandleButton(event, camera);
121 }
122 
123 ////////////////////////////////////////////////////////////////////////////////
124 /// Handle mouse motion over manipulator - if active (selected
125 /// widget) scale physical along selected widget (axis) of the
126 /// manipulator, so it tracks mouse action. Returns kTRUE if redraw
127 /// required kFALSE otherwise.
128 
129 Bool_t TGLScaleManip::HandleMotion(const Event_t & event,
130  const TGLCamera & camera)
131 {
132  if (fActive) {
133  // Find mouse delta projected into world at attached object center
134  TGLVector3 shift = camera.ViewportDeltaToWorld(fShape->BoundingBox().Center(),
135  event.fX - fFirstMouse.GetX(),
136  -event.fY + fFirstMouse.GetY()); // Y inverted
137 
138  UInt_t axisIndex = fSelectedWidget - 1; // Ugg sort out axis / widget id mapping
139  TGLVector3 widgetAxis = fShape->BoundingBox().Axis(axisIndex, kTRUE);
140 
141  // Scale by projected screen factor
142  TGLVector3 screenScale = camera.ViewportDeltaToWorld(fShape->BoundingBox().Center(), 500, 500);
143  Double_t factor = -5.0*Dot(shift, widgetAxis) / screenScale.Mag();
144 
145  TGLVector3 newScale = fStartScale;
146  newScale[axisIndex] += factor;
147  LimitScale(newScale[axisIndex]);
148  fShape->Scale(newScale);
149 
150  fLastMouse.SetX(event.fX);
151  fLastMouse.SetY(event.fY);
152 
153  return kTRUE;
154  }
155  return kFALSE;
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Clamp scale to sizable values: 1000 - 1/1000
160 /// Guards against div by zero problems.
161 
162 void TGLScaleManip::LimitScale(Double_t & factor) const
163 {
164  if (factor < 1e-4) {
165  factor = 1e-4;
166  }
167  if (factor > 1e+4) {
168  factor = 1e+4;
169  }
170 }