0023715: Generated cmake files should link against Cocoa on Mac OS X
[occt.git] / src / NIS / NIS_SurfaceDrawer.cxx
1 // Created on: 2008-03-20
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2008-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_SurfaceDrawer.hxx>
22 #include <NIS_Surface.hxx>
23 #include <NIS_InteractiveObject.hxx>
24 #include <Standard_ProgramError.hxx>
25
26 #include <OpenGl_GlCore11.hxx>
27
28 static void setColor(GLenum               theFace,
29                      Quantity_Parameter * theAmbient,
30                      const Standard_Real  theSpecularity,
31                      GLint                theShininess);
32
33 IMPLEMENT_STANDARD_HANDLE  (NIS_SurfaceDrawer, NIS_Drawer)
34 IMPLEMENT_STANDARD_RTTIEXT (NIS_SurfaceDrawer, NIS_Drawer)
35
36 //=======================================================================
37 //function : NIS_SurfaceDrawer()
38 //purpose  : Constructor
39 //=======================================================================
40
41 NIS_SurfaceDrawer::NIS_SurfaceDrawer
42                                 (const Quantity_Color   &theNormal,
43                                  const Quantity_Color   &theHilight,
44                                  const Quantity_Color   &theDynHilight)
45   : myBackColor     (theNormal),
46     myPolygonOffset (0.f),
47     myIsWireframe   (Standard_False)
48 {
49   myColor[Draw_Normal]       = theNormal;
50   myColor[Draw_Top]          = theNormal;
51   myColor[Draw_Transparent]  = theNormal;
52   myColor[Draw_Hilighted]    = theHilight;
53   myColor[Draw_DynHilighted] = theDynHilight;
54 }
55
56 //=======================================================================
57 //function : SetColor
58 //purpose  :
59 //=======================================================================
60
61 void NIS_SurfaceDrawer::SetColor(const Quantity_Color &theColor)
62 {
63   myColor[Draw_Normal]      = theColor;
64   myColor[Draw_Top]         = theColor;
65   myColor[Draw_Transparent] = theColor;
66 }
67
68 //=======================================================================
69 //function : Assign
70 //purpose  :
71 //=======================================================================
72
73 void NIS_SurfaceDrawer::Assign (const Handle_NIS_Drawer& theOther)
74 {
75   if (theOther.IsNull() == Standard_False) {
76     NIS_Drawer::Assign (theOther);
77     const Handle(NIS_SurfaceDrawer)& anOther =
78       static_cast <const Handle(NIS_SurfaceDrawer)&> (theOther);
79     myColor[Draw_Normal]       = anOther->myColor[Draw_Normal];
80     myColor[Draw_Top]          = anOther->myColor[Draw_Top];
81     myColor[Draw_Transparent]  = anOther->myColor[Draw_Transparent];
82     myColor[Draw_Hilighted]    = anOther->myColor[Draw_Hilighted];
83     myColor[Draw_DynHilighted] = anOther->myColor[Draw_DynHilighted];
84     myBackColor                = anOther->myBackColor;
85     myPolygonOffset            = anOther->myPolygonOffset;
86     myIsWireframe              = anOther->myIsWireframe;
87   }
88 }
89
90 //=======================================================================
91 //function : IsEqual
92 //purpose  : Comparison of two Drawers (for Map impementation)
93 //=======================================================================
94
95 Standard_Boolean NIS_SurfaceDrawer::IsEqual
96                                 (const Handle_NIS_Drawer& theOther)const
97 {
98   static const Standard_Real       anEpsilon2 (1e-7);
99   Standard_Boolean                 aResult (Standard_False);
100   const Handle(NIS_SurfaceDrawer) anOther =
101                         Handle(NIS_SurfaceDrawer)::DownCast (theOther);
102   if (NIS_Drawer::IsEqual(theOther))
103     aResult = (anOther->myColor[Draw_Normal]
104                .SquareDistance (myColor[Draw_Normal]) < anEpsilon2 &&
105                anOther->myColor[Draw_Hilighted]
106                .SquareDistance (myColor[Draw_Hilighted]) < anEpsilon2 &&
107                anOther->myColor[Draw_DynHilighted]
108                .SquareDistance (myColor[Draw_DynHilighted]) < anEpsilon2 &&
109                anOther->myBackColor.SquareDistance(myBackColor) < anEpsilon2 &&
110                fabs(anOther->myPolygonOffset - myPolygonOffset) < 0.999 &&
111                myIsWireframe == anOther->myIsWireframe);
112   if (aResult) {
113     // Arbitrary point for test
114     gp_XYZ aPnt[2] = {
115       gp_XYZ(113., -31.3, 29.19),
116       gp_XYZ(113., -31.3, 29.19)
117     };
118     anOther->myTrsf.Transforms(aPnt[0]);
119     myTrsf.Transforms(aPnt[1]);
120     if ((aPnt[0] - aPnt[1]).SquareModulus() > anEpsilon2)
121       aResult = Standard_False;
122   }
123   return aResult;
124 }
125
126 //=======================================================================
127 //function : redraw
128 //purpose  :
129 //=======================================================================
130
131 void NIS_SurfaceDrawer::redraw  (const DrawType         theType,
132                                  const Handle_NIS_View& theView)
133 {
134   glMatrixMode( GL_MODELVIEW );
135   glPushMatrix();
136
137   GLdouble aMatrix[16] = {
138     myTrsf.Value(1,1), myTrsf.Value(2,1), myTrsf.Value(3,1),  0.,
139     myTrsf.Value(1,2), myTrsf.Value(2,2), myTrsf.Value(3,2),  0.,
140     myTrsf.Value(1,3), myTrsf.Value(2,3), myTrsf.Value(3,3),  0.,
141     myTrsf.Value(1,4), myTrsf.Value(2,4), myTrsf.Value(3,4),  1.
142   };
143
144   glMultMatrixd( aMatrix );
145
146   NIS_Drawer::redraw(theType, theView);
147
148   glPopMatrix();
149 }
150
151 //=======================================================================
152 //function : BeforeDraw
153 //purpose  :
154 //=======================================================================
155
156 void NIS_SurfaceDrawer::BeforeDraw (const DrawType      theType,
157                                     const NIS_DrawList&)
158 {
159   glEnable(GL_LIGHTING);
160   //  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
161   glEnableClientState (GL_VERTEX_ARRAY);
162   if (myIsWireframe == Standard_False) {
163     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
164     glEnable(GL_POLYGON_OFFSET_FILL);
165     glShadeModel(GL_SMOOTH);
166   }
167
168   Quantity_Parameter   aValueCol[4] = {0., 0., 0., 1.};
169   Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
170   GLfloat aLineWidth (1.f);
171   GLfloat anOffset = myPolygonOffset;
172   static const GLfloat gColorN[4]  = {0.f, 0.f, 0.f, 1.f};
173
174   switch (theType) {
175   case Draw_DynHilighted:
176     aLineWidth = 3.f;
177     myColor[theType].Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
178     setColor(GL_FRONT_AND_BACK, &aValueCol[0], 0.1, 5);
179     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &gColorN[0]);
180     glLineWidth (aLineWidth);
181     if (myIsWireframe == Standard_False)
182       glPolygonOffset(1.f, -(anOffset + 11.f));
183     return;
184   case Draw_Hilighted:
185     anOffset += 10.f;
186   case Draw_Normal:
187   case Draw_Top:
188   case Draw_Transparent:
189     if (myIsWireframe == Standard_False) {
190       glPolygonOffset(1.f, -anOffset);
191       glEnableClientState (GL_NORMAL_ARRAY);
192     }
193     myColor[theType].Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
194     aValueCol[3] = 1. - myTransparency;
195     if (theType == Draw_Transparent) {
196       glEnable(GL_BLEND);
197       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
198       // don't write triangles into depth test
199       glDepthMask(GL_FALSE);
200     }
201     break;
202   default:
203     return;
204   }
205   //  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
206   if (theType == Draw_Hilighted ||
207       myBackColor.SquareDistance(myColor[Draw_Normal]) < 1.e-7)
208   {
209     setColor(GL_FRONT_AND_BACK, &aValueCol[0], 0.5, 10);
210   } else {
211     setColor(GL_FRONT, &aValueCol[0], 0.4, 10);
212     myBackColor.Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
213     setColor(GL_BACK, &aValueCol[0], 0.8, 5);
214   }
215   glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &gColorN[0]);
216   glLineWidth (aLineWidth);
217 }
218
219 //=======================================================================
220 //function : AfterDraw
221 //purpose  :
222 //=======================================================================
223
224 void NIS_SurfaceDrawer::AfterDraw (const DrawType      theType,
225                                    const NIS_DrawList&)
226 {
227   glDisable(GL_LIGHTING);
228   glDisableClientState(GL_VERTEX_ARRAY);
229   switch (theType) {
230     case Draw_Transparent:
231       glDisable(GL_BLEND);
232       glDepthMask(GL_TRUE);
233     case Draw_Hilighted:
234     case Draw_Normal:
235     case Draw_Top:
236       if (myIsWireframe == Standard_False)
237         glDisableClientState(GL_NORMAL_ARRAY);
238     default:;
239   }
240   if (myIsWireframe == Standard_False)
241     glDisable(GL_POLYGON_OFFSET_FILL);
242 }
243
244 //=======================================================================
245 //function : Draw
246 //purpose  :
247 //=======================================================================
248
249 void NIS_SurfaceDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
250                               const DrawType                      theType,
251                               const NIS_DrawList&)
252 {
253   // Assertion for the type of the drawn object
254 #ifdef _DEBUG
255   static const Handle(Standard_Type) ThisType = STANDARD_TYPE(NIS_Surface);
256   Standard_ProgramError_Raise_if (theObj->IsKind(ThisType) == Standard_False,
257                                   "NIS_Surface::Draw: irrelevant object type");
258 #endif
259   const NIS_Surface * pObject =
260     static_cast <const NIS_Surface *> (theObj.operator->());
261   glVertexPointer (3, GL_FLOAT, 0, pObject->Node(0));
262
263   // In Highlited mode the shape must be shown as wireframe
264   Standard_Boolean isWireframe(myIsWireframe);
265   if (isWireframe == Standard_False && theType == Draw_DynHilighted)
266     if (pObject->NEdges() > 0)
267       isWireframe = Standard_True;
268
269   if (isWireframe)
270   {
271     for (Standard_Integer i = 0; i < pObject->NEdges(); i++) {
272       const GLint * pEdge = static_cast<const GLint *> (pObject->Edge(i));
273       glDrawElements (GL_LINE_STRIP, pEdge[0], GL_UNSIGNED_INT, &pEdge[1]);
274     }
275   } else {
276     if (pObject->NTriangles()) {
277       if (theType != Draw_DynHilighted)
278         glNormalPointer (GL_FLOAT, 0, pObject->Normal(0));
279       glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
280                       GL_UNSIGNED_INT, pObject->Triangle(0));
281     }
282   }
283 }
284
285 //=======================================================================
286 //function : setColor
287 //purpose  :
288 //=======================================================================
289
290 void setColor(GLenum               theFace,
291               Quantity_Parameter * theAmbient,
292               const Standard_Real  theSpecularity,
293               GLint                theShininess)
294 {
295   GLfloat aSpec = static_cast<GLfloat>(theSpecularity);
296   GLfloat aValueCol[4] = {
297     GLfloat(theAmbient[0]),
298     GLfloat(theAmbient[1]),
299     GLfloat(theAmbient[2]),
300     GLfloat(theAmbient[3])
301   };
302   glMaterialfv(theFace, GL_AMBIENT_AND_DIFFUSE, &aValueCol[0]);
303   aValueCol[0] = aSpec * (aValueCol[0] - 1.f) + 1.f;
304   aValueCol[1] = aSpec * (aValueCol[1] - 1.f) + 1.f;
305   aValueCol[2] = aSpec * (aValueCol[2] - 1.f) + 1.f;
306   aValueCol[3] = 1.f;
307   glMaterialfv(theFace, GL_SPECULAR, &aValueCol[0]);
308   glMateriali(theFace, GL_SHININESS, theShininess);
309 }
310