0023630: Incorrect NULL check in OpenGl_Workspace::EnableTexture()
[occt.git] / src / OpenGl / OpenGl_Polygon.cxx
1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-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 #include <OpenGl_GlCore11.hxx>
21
22 #include <OpenGl_Polygon.hxx>
23
24 #include <OpenGl_telem_util.hxx>
25
26 #include <OpenGl_AspectFace.hxx>
27 #include <OpenGl_Structure.hxx>
28 #include <OpenGl_Workspace.hxx>
29
30 #include <GL/glu.h>
31
32 #if (defined(_WIN32) || defined(__WIN32__))
33   #define STATIC
34 #else
35   #define STATIC static
36 #endif
37
38 struct EXTRA_VERTEX
39 {
40   GLfloat vert[3];
41   int ind;
42   DEFINE_STANDARD_ALLOC
43 };
44 typedef EXTRA_VERTEX* extra_vertex;
45
46 struct SEQ_
47 {
48   NCollection_Vector<void *> tmesh_sequence;
49   GLenum triangle_type; /* FSXXX OPTI */
50   DEFINE_STANDARD_ALLOC
51 };
52
53 static void bgntriangulate( const TEL_POLYGON_DATA *, void (APIENTRY*)() );
54 static void endtriangulate(void);
55
56 #ifndef GLU_VERSION_1_2
57   #define GLUtesselator GLUtriangulatorObj
58   void gluTessBeginContour();
59   void gluTessBeginPolygon();
60   void gluTessEndPolygon();
61   void gluTessEndContour();
62   #define GLU_TESS_BEGIN   100100
63   #define GLU_TESS_VERTEX  100101
64   #define GLU_TESS_END     100102
65   #define GLU_TESS_ERROR   100103
66   #define GLU_TESS_COMBINE 100105
67 #endif
68
69 /*----------------------------------------------------------------------*/
70
71 void OpenGl_Polygon::draw_polygon (const Handle(OpenGl_Workspace) &AWorkspace, Tint front_lighting_model) const
72 {
73   Tint      i;
74
75   tel_point ptr;
76   tel_point  pvn;
77   tel_colour pfc, pvc;
78   tel_texture_coord pvt;
79
80   pfc = myData.fcolour;
81   pvc = myData.vcolours;
82   pvn = myData.vnormals;
83   pvt = myData.vtexturecoord;
84
85   if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
86     pvc = pfc = NULL;
87
88   ptr = myData.vertices;
89   if ( pfc )
90     glColor3fv( pfc->rgb );
91   if ( front_lighting_model )
92     glNormal3fv( myData.fnormal.xyz );
93
94   if( myData.reverse_order ) glFrontFace( GL_CW );
95
96   if (myData.num_vertices == 3) glBegin(GL_TRIANGLES);
97   else if(myData.num_vertices == 4) glBegin(GL_QUADS);
98   else glBegin(GL_POLYGON);
99   if( front_lighting_model )
100   {
101     if( pvn )
102     {
103       if (pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
104         for( i=0; i<myData.num_vertices; i++, ptr++ )
105         {
106           glNormal3fv( pvn[i].xyz );
107           glTexCoord2fv( pvt[i].xy );
108           glVertex3fv( ptr->xyz );
109         }
110       else
111         for( i=0; i<myData.num_vertices; i++, ptr++ )
112         {
113           glNormal3fv( pvn[i].xyz );
114           glVertex3fv( ptr->xyz );
115         }
116     }
117     else
118     {
119       for( i=0; i<myData.num_vertices; i++, ptr++ )
120       {
121         glVertex3fv( ptr->xyz );
122       }
123     }
124   }
125   else
126   {
127     if( pvc )
128     {
129       for( i=0; i<myData.num_vertices; i++, ptr++ )
130       {
131         glColor3fv( pvc[i].rgb );
132         glVertex3fv( ptr->xyz );
133       }
134     }
135     else
136     {
137       for( i=0; i<myData.num_vertices; i++, ptr++ )
138       {
139         glVertex3fv( ptr->xyz );
140       }
141     }
142   }
143   glEnd();
144   if( myData.reverse_order ) glFrontFace( GL_CCW );
145
146 }
147
148 /*----------------------------------------------------------------------*/
149
150 /* JWR - allow varying the size */
151
152 static const TEL_POLYGON_DATA *DaTa;
153 static GLUtesselator *tripak = 0;
154
155 STATIC void APIENTRY
156 out_bgntmesh( GLenum triangle_type )
157 {
158   NCollection_Vector<SEQ_> *dis = DaTa->dsply;
159
160   SEQ_ aSeq;
161 #ifdef JWR_DEC_TRIFAN_BUG
162   aSeq.triangle_type = GL_POLYGON;
163   dis->Append(aSeq);
164   glBegin(GL_POLYGON);
165 #else
166   aSeq.triangle_type = triangle_type;
167   dis->Append(aSeq);
168   glBegin(triangle_type);
169 #endif
170 }
171
172 /*----------------------------------------------------------------------*/
173
174 STATIC void APIENTRY
175 out_vert1( void *data )
176 {
177   SEQ_ &s = DaTa->dsply->ChangeValue(DaTa->dsply->Length() - 1);
178
179   s.tmesh_sequence.Append(data);
180
181   if ( data < (void *)0xffff ) {
182     long a = (long)data;
183
184     glVertex3fv( DaTa->vertices[a].xyz );
185   }
186   else {
187     extra_vertex b = (extra_vertex) data;
188
189     glVertex3fv( b->vert );
190   }
191
192 }
193
194 /*----------------------------------------------------------------------*/
195
196 STATIC void APIENTRY
197 out_vert2( void *data )
198 {
199   SEQ_ &s = DaTa->dsply->ChangeValue(DaTa->dsply->Length() - 1);
200
201   s.tmesh_sequence.Append(data);
202
203   if ( data < (void *)0xffff ) {
204     long a = (long)data;
205
206     glColor3fv( DaTa->vcolours[a].rgb );
207     glVertex3fv(  DaTa->vertices[a].xyz );
208   }
209   else {
210     extra_vertex b = (extra_vertex) data;
211
212     glColor3fv( DaTa->vcolours[(b->ind)].rgb );
213     glVertex3fv( b->vert );
214   }
215 }
216
217 /*----------------------------------------------------------------------*/
218
219 STATIC void APIENTRY
220 out_vert3( void *data )
221 {
222   SEQ_ &s = DaTa->dsply->ChangeValue(DaTa->dsply->Length() - 1);
223
224   s.tmesh_sequence.Append(data);
225
226   if ( data <= (void *)0xffff ) {
227     long a = (long)data;
228
229     glNormal3fv(  DaTa->vnormals[a].xyz );
230     glVertex3fv(  DaTa->vertices[a].xyz);
231   }
232   else {
233     extra_vertex b = (extra_vertex) data;
234
235     glNormal3fv(  DaTa->vnormals[(b->ind)].xyz );
236     glVertex3fv( b->vert );
237   }
238 }
239
240 /*----------------------------------------------------------------------*/
241
242 STATIC void APIENTRY
243 mycombine( GLdouble coords[3], int *data, GLfloat w[4], void **dataout)
244 {
245   extra_vertex new_vertex = new EXTRA_VERTEX();
246
247   new_vertex->vert[0] = ( float )coords[0];
248   new_vertex->vert[1] = ( float )coords[1];
249   new_vertex->vert[2] = ( float )coords[2];
250   new_vertex->ind =   *data;
251   *dataout = new_vertex;
252 }
253
254 /*----------------------------------------------------------------------*/
255
256 STATIC void APIENTRY
257 out_endtmesh( void )
258 {
259   glEnd();
260 }
261
262 /*----------------------------------------------------------------------*/
263
264 STATIC void APIENTRY
265 out_error( GLenum error )
266 {
267   printf( "POLYGON : %s\n", (char *) gluErrorString(error) );
268 }
269
270 /*----------------------------------------------------------------------*/
271
272 static void
273 bgntriangulate(const TEL_POLYGON_DATA *d, void ( APIENTRY * out_ver)() )
274 {
275   DaTa = d;
276
277   tripak = gluNewTess();
278
279 #if defined(linux) && !defined(NOGLUfuncptr)
280   gluTessCallback( tripak, GLU_TESS_BEGIN, (_GLUfuncptr)(out_bgntmesh) );
281   gluTessCallback( tripak, GLU_TESS_VERTEX, out_ver );
282   gluTessCallback( tripak, GLU_TESS_END, out_endtmesh );
283   gluTessCallback( tripak, GLU_TESS_ERROR, (_GLUfuncptr)(out_error) );
284   gluTessCallback( tripak, GLU_TESS_COMBINE, (_GLUfuncptr)(mycombine) );
285 #else
286   gluTessCallback( tripak, GLU_TESS_BEGIN, (void (APIENTRY*)())out_bgntmesh );
287   gluTessCallback( tripak, GLU_TESS_VERTEX, (void (APIENTRY*)())out_ver );
288   gluTessCallback( tripak, GLU_TESS_END, (void (APIENTRY*)())out_endtmesh );
289   gluTessCallback( tripak, GLU_TESS_ERROR, (void (APIENTRY*)())out_error );
290   gluTessCallback( tripak, GLU_TESS_COMBINE, (void (APIENTRY*)())mycombine );
291 #endif
292 }
293
294 /*----------------------------------------------------------------------*/
295
296 static void
297 endtriangulate()
298 {
299   DaTa = 0;
300   gluDeleteTess(tripak);
301 }
302
303 /*----------------------------------------------------------------------*/
304
305 void OpenGl_Polygon::draw_polygon_concav (const Handle(OpenGl_Workspace) &AWorkspace, Tint front_lighting_model) const
306 {
307   long       i;
308
309   tel_point  pvn;
310   tel_point  ptr;
311   tel_colour pfc, pvc;
312   GLdouble  xyz[3];
313
314   pfc = myData.fcolour;
315   pvc = myData.vcolours;
316   pvn = myData.vnormals;
317
318   if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
319     pvc = pfc = NULL;
320
321   ptr = myData.vertices;
322   DaTa = &myData;
323
324   if ( pfc )
325     glColor3fv( pfc->rgb );
326   if ( front_lighting_model )
327     glNormal3fv( myData.fnormal.xyz );
328
329   if( myData.reverse_order ) glFrontFace( GL_CW );
330
331   if( !myData.dsply )
332   {
333     if( front_lighting_model )
334     {
335       if( pvn )
336       {
337         bgntriangulate(&myData, (void (APIENTRY*)())out_vert3);
338       }
339       else
340       {
341         bgntriangulate(&myData, (void (APIENTRY*)())out_vert1);
342       }
343     }
344     else
345     {
346       if( pvc )
347       {
348         bgntriangulate(&myData, (void (APIENTRY*)())out_vert2);
349       }
350       else
351       {
352         bgntriangulate(&myData, (void (APIENTRY*)())out_vert1);
353       }
354     }
355     gluTessBeginPolygon( tripak, NULL );
356     gluTessBeginContour( tripak);
357
358     for( i=0; i<myData.num_vertices; i++, ptr++ )
359     {
360       xyz[0] = ptr->xyz[0];
361       xyz[1] = ptr->xyz[1];
362       xyz[2] = ptr->xyz[2];
363 #ifndef WNT
364       gluTessVertex( tripak, xyz,(void * ) i );
365 #else
366       {
367         double v[ 3 ] = {ptr -> xyz[ 0 ], ptr -> xyz[ 1 ], ptr -> xyz[ 2 ]};
368         gluTessVertex (  tripak,  v, ( void* )i  );
369       }
370 #endif  /* WNT */
371     }
372     gluTessEndContour( tripak );
373     gluTessEndPolygon( tripak );
374     endtriangulate();
375   }
376   else
377   {
378     if( front_lighting_model )
379     {
380       draw_tmesh( pvn? 3 : 1 );
381     }
382     else
383     {
384       draw_tmesh( pvc? 2 : 1 );
385     }
386   }
387
388   if( myData.reverse_order ) glFrontFace( GL_CCW );
389 }
390
391 /*----------------------------------------------------------------------*/
392
393 void OpenGl_Polygon::draw_edges (const TEL_COLOUR*               theEdgeColor,
394                                  const Aspect_InteriorStyle      theInteriorStyle,
395                                  const Handle(OpenGl_Workspace)& theWorkspace) const
396 {
397   const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
398
399   if (theInteriorStyle != Aspect_IS_HIDDENLINE
400    && anAspectFace->Edge == TOff)
401   {
402     return;
403   }
404
405   glDisable (GL_LIGHTING);
406   const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
407
408   // Setup line aspect
409   const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->SetAspectLine (anAspectFace->AspectEdge());
410   theWorkspace->AspectLine (Standard_True);
411
412   glColor3fv (theEdgeColor->rgb);
413
414   glBegin (GL_LINE_LOOP);
415   tel_point ptr = myData.vertices;
416   for (Tint i = 0; i < myData.num_vertices; i++, ptr++)
417   {
418     glVertex3fv (ptr->xyz);
419   }
420   glEnd();
421
422   // Restore line context
423   theWorkspace->SetAspectLine (aPrevAspectLine);
424
425   theWorkspace->EnableTexture (aPrevTexture);
426 }
427
428 /*----------------------------------------------------------------------*/
429
430 void OpenGl_Polygon::draw_tmesh ( Tint v ) const
431 {
432   Tint      i, j, k;
433   SEQ_     *s;
434   extra_vertex b;
435
436   NCollection_Vector<SEQ_> *dis = myData.dsply;
437   for( i = 0; i < dis->Length(); i++ )
438   {
439     s = &(dis->ChangeValue(i));
440
441     glBegin(s->triangle_type);
442     switch( v )
443     {
444     case 1:
445       {
446         for( j = 0, k = 0; j < s->tmesh_sequence.Length(); j++ )
447         {
448           if ( s->tmesh_sequence(j) < (void *)0xffff )
449             glVertex3fv( myData.vertices[ (long)s->tmesh_sequence.Value(j) ].xyz );
450           else {
451             b = (extra_vertex) s->tmesh_sequence(j);
452             glVertex3fv( b->vert );
453           }
454
455         }
456         break;
457       }
458     case 2:
459       {
460         for( j = 0, k = 0; j < s->tmesh_sequence.Length(); j++ )
461         {
462           if ( s->tmesh_sequence(j) < (void *)0xffff ) {
463             glColor3fv( myData.vcolours[ (long) s->tmesh_sequence(j) ].rgb );
464             glVertex3fv( myData.vertices[ (long) s->tmesh_sequence(j) ].xyz );
465           } else {
466             b = (extra_vertex) s->tmesh_sequence(j);
467             glColor3fv( myData.vcolours[(b->ind)].rgb);
468             glVertex3fv( b->vert );
469           }
470         }
471         break;
472       }
473     case 3:
474       {
475         for( j = 0, k = 0; j < s->tmesh_sequence.Length(); j++ )
476         {
477           if ( s->tmesh_sequence(j) < (void *)0xffff ) {
478             glNormal3fv( myData.vnormals[ (long) s->tmesh_sequence(j) ].xyz);
479             glVertex3fv( myData.vertices[ (long) s->tmesh_sequence(j) ].xyz);
480           } else {
481             b = (extra_vertex) s->tmesh_sequence(j);
482             glNormal3fv( myData.vnormals[(b->ind)].xyz);
483             glVertex3fv( b->vert );
484           }
485         }
486         break;
487       }
488     }
489     glEnd();
490   }
491 }
492
493 /*----------------------------------------------------------------------*/
494
495 OpenGl_Polygon::OpenGl_Polygon (const Graphic3d_Array1OfVertex& AListVertex,
496                               const Graphic3d_TypeOfPolygon AType)
497 {
498   const Standard_Integer nv = AListVertex.Length();
499
500   myData.num_vertices = nv;
501
502   myData.vertices = new TEL_POINT[nv];
503   memcpy( myData.vertices, &AListVertex(AListVertex.Lower()), nv*sizeof(TEL_POINT) );
504
505   myData.vertex_flag = TEL_VT_NONE;
506   myData.vnormals = NULL;
507
508   myData.vcolours = NULL;
509
510   myData.vtexturecoord = NULL;
511
512   myData.reverse_order = 0;
513
514   myData.facet_flag = TEL_FA_NONE;
515   TelGetPolygonNormal( myData.vertices, NULL, nv, myData.fnormal.xyz );
516
517   myData.fcolour = NULL;
518
519 #if defined(__sgi) || defined(IRIX)
520   // Pb with tesselator on sgi
521   myData.shape_flag = TEL_SHAPE_CONVEX;
522 #else
523   switch (AType)
524   {
525     case Graphic3d_TOP_UNKNOWN :
526       myData.shape_flag = TEL_SHAPE_UNKNOWN;
527       break;
528     case Graphic3d_TOP_COMPLEX :
529       myData.shape_flag = TEL_SHAPE_COMPLEX;
530       break;
531     case Graphic3d_TOP_CONCAVE :
532       myData.shape_flag = TEL_SHAPE_CONCAVE;
533       break;
534     //case Graphic3d_TOP_CONVEX :
535     default :
536       myData.shape_flag = TEL_SHAPE_CONVEX;
537       break;
538   }
539 #endif
540
541   myData.dsply = new NCollection_Vector<SEQ_>();
542 }
543
544 /*----------------------------------------------------------------------*/
545
546 OpenGl_Polygon::~OpenGl_Polygon ()
547 {
548   if( myData.fcolour )
549     delete myData.fcolour;
550   if( myData.vertices )
551     delete[] myData.vertices;
552   if( myData.vcolours )
553     delete[] myData.vcolours;
554   if( myData.vnormals )
555     delete[] myData.vnormals;
556   if ( myData.vtexturecoord )
557     delete myData.vtexturecoord;
558
559   if ( myData.dsply )
560   {
561     Tint i, j;
562
563     for( i = 0; i <  myData.dsply->Length(); i++ )
564     {
565       for ( j = 0; j < myData.dsply->Value(i).tmesh_sequence.Length() ; j++ )
566       {
567         if ( myData.dsply->Value(i).tmesh_sequence(j) >= (void *)0xffff )
568           delete myData.dsply->Value(i).tmesh_sequence(j);
569       }
570     }
571
572     delete myData.dsply;
573   }
574 }
575
576 /*----------------------------------------------------------------------*/
577
578 void OpenGl_Polygon::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
579 {
580   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
581
582   Tint front_lighting_model = aspect_face->IntFront.color_mask;
583   const Aspect_InteriorStyle interior_style = aspect_face->InteriorStyle;
584   const TEL_COLOUR *interior_colour = &aspect_face->IntFront.matcol;
585   const TEL_COLOUR *edge_colour = &aspect_face->AspectEdge()->Color();
586
587   // Use highlight colous
588   if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
589   {
590     edge_colour = interior_colour = AWorkspace->HighlightColor;
591     front_lighting_model = 0;
592   }
593
594   if( interior_style != Aspect_IS_EMPTY && AWorkspace->DegenerateModel < 2 )
595   {
596     if ( front_lighting_model )
597       glEnable(GL_LIGHTING);
598     else
599       glDisable(GL_LIGHTING);
600
601     glColor3fv( interior_colour->rgb );
602
603     if( myData.shape_flag != TEL_SHAPE_CONVEX )
604       draw_polygon_concav( AWorkspace, front_lighting_model );
605     else
606       draw_polygon( AWorkspace, front_lighting_model );
607   }
608
609   /* OCC11904 -- Temporarily disable environment mapping */
610   glPushAttrib(GL_ENABLE_BIT);
611   glDisable(GL_TEXTURE_1D);
612   glDisable(GL_TEXTURE_2D);
613
614   switch ( AWorkspace->DegenerateModel )
615   {
616     default:
617       draw_edges ( edge_colour, interior_style, AWorkspace );
618       break;
619     case 3:  /* marker degeneration */
620       break;
621   }
622
623   glPopAttrib(); /* skt: GL_ENABLE_BIT*/
624 }
625
626 void OpenGl_Polygon::Release (const Handle(OpenGl_Context)& theContext)
627 {
628   //
629 }