0023544: Texture management in TKOpenGl should be redesigned
[occt.git] / src / OpenGl / OpenGl_Polygon.cxx
... / ...
CommitLineData
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
38struct EXTRA_VERTEX
39{
40 GLfloat vert[3];
41 int ind;
42 DEFINE_STANDARD_ALLOC
43};
44typedef EXTRA_VERTEX* extra_vertex;
45
46struct SEQ_
47{
48 NCollection_Vector<void *> tmesh_sequence;
49 GLenum triangle_type; /* FSXXX OPTI */
50 DEFINE_STANDARD_ALLOC
51};
52
53static void bgntriangulate( const TEL_POLYGON_DATA *, void (APIENTRY*)() );
54static 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
71void 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
152static const TEL_POLYGON_DATA *DaTa;
153static GLUtesselator *tripak = 0;
154
155STATIC void APIENTRY
156out_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
174STATIC void APIENTRY
175out_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
196STATIC void APIENTRY
197out_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
219STATIC void APIENTRY
220out_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
242STATIC void APIENTRY
243mycombine( 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
256STATIC void APIENTRY
257out_endtmesh( void )
258{
259 glEnd();
260}
261
262/*----------------------------------------------------------------------*/
263
264STATIC void APIENTRY
265out_error( GLenum error )
266{
267 printf( "POLYGON : %s\n", (char *) gluErrorString(error) );
268}
269
270/*----------------------------------------------------------------------*/
271
272static void
273bgntriangulate(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
296static void
297endtriangulate()
298{
299 DaTa = 0;
300 gluDeleteTess(tripak);
301}
302
303/*----------------------------------------------------------------------*/
304
305void 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
393void 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
430void 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
495OpenGl_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
546OpenGl_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
578void 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
626void OpenGl_Polygon::Release (const Handle(OpenGl_Context)& theContext)
627{
628 //
629}