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