0024814: Avoid using explicit names of Handle classes
[occt.git] / src / NIS / NIS_TriangulatedDrawer.cxx
1 // Created on: 2007-07-19
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2007-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <NIS_TriangulatedDrawer.hxx>
17 #include <NIS_InteractiveObject.hxx>
18 #include <NIS_Triangulated.hxx>
19 #ifdef _DEBUG
20 #include <Standard_ProgramError.hxx>
21 #endif
22
23 #include <OpenGl_GlCore11.hxx>
24
25 // Comment this line if you see no hilighting of triangulations due to negative
26 // polygon offsets. Disabling this macro means that all offsets will be created
27 // in the positive scale.
28
29 // But before changing this macro please play with your OpenGL video card
30 // settings in the direction of performance improvement. Particularly, I had a
31 // good result after checking "Enable write combining" option in NVIDIA 6600.
32
33 #define NEGATIVE_POFFSET
34
35 IMPLEMENT_STANDARD_HANDLE  (NIS_TriangulatedDrawer, NIS_Drawer)
36 IMPLEMENT_STANDARD_RTTIEXT (NIS_TriangulatedDrawer, NIS_Drawer)
37
38 //=======================================================================
39 //function : NIS_TriangulatedDrawer()
40 //purpose  : Constructor
41 //=======================================================================
42
43 NIS_TriangulatedDrawer::NIS_TriangulatedDrawer
44                                 (const Quantity_Color theNormal,
45                                  const Quantity_Color theHilight,
46                                  const Quantity_Color theDynHilight)
47   : myPolygonAsLineLoop (Standard_False),
48     myLineWidth      (1.f),
49     myIsDrawPolygons (Standard_False),
50     myPolygonType    (NIS_Triangulated::Polygon_Default)
51 {
52   myColor[Draw_Normal]       = theNormal;
53   myColor[Draw_Top]          = theNormal;
54   myColor[Draw_Transparent]  = theNormal;
55   myColor[Draw_Hilighted]    = theHilight;
56   myColor[Draw_DynHilighted] = theDynHilight;
57 }
58
59 //=======================================================================
60 //function : Assign
61 //purpose  :
62 //=======================================================================
63
64 void NIS_TriangulatedDrawer::Assign (const Handle(NIS_Drawer)& theOther)
65 {
66   if (theOther.IsNull() == Standard_False) {
67     NIS_Drawer::Assign (theOther);
68     const Handle(NIS_TriangulatedDrawer)& anOther =
69       static_cast <const Handle(NIS_TriangulatedDrawer)&> (theOther);
70     myColor[Draw_Normal]       = anOther->myColor[Draw_Normal];
71     myColor[Draw_Top]          = anOther->myColor[Draw_Top];
72     myColor[Draw_Transparent]  = anOther->myColor[Draw_Transparent];
73     myColor[Draw_Hilighted]    = anOther->myColor[Draw_Hilighted];
74     myColor[Draw_DynHilighted] = anOther->myColor[Draw_DynHilighted];
75     myLineWidth                = anOther->myLineWidth;
76     myIsDrawPolygons           = anOther->myIsDrawPolygons;
77     myPolygonType              = anOther->myPolygonType;
78   }
79 }
80
81 static const Standard_Integer nObjPerDrawer = 64;
82
83 //=======================================================================
84 //function : IsEqual
85 //purpose  : Comparison of two Drawers (for Map impementation)
86 //=======================================================================
87
88 Standard_Boolean NIS_TriangulatedDrawer::IsEqual
89                                 (const Handle(NIS_Drawer)& theOther)const
90 {
91   static const Standard_Real anEpsilon2 (1e-7);
92   Standard_Boolean aResult (Standard_False);
93   const Handle(NIS_TriangulatedDrawer) anOther =
94     Handle(NIS_TriangulatedDrawer)::DownCast (theOther);
95   if (NIS_Drawer::IsEqual(theOther))
96     aResult = (anOther->myColor[Draw_Normal]
97                .SquareDistance (myColor[Draw_Normal]) < anEpsilon2 &&
98                anOther->myColor[Draw_Hilighted]
99                .SquareDistance (myColor[Draw_Hilighted]) < anEpsilon2 &&
100                anOther->myColor[Draw_DynHilighted]
101                .SquareDistance (myColor[Draw_DynHilighted]) < anEpsilon2 &&
102                (anOther->myLineWidth - myLineWidth) *
103                (anOther->myLineWidth - myLineWidth) < 0.01 &&
104                anOther->myIsDrawPolygons == myIsDrawPolygons &&
105                anOther->myPolygonType == myPolygonType);
106   return aResult;
107 }
108
109 //=======================================================================
110 //function : BeforeDraw
111 //purpose  :
112 //=======================================================================
113
114 void NIS_TriangulatedDrawer::BeforeDraw (const DrawType      theType,
115                                          const NIS_DrawList&)
116 {
117   Quantity_Parameter   aValue[4];
118   Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
119   GLfloat aLineWidth (myLineWidth);
120   Standard_Integer anOffsetHilighted = 0;
121   switch (theType) {
122   case Draw_DynHilighted:
123     aLineWidth = myLineWidth + 1.f;
124 #ifdef NEGATIVE_POFFSET
125     anOffsetHilighted = -11;
126 #endif
127   case Draw_Hilighted:
128     switch (myPolygonType) {
129       default:
130       case NIS_Triangulated::Polygon_Default:
131         if (myIsDrawPolygons) {
132       case NIS_Triangulated::Polygon_Line:
133           glEnable(GL_POLYGON_OFFSET_LINE);
134         } else {
135       case NIS_Triangulated::Polygon_Fill:
136           glEnable(GL_POLYGON_OFFSET_FILL);
137         }
138     }
139     if (theType == Draw_Hilighted)
140     {
141 #ifdef NEGATIVE_POFFSET
142       anOffsetHilighted = -10;
143 #else
144       anOffsetHilighted = 1;
145 #endif
146     }
147     myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
148     glColor3d (aValue[0], aValue[1], aValue[2]);
149     break;
150   case Draw_Normal:
151   case Draw_Top:
152   case Draw_Transparent:
153 #ifndef NEGATIVE_POFFSET
154     anOffsetHilighted = 11;
155 #endif
156     myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
157     aValue[3] = 1. - myTransparency;
158     if (myTransparency > 0.01) {
159       glEnable(GL_BLEND);
160       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
161     }
162     glColor4d (aValue[0], aValue[1], aValue[2], aValue[3]);
163     break;
164   default:
165     return;
166   }
167   if (anOffsetHilighted)
168     glPolygonOffset(1.f, static_cast<GLfloat>(anOffsetHilighted));
169
170 // myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
171 // glColor3d (aValue[0], aValue[1], aValue[2]);
172     switch (myPolygonType) {
173       default:
174       case NIS_Triangulated::Polygon_Default:
175         if (myIsDrawPolygons) {
176       case NIS_Triangulated::Polygon_Line:
177           glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
178         } else {
179       case NIS_Triangulated::Polygon_Fill:
180           glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
181         }
182     }
183   glEnableClientState (GL_VERTEX_ARRAY);
184   glLineWidth (aLineWidth);
185   glShadeModel(GL_FLAT);
186   glDisable(GL_LIGHTING);
187 }
188
189 //=======================================================================
190 //function : AfterDraw
191 //purpose  :
192 //=======================================================================
193
194 void NIS_TriangulatedDrawer::AfterDraw (const DrawType      theType,
195                                         const NIS_DrawList&)
196 {
197   switch (theType) {
198     case Draw_Hilighted:
199     case Draw_DynHilighted:
200     switch (myPolygonType) {
201       default:
202       case NIS_Triangulated::Polygon_Default:
203         if (myIsDrawPolygons) {
204       case NIS_Triangulated::Polygon_Line:
205           glDisable(GL_POLYGON_OFFSET_LINE);
206         } else {
207       case NIS_Triangulated::Polygon_Fill:
208           glDisable(GL_POLYGON_OFFSET_FILL);
209         }
210     }
211     case Draw_Normal:
212     case Draw_Top:
213     case Draw_Transparent:
214       glDisableClientState(GL_VERTEX_ARRAY);
215       if (myTransparency > 0.01)
216         glDisable(GL_BLEND);
217     default:;
218   }
219   if (myPolygonType == NIS_Triangulated::Polygon_Line ||
220       (myPolygonType == NIS_Triangulated::Polygon_Default && myIsDrawPolygons))
221     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
222 }
223
224 //=======================================================================
225 //function : Draw
226 //purpose  :
227 //=======================================================================
228
229 void NIS_TriangulatedDrawer::Draw (const Handle(NIS_InteractiveObject)& theObj,
230                                    const DrawType                   /*theType*/,
231                                    const NIS_DrawList&)
232 {
233   // Assertion for the type of the drawn object
234 #ifdef _DEBUG
235   static const Handle(Standard_Type) ThisType = STANDARD_TYPE(NIS_Triangulated);
236   if (theObj->IsKind(ThisType) == Standard_False)
237     Standard_ProgramError::Raise ("NIS_Triangulated::Draw: "
238                                   "irrelevant object type");
239 #endif
240   const NIS_Triangulated * pObject =
241     static_cast <const NIS_Triangulated *> (theObj.operator->());
242   glVertexPointer (pObject->myNodeCoord, GL_FLOAT, 0, pObject->Node(0));
243
244   GLenum aType = GL_UNSIGNED_INT;
245   if (pObject->myIndexType == 0)
246     aType = GL_UNSIGNED_BYTE;
247   else if (pObject->myIndexType == 1)
248     aType = GL_UNSIGNED_SHORT;
249
250   if (myIsDrawPolygons == Standard_False) {
251     if (pObject->IsTriangulation()) {
252       glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
253                       aType, pObject->mypTriangles);
254     }
255   } else {
256     if (pObject->IsPolygons()) {
257       GLenum aMode = GL_POLYGON;
258       if (myPolygonAsLineLoop &&
259           (myPolygonType == NIS_Triangulated::Polygon_Line ||
260            (myPolygonType == NIS_Triangulated::Polygon_Default &&
261             myIsDrawPolygons)))
262         aMode = GL_LINE_LOOP;
263       const Standard_Integer nPoly = pObject->NPolygons();
264       for (Standard_Integer i = 0; i < nPoly; i++) {
265         const Standard_Integer nSize = pObject->NPolygonNodes(i);
266         void* anArray;
267         if (pObject->myIndexType == 0)
268           anArray = reinterpret_cast<unsigned char *>(pObject->mypPolygons[i]) + 1;
269         else if (pObject->myIndexType == 1)
270           anArray = reinterpret_cast<unsigned short *>(pObject->mypPolygons[i]) + 1;
271         else
272           anArray = pObject->mypPolygons[i] + 1;
273         glDrawElements (aMode, nSize, aType, anArray);
274       }
275     }
276   }
277   if (pObject->IsSegments())
278     glDrawElements (GL_LINES, pObject->NLineNodes(),
279                     aType, pObject->mypLines);
280   else {
281     Standard_Boolean isLoop;
282     if (pObject->IsLine(isLoop))
283     {
284       if (isLoop) {
285 //         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
286         glDrawElements (GL_LINE_LOOP, pObject->NLineNodes(),
287                         aType, pObject->mypLines);
288 //         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
289       } else {
290         glDrawElements (GL_LINE_STRIP, pObject->NLineNodes(),
291                         aType, pObject->mypLines);
292       }
293     }
294   }
295
296 }
297