1Tessellation(3)       User Contributed Perl Documentation      Tessellation(3)
2
3
4

NAME

6       OpenGL::Tessellation - discussion of tessellation in POGL
7

SYNOPSIS

9           # somewhere in your drawing routine or drawlist compilation
10
11           my $tess = gluNewTess();
12
13           gluTessCallback($tess, GLU_TESS_BEGIN,     'DEFAULT');
14           gluTessCallback($tess, GLU_TESS_END,       'DEFAULT');
15           gluTessCallback($tess, GLU_TESS_VERTEX,    'DEFAULT');
16           gluTessCallback($tess, GLU_TESS_COMBINE,   'DEFAULT');
17           gluTessCallback($tess, GLU_TESS_ERROR,     'DEFAULT');
18           gluTessCallback($tess, GLU_TESS_EDGE_FLAG, 'DEFAULT');
19
20           gluTessBeginPolygon($tess);
21           gluTessBeginContour($tess);
22
23           gluTessVertex_p($tess, 0,     200, 0);
24           gluTessVertex_p($tess, 150,  -200, 0);
25           gluTessVertex_p($tess, 0,    -100, 0);
26           gluTessVertex_p($tess, -150, -200, 0);
27
28           gluTessEndContour($tess);
29           gluTessEndPolygon($tess);
30
31           gluDeleteTess($tess);
32

DESCRIPTION

34       OpenGL rendering hardware typically does not have support for drawing
35       concave polygons or drawing polygons with windows.  OpenGL provides glu
36       extentions that allow for translating concave polygon vertices into
37       triangles that can be rendered quickly on GL hardware.  The OpenGL red
38       book chapter 11 has the full discussion of Tessellators and the OpenGL
39       functions (http://glprogramming.com/red/chapter11.html, or use your
40       favorite search engine and search for "opengl gluNewTess").  It is a
41       good idea to read that chapter before reading the rest of this
42       document.
43
44       As much as possible, the POGL implementation of the tessellation
45       functions tries to remain faithful to the OpenGL specification.  Where
46       it doesn't match exactly, POGL follows the spirit of the specification,
47       but offloads what it can to c based implementations.
48
49       Tessellation functions are safe to call during drawlist creation.  It
50       is advisable to use drawlists, or to store the generated polygon data
51       into OpenGL::Array objects as these methods offer faster redraws.
52

FUNCTIONS

54       "gluNewTess"
55               my $tess = gluNewTess();
56
57           Returns a reference that can be passed to the remaining tesselation
58           functions.
59
60           Note: this isn't the c-reference returned by the normal
61           gluNewTess() c function, it is a struct which contains that
62           reference as well as other members allowing callbacks to interface
63           cleanly with the perl code.  This means that if you have loaded
64           other c-libraries that use standard opengl tessellation, you will
65           not be able to use this perl reference directly.
66
67           The POGL implementation of gluNewTess() allows for two additional
68           parameters to be passed.  The first is a boolean value indicating
69           that default c callbacks and perl callbacks should be passed rgba
70           color data.  The second is a boolean value indicating that xyz
71           normal data should be passed.  Eventually one additional flag
72           indicating that texture data should be passed will be added as
73           well.
74
75               my $tess = gluNewTess();
76               # gluTessVertex_p should be passed only x,y,z vertex data
77               # as in gluTessVertex_p($tess, $x, $y, $z);
78
79               my $tess = gluNewTess('do_colors');
80               # gluTessVertex_p should be passed x,y,z AND r,g,b,a vertex data
81               # as in gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a);
82
83               my $tess = gluNewTess('do_colors', 'do_normals');
84               # gluTessVertex_p should be passed x,y,z AND r,g,b,a AND nx,ny,nz vertex data
85               # as in gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a, $nx, $ny, $nz);
86
87               my $tess = gluNewTess(undef, 'do_normals');
88               # gluTessVertex_p should be passed x,y,z AND nx,ny,nz vertex data (no colors)
89               # as in gluTessVertex_p($tess, $x, $y, $z, $nx, $ny, $nz);
90
91           Any true value can be passed in place of 'do_colors' and
92           'do_normals' though using 'do_colors' and 'do_normals' acts as
93           documentation.
94
95           Behavior in these modes will be discussed further for functions to
96           which they apply.
97
98       "gluDeleteTess"
99               gluDeleteTess($tess);
100
101           This deletes the tessellation structure and frees up any remaining
102           associated memory.
103
104       "gluTessCallback"
105              gluTessCallback($tess, GLU_TESS_BEGIN, 'DEFAULT');
106
107              gluTessCallback($tess, GLU_TESS_BEGIN, \&glBegin);
108
109              gluTessCallback($tess, GLU_TESS_BEGIN, sub { my $enum = shift; glBegin($enum) });
110
111              gluTessCallback($tess, GLU_TESS_BEGIN);  # unsets current handler
112
113           Registers handlers for each of the tessellation callback types.
114           Takes a tessellation reference generated by gluNewTess, a type, and
115           a coderef or the word 'DEFAULT'.  If the word 'DEFAULT' is passed,
116           a default c-level callback will be installed (which will be
117           discussed for each callback).  If no 3rd argument is given, then
118           any handler currently set will be removed.  Valid callback types
119           are
120
121               GLU_TESS_BEGIN
122               GLU_TESS_END
123               GLU_TESS_VERTEX
124               GLU_TESS_COMBINE
125               GLU_TESS_ERROR
126               GLU_TESS_EDGE_FLAG
127
128               GLU_TESS_BEGIN_DATA
129               GLU_TESS_END_DATA
130               GLU_TESS_VERTEX_DATA
131               GLU_TESS_COMBINE_DATA
132               GLU_TESS_ERROR_DATA
133               GLU_TESS_EDGE_FLAG_DATA
134
135           These types and their passed parameters will be discussed in the
136           CALLBACKS section.
137
138           The types ending with "_DATA" are similar to their non-_DATA
139           counterpart, but when called are passed the option $polygon_data
140           that can be set during gluTessBeginPolygon.
141
142       "gluTessBeginPolygon"
143               gluTessBeginPolygon($tess);
144
145               gluTessBeginPolygon($tess, $polygon_data);
146
147           Begins the tessellation transaction.  It must eventually be ended
148           with a gluTessEndPolygon before the tessellator will normally begin
149           work.
150
151           An optional second argument can be passed which can be any perl
152           scalar or reference.  If a callback is registered using a type
153           ending in _DATA, this perl scalar or reference will be passed as an
154           additional argument to that callback.
155
156               gluTessCallback($tess, GLU_TESS_END_DATA, sub {
157                   my $polygon_data = shift;
158                   glEnd();
159                   print "glEnd: (".($polygon_data->[2] eq 8 ? "YES" : "NO").")\n";
160               });
161
162               gluTessBeginPoly($tess, [6,7,8]); # arrayref will be passed to _DATA callbacks
163
164           A sample Object Oriented tesselation sample listed at the end of
165           this document makes use of this "opaque" polygon data.
166
167       "gluTessEndPolygon"
168               gluTessEndPolygon($tess);
169
170           Finishes the tessellation transaction, which normally will
171           immediately fire the necessary callbacks generated by the
172           tessellation process.  Once finished, it cleans up any accumulated
173           temporary vertice data.
174
175       "gluTessBeginContour"
176               gluTessBeginContour($tess);
177
178           Starts a new contour of the tessellation of the current polygon.
179           Please read the OpenGL documentation, and red book chapter on
180           tessellation for more help on when to use different contours.
181           Should eventually be followed by a gluTessEndContour call.
182
183           (At a high level, tessellated polygons may have windows and
184           multiple separate portions.  Each inner and outer border of these
185           portions should be represented by a different contour.)
186
187       "gluTessVertex_p"
188               gluTessVertex_p($tess, $x, $y, $z);
189
190               gluTessVertex_p($tess, $x, $y, $z, $vertex_data);
191
192           Adds a vertex to the current contour of the current polygon being
193           tessellated.
194
195           If the vertex callback type is set to GLU_TESS_VERTEX, the optional
196           $vertex_data argument will be passed to the vertex callback, and to
197           the combine callback (if GLU_TESS_VERTEX_DATA is used, then the
198           $polygon_data passed to gluTessBeginPolygon will be passed
199           instead).  This optional opaque vertex data can be any perl scalar
200           or reference and can be used to pass useful information along
201           during the tessellation process.
202
203           If the 'do_colors' or 'do_normals' parameters were passed to
204           gluNewTess, then those additional properties MUST be passed as
205           additional arguments.
206
207               # my $tess = gluNewTess('do_colors');
208               gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a);
209               gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a, $vertex_data);
210
211               # my $tess = gluNewTess('do_colors', 'do_normals');
212               gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a, $nx, $ny, $nz);
213               gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a, $nx, $ny, $nz, $vertex_data);
214
215               # my $tess = gluNewTess(undef, 'do_normals');
216               gluTessVertex_p($tess, $x, $y, $z, $nx, $ny, $nz);
217               gluTessVertex_p($tess, $x, $y, $z, $nx, $ny, $nz, $vertex_data);
218

CALLBACKS

220       All of the callbacks support a 'DEFAULT' handler that can be installed
221       by passing the word 'DEFAULT' in place of the callback code reference.
222       The DEFAULT c implementations are there to avoid needing to round trip
223       out to perl.  The defaults employed are described for each of the
224       callback types.
225
226       With the exception of the COMBINE callback, return values from
227       callbacks are discarded.
228
229       "GLU_TESS_BEGIN"
230              gluTessCallback($tess, GLU_TESS_BEGIN, 'DEFAULT');
231
232              gluTessCallback($tess, GLU_TESS_BEGIN, \&glBegin);
233
234              gluTessCallback($tess, GLU_TESS_BEGIN, sub {
235                  my $enum = shift;
236                  glBegin($enum);
237              });
238
239           The 'DEFAULT' option installs a c-handler that calls the glBegin c
240           function directly without round-tripping out to perl.
241
242           If $polygon_data was set during gluTessBeginPolygon, it is
243           discarded.
244
245       "GLU_TESS_BEGIN_DATA"
246           Similar to GLU_TESS_BEGIN but will be passed optional $polygon_data
247           set in gluTessBeginPolygon if any.  The 'DEFAULT' handler will
248           ignore this data.
249
250              gluTessCallback($tess, GLU_TESS_BEGIN_DATA, sub {
251                  my ($enum, $polygon_data) = @_;
252                  glBegin($enum);
253                  print "glBegin - and I received polygon_data\n" if $polygon_data;
254              });
255
256       "GLU_TESS_END"
257              gluTessCallback($tess, GLU_TESS_END, 'DEFAULT');
258
259              gluTessCallback($tess, GLU_TESS_END, \&glEnd);
260
261              gluTessCallback($tess, GLU_TESS_END, sub { glEnd() });
262
263           The 'DEFAULT' option installs a c-handler that calls the glEnd c
264           function directly without round-tripping out to perl.
265
266           If $polygon_data was set during gluTessBeginPolygon, it is
267           discarded.
268
269       "GLU_TESS_END_DATA"
270           Similar to GLU_TESS_END but will be passed optional $polygon_data
271           set in gluTessBeginPolygon if any.  The 'DEFAULT' handler will
272           ignore this data.
273
274              gluTessCallback($tess, GLU_TESS_END_DATA, sub {
275                  my ($polygon_data) = @_;
276                  glEnd();
277                  print "glEnd - and I received polygon_data\n" if $polygon_data;
278              });
279
280       "GLU_TESS_VERTEX"
281           The GLU_TESS_VERTEX callback handler has slightly different
282           behavior depending on how gluNewTess was called.  The optional
283           behaviors allow for sane default processing of colors and normals
284           without needing to roundtrip out to perl.
285
286              my $tess = gluNewTess();
287
288              gluTessCallback($tess, GLU_TESS_VERTEX, 'DEFAULT');
289
290              # the following will break if vertex_data is passed to gluTessVertex_p
291              gluTessCallback($tess, GLU_TESS_VERTEX, \&glVertex3f);
292
293              gluTessCallback($tess, GLU_TESS_VERTEX, sub {
294                  my ($x, $y, $z) = @_;
295                  glVertex3f($x, $y, $z);
296              });
297
298              # you can also pass vertex_data to gluTessVertex_p
299              gluTessCallback($tess, GLU_TESS_VERTEX, sub {
300                  my ($x, $y, $z, $vertex_data) = @_;
301                  glVertex3f($x, $y, $z);
302                  print "glVertex - and I received vertex_data\n" if $vertex_data;
303              });
304
305           The 'DEFAULT' option installs a c-handler that calls the glVertex c
306           function directly without round-tripping out to perl.  The DEFAULT
307           handler discards any polygon_data or vertex_data.
308
309           IF $vertex_data was set during gluTessVertex_p it will be passed as
310           the final argument.
311
312           If gluNewTess was passed 'do_colors' then the GLU_TESS_VERTEX
313           callback will also be passed the rgba information.  The 'DEFAULT'
314           option will pass the color information to glColor4f before calling
315           glVertex3f.
316
317              my $tess = gluNewTess('do_colors');
318
319              gluTessCallback($tess, GLU_TESS_VERTEX, sub {
320                  my ($x, $y, $z, $r, $g, $b, $a, $vertex_data) = @_;
321                  glColor4f($r, $g, $b, $a);
322                  glVertex3f($x, $y, $z);
323              });
324
325           If gluNewTess was passed 'do_normals' then the GLU_TESS_VERTEX
326           callback will also be passed the normal x,y,z information.  The
327           'DEFAULT' option will pass the normal information to glNormal3f
328           before calling glVertex3f.
329
330              my $tess = gluNewTess('do_colors', 'do_normals');
331
332              gluTessCallback($tess, GLU_TESS_VERTEX, sub {
333                  my ($x, $y, $z, $r, $g, $b, $a, $nx, $ny, $nz, $vertex_data) = @_;
334                  glColor4f($r, $g, $b, $a);
335                  glNormalf($nx, $ny, $nz);
336                  glVertex3f($x, $y, $z);
337              });
338
339              # OR
340
341              my $tess = gluNewTess(undef, 'do_normals');
342
343              gluTessCallback($tess, GLU_TESS_VERTEX, sub {
344                  my ($x, $y, $z, $nx, $ny, $nz, $vertex_data) = @_;
345                  glNormalf($nx, $ny, $nz);
346                  glVertex3f($x, $y, $z);
347              });
348
349           In all cases, any optional vertex_data will be passed as the final
350           argument.
351
352       "GLU_TESS_VERTEX_DATA"
353           Similar to GLU_TESS_VERTEX but will be passed optional
354           $polygon_data set in gluTessBeginPolygon (if any) rather than the
355           optional $vertex_data passed to gluTessVertex_p.  The 'DEFAULT'
356           handler will ignore this data.
357
358              gluTessCallback($tess, GLU_TESS_VERTEX_DATA, sub {
359                  my ($x, $y, $z, $vertex_data) = @_;
360                  glVertex3f($x, $y, $z);
361                  print "glVertex - and I received vertex_data\n" if $vertex_data;
362              });
363
364       "GLU_TESS_COMBINE"
365              gluTessCallback($tess, GLU_TESS_COMBINE, 'DEFAULT');
366              # works with gluTessCallback($tess, GLU_TESS_VERTEX, 'DEFAULT');
367
368
369              # OR
370
371
372              # the following callback is valid for gluNewTess() (no do_colors or do_normals)
373              # using gluTessVertex_p($tess, $x, $y, $z);
374              my $tess = gluNewTess();
375              gluTessCallback($tess, GLU_TESS_COMBINE, sub {
376                  my ($x, $y, $z,           # new vertex location
377                      $v0, $v1, $v2, $v3,   # border vertex arrayrefs
378                      $w0, $w1, $w2, $w3,   # border vertex weights
379                      $polygon_data) = @_;  # optional data passed to gluTessBeginPolygon
380                  return ($x, $y, $z);
381              });
382              # works with gluTessCallback($tess, GLU_TESS_VERTEX, 'DEFAULT');
383
384
385              # OR
386
387
388              # the following callback is valid for gluNewTess() when vertex data is passed
389              # using gluTessVertex_p($tess, $x, $y, $z, [$r, $g, $b, $a]);
390              # The DEFAULT callback cannot automatically proceess this type of data
391              # but passing data to a custom handler this way could handle any arbitrary data passed to it
392              my $tess = gluNewTess();
393              use constant _r => 0;
394              use constant _g => 1;
395              use constant _b => 2;
396              use constant _a => 3;
397              gluTessCallback($tess, GLU_TESS_COMBINE, sub {
398                  my ($x, $y, $z,           # new vertex location
399                      $v0, $v1, $v2, $v3,   # border vertex arrayrefs
400                      $w0, $w1, $w2, $w3,   # border vertex weights
401                      $polygon_data) = @_;  # optional data passed to gluTessBeginPolygon
402
403                  # $v0 will contain [$x, $y, $z, [$r, $g, $b, $a]]
404                  my @rgba = map {$_->[3]} $v0, $v1, $v2, $v3;
405
406                  # generate a point with color weighted from the surrounding vertices
407                  # then return that color information in the same way we received it (an rgba arrayref)
408                  return (
409                      $x, $y, $z,
410                      [$w0*$rgba[0]->[_r] + $w1*$rgba[1]->[_r] + $w2*$rgba[2]->[_r] + $w3*$rgba[3]->[_r],
411                       $w0*$rgba[0]->[_g] + $w1*$rgba[1]->[_g] + $w2*$rgba[2]->[_g] + $w3*$rgba[3]->[_g],
412                       $w0*$rgba[0]->[_b] + $w1*$rgba[1]->[_b] + $w2*$rgba[2]->[_b] + $w3*$rgba[3]->[_b],
413                       $w0*$rgba[0]->[_a] + $w1*$rgba[1]->[_a] + $w2*$rgba[2]->[_a] + $w3*$rgba[3]->[_a]],
414                      );
415              });
416              # works with gluTessCallback($tess, GLU_TESS_VERTEX, sub {
417              #    my ($x, $y, $z, $rgba) = @_;
418              #    glColor4f(@$rgba);
419              #    glVertex3f($x, $y, $z);
420              # });
421
422
423              # OR
424
425
426              # the following callback is valid for gluNewTess('do_colors')
427              # using gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a);
428              # the DEFAULT callback COULD automatically proceess this type of data as well if additional vertex data is not passed
429              my $tess = gluNewTess('do_colors');
430              use constant _r => 3;
431              use constant _g => 4;
432              use constant _b => 5;
433              use constant _a => 6;
434              gluTessCallback($tess, GLU_TESS_COMBINE, sub {
435                  my ($x, $y, $z,           # new vertex location
436                      $v0, $v1, $v2, $v3,   # border vertex arrayrefs
437                      $w0, $w1, $w2, $w3,   # border vertex weights
438                      $polygon_data) = @_;  # optional data passed to gluTessBeginPolygon
439
440                  # $v0 will contain [$x, $y, $z, $r, $g, $b, $a]
441
442                  return ( # generate a point with color weighted from the surrounding vertices
443                      $x, $y, $z,
444                      $w0*$v0->[_r] + $w1*$v1->[_r] + $w2*$v2->[_r] + $w3*$v3->[_r],
445                      $w0*$v0->[_g] + $w1*$v1->[_g] + $w2*$v2->[_g] + $w3*$v3->[_g],
446                      $w0*$v0->[_b] + $w1*$v1->[_b] + $w2*$v2->[_b] + $w3*$v3->[_b],
447                      $w0*$v0->[_a] + $w1*$v1->[_a] + $w2*$v2->[_a] + $w3*$v3->[_a],
448                      ($v0->[7] || $v1->[7] || $v2->[7] || $v3->[7]), # if we received vertex data - return some for the new vertex
449                      );
450              });
451              # works with gluTessCallback($tess, GLU_TESS_VERTEX, 'DEFAULT');
452              # OR
453              # works with gluTessCallback($tess, GLU_TESS_VERTEX, sub {
454              #    my ($x, $y, $z, $r, $g, $b, $a, $vertex_data) = @_;
455              #    glColor4f($r, $g, $b, $a);
456              #    glVertex3f($x, $y, $z);
457              # });
458
459           The combine callback is called if the tessellator decides a new
460           vertex is needed.  This will happen with self intersecting
461           polygons.  In this case, the COMBINE callback can be used to
462           interpolate appropriate values for normals, and colors, or for any
463           desired information.
464
465           The combine callback will be passed the following:
466
467           "$x, $y, $z"
468               The x y and z coordinates of the new vertex being created.
469
470           "$v0, $v1, $v2, $v3"
471               Arrayrefs of vertex information for the vertices bordering this
472               new vertex (the ones that caused the new vertex to be created).
473
474               By default if gluNewTess() is called, these arrayrefs will be
475               passed:
476
477                    my ($x, $y, $z, $vertex_data) = @$v0;
478                    # received from gluTessVertex_p($tess, $x, $y, $z, $vertex_data);
479
480               If gluNewTess('do_colors') is called, the following will be
481               passed:
482
483                    my ($x, $y, $z, $r, $g, $b, $a, $vertex_data) = @$v0;
484                    # received from gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a, $vertex_data);
485
486               If gluNewTess('do_colors', 'do_normals') is called, the
487               following will be passed:
488
489                    my ($x, $y, $z, $r, $g, $b, $a, $nx, $ny, $nz, $vertex_data) = @$v0;
490                    # received from gluTessVertex_p($tess, $x, $y, $z, $r, $g, $b, $a, $nx, $ny, $nz, $vertex_data);
491
492               If gluNewTess(undef, 'do_normals') is called, the following
493               will be passed:
494
495                    my ($x, $y, $z, $nx, $ny, $nz, $vertex_data) = @$v0;
496                    # received from gluTessVertex_p($tess, $x, $y, $z, $nx, $ny, $nz, $vertex_data);
497
498               In all cases, the data returned by the COMBINE callback should
499               be in the same format that each of the vertices are in when
500               passed into the COMBINE callback.
501
502           "$w0, $w1, $w2, $w3"
503               Weights of the participating vertices (weight $w0 corresponds
504               to vertex $v0).
505
506           "optional $polygon_data"
507               Any optional data passed to gluTessBeginPolygon.  Normally this
508               would only be passed to GLU_TESS_COMBINE_DATA, but
509               GLU_TESS_COMBINE_DATA and GLU_TESS_COMBINE share the same code
510               implementation.
511
512       "GLU_TESS_COMBINE_DATA"
513           Identical in function to the GLU_TESS_COMBINE handler.  They use
514           the same callback implementation.
515
516       "GLU_TESS_ERROR"
517              gluTessCallback($tess, GLU_TESS_ERROR, 'DEFAULT');
518
519              gluTessCallback($tess, GLU_TESS_ERROR, \&glEdgeFlag);
520
521              gluTessCallback($tess, GLU_TESS_ERROR, sub {
522                  my $errno = shift;
523                  my $err = gluErrorString($errno);
524                  warn "Received a glu tess error ($errno - $err)\n";
525               });
526
527           The 'DEFAULT' option installs a c-handler that warns with the
528           appropriate gluErrorString.
529
530           If $polygon_data was set during gluTessBeginPolygon, it is
531           discarded.
532
533       "GLU_TESS_ERROR_DATA"
534           Similar to GLU_TESS_ERROR but will be passed optional $polygon_data
535           set in gluTessBeginPolygon if any.  The 'DEFAULT' handler will
536           ignore this data.
537
538              gluTessCallback($tess, GLU_TESS_ERROR_DATA, sub {
539                  my ($errno, $polygon_data) = @_;
540                  my $err = gluErrorString($errno);
541                  warn "Received a glu tess error ($errno - $err)\n";
542                  warn "And I received polygon_data\n" if $polygon_data;
543              });
544
545       "GLU_TESS_EDGE_FLAG"
546              gluTessCallback($tess, GLU_TESS_EDGE_FLAG, 'DEFAULT');
547
548              gluTessCallback($tess, GLU_TESS_EDGE_FLAG, \&glEdgeFlag);
549
550              gluTessCallback($tess, GLU_TESS_EDGE_FLAG, sub {
551                  my ($flag) = @_;
552                  glEdgeFlag($flag);
553               });
554
555           The 'DEFAULT' option installs a c-handler that calls the glEdgeFlag
556           c function directly without round-tripping out to perl.
557
558           If $polygon_data was set during gluTessBeginPolygon, it is
559           discarded.
560
561       "GLU_TESS_EDGE_FLAG_DATA"
562           Similar to GLU_TESS_EDGE_FLAG but will be passed $polygon_data set
563           in gluTessBeginPolygon if any.  The 'DEFAULT' handler will ignore
564           this data.
565
566              gluTessCallback($tess, GLU_TESS_EDGE_FLAG_DATA, sub {
567                  my ($flag, $polygon_data) = @_;
568                  glEdgeFlag($flag);
569                  print "glEdgeFlag - and I received polygon_data\n" if $polygon_data;
570              });
571

Example: Basic Arrowhead

573           use OpenGL qw(:all);
574
575           glutInit();
576           glutInitWindowSize(501, 501);
577           glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
578           glutCreateWindow("Tessellation");
579           glMatrixMode(GL_PROJECTION());
580           glLoadIdentity();
581           glOrtho(-250,250,-250,250,-1.0,1.0);
582           glMatrixMode(GL_MODELVIEW);
583
584           my $view_triangles = 1; # set to zero to show polygon
585           glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) if $view_triangles;
586
587           glutDisplayFunc(sub {
588               glColor3f(1,1,1);
589
590               my $tess = gluNewTess();
591               gluTessCallback($tess, GLU_TESS_BEGIN,     'DEFAULT');
592               gluTessCallback($tess, GLU_TESS_END,       'DEFAULT');
593               gluTessCallback($tess, GLU_TESS_VERTEX,    'DEFAULT');
594               gluTessCallback($tess, GLU_TESS_COMBINE,   'DEFAULT');
595               gluTessCallback($tess, GLU_TESS_ERROR,     'DEFAULT');
596               gluTessCallback($tess, GLU_TESS_EDGE_FLAG, 'DEFAULT') if ! $view_triangles;
597               gluTessBeginPolygon($tess);
598               gluTessBeginContour($tess);
599
600               gluTessVertex_p($tess, 0,    200,  0);
601               gluTessVertex_p($tess, 150,  -200, 0);
602               gluTessVertex_p($tess, 0,    -100, 0);
603               gluTessVertex_p($tess, -150, -200, 0);
604
605               gluTessEndContour($tess);
606               gluTessEndPolygon($tess);
607               gluDeleteTess($tess);
608
609               glutSwapBuffers();
610           });
611
612           glutMainLoop();
613

Example: Multiple contours

615           use OpenGL qw(:all);
616
617           glutInit();
618           glutInitWindowSize(501, 501);
619           glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
620           glutCreateWindow("Tessellation");
621           glMatrixMode(GL_PROJECTION());
622           glLoadIdentity();
623           glOrtho(-250,250,-250,250,-1.0,1.0);
624           glMatrixMode(GL_MODELVIEW);
625
626           my $view_triangles = 1; # set to zero to show polygon
627           glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) if $view_triangles;
628
629           glutDisplayFunc(sub {
630               glColor3f(1,1,1);
631               my $v = [[[125,0,0], [150,150,0], [0,125,0], [-150,150,0],
632                         [-125,0,0], [-150,-150,0], [0,-125,0], [150,-150,0], [125,0,0]],
633                        [[75,0,0], [100,100,0], [0,75,0], [-100,100,0],
634                         [-75,0,0], [-100,-100,0], [0,-75,0], [100,-100,0], [75,0,0]]
635                       ];
636
637               my $tess = gluNewTess();
638               gluTessCallback($tess, GLU_TESS_BEGIN,     'DEFAULT');
639               gluTessCallback($tess, GLU_TESS_END,       'DEFAULT');
640               gluTessCallback($tess, GLU_TESS_VERTEX,    'DEFAULT');
641               gluTessCallback($tess, GLU_TESS_COMBINE,   'DEFAULT');
642               gluTessCallback($tess, GLU_TESS_ERROR,     'DEFAULT');
643               gluTessCallback($tess, GLU_TESS_EDGE_FLAG, 'DEFAULT') if ! $view_triangles;
644               gluTessBeginPolygon($tess);
645               foreach (@$v) {
646                   gluTessBeginContour($tess);
647                   foreach (@$_) {
648                       gluTessVertex_p($tess, @$_);
649                   }
650                   gluTessEndContour($tess);
651               }
652               gluTessEndPolygon($tess);
653               gluDeleteTess($tess);
654
655               glutSwapBuffers();
656           });
657
658           glutMainLoop();
659

Example: Sample OO Tessellation interface using polygon_data

661           use OpenGL qw(:all);
662
663           glutInit();
664           glutInitWindowSize(501, 501);
665           glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
666           glutCreateWindow("Tessellation");
667           glMatrixMode(GL_PROJECTION());
668           glLoadIdentity();
669           glOrtho(-250,250,-250,250,-1.0,1.0);
670           glMatrixMode(GL_MODELVIEW);
671
672           my $view_triangles = 0;
673           glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) if $view_triangles;
674
675           glutDisplayFunc(sub {
676               glColor3f(1,1,1);
677               my $v = [[[125,0,0], [150,150,0, 0,1,0], [0,125,0], [-150,150,0, 1,0,0],
678                         [-125,0,0], [-150,-150,0, 0,0,1], [0,-125,0], [150,-150,0, 1,1,0], [125,0,0]],
679                        [[75,0,0], [100,100,0], [0,75,0], [-100,100,0],
680                         [-75,0,0], [-100,-100,0], [0,-75,0], [100,-100,0], [75,0,0]]
681                       ];
682
683               OpenGL::Tess->new(do_colors => 1, no_edge_flag => $view_triangles)->draw_contours(@$v);
684
685               glutSwapBuffers();
686           });
687
688           glutMainLoop();
689
690           ###----------------------------------------------------------------###
691
692
693           package OpenGL::Tess;
694
695           # Sample object oriented Tessellator
696           # OpenGL::Tess->new(do_colors => 1, no_edge_flag => $view_triangles)->draw_contours(@$v);
697
698           use strict;
699
700           sub new {
701               my $class = shift;
702               my $self  = bless {@_}, $class;
703               my $tess = $self->{'_tess'} = OpenGL::gluNewTess($self->do_colors);
704               for my $cb (qw(begin end vertex combine error edge_flag)) {
705                   my $enum = OpenGL->can("GLU_TESS_\U${cb}_DATA") || die "Couldn't find callback for $cb";
706                   my $name = "_$cb";
707                   OpenGL::gluTessCallback($tess, $enum->(), sub { $_[-1]->$name(@_) });
708               }
709               return $self;
710           }
711
712           sub DESTROY {
713               my $tess = shift->{'_tess'};
714               OpenGL::gluDeleteTess($tess) if $tess;
715           }
716
717           sub tess {
718               my $self = shift;
719               return $self->{'_tess'} || die "Missing tess";
720           }
721
722           sub do_colors { shift->{'do_colors'} }
723
724           sub begin_polygon {
725               my $self = shift;
726               my $tess = $self->tess;
727               # self will be passed as last arg ([-1]) to all callbacks as opaque polygon data
728               return OpenGL::gluTessBeginPolygon($tess, $self);
729           }
730
731           sub end_polygon   { OpenGL::gluTessEndPolygon(  shift->tess) }
732           sub begin_contour { OpenGL::gluTessBeginContour(shift->tess) }
733           sub end_contour   { OpenGL::gluTessEndContour(  shift->tess) }
734
735           sub draw_contours {
736               my $self = shift;
737               $self->begin_polygon;
738               foreach my $c (@_) {
739                   $self->begin_contour;
740                   $self->add_vertex(@$_) for @$c;
741                   $self->end_contour;
742               }
743               $self->end_polygon;
744           }
745
746           sub add_vertex {
747               my $self = shift;
748               die 'Usage $self->add_vertex($x,$y,$z)' if @_ < 3;
749               if ($self->do_colors) {
750                   push @_, 1 for @_ .. 6;
751                   OpenGL::gluTessVertex_p($self->tess, @_[0..6]);
752               } else {
753                   OpenGL::gluTessVertex_p($self->tess, @_[0..3]);
754               }
755           }
756
757           sub _begin {
758               my ($self, $enum) = @_;
759               OpenGL::glBegin($enum);
760           }
761
762           sub _end { OpenGL::glEnd() }
763
764           sub _vertex {
765               my ($self, $x, $y, $z, $r, $g, $b, $a) = @_;
766               OpenGL::glColor4f($r, $g, $b, $a) if $self->do_colors;
767               OpenGL::glVertex3f($x, $y, $z);
768           }
769
770           sub _edge_flag {
771               my ($self, $flag) = @_;
772               return if $self->{'no_edge_flag'};
773               OpenGL::glEdgeFlag($flag);
774           }
775
776           sub _error {
777               my ($self, $errno) = @_;
778               warn __PACKAGE__ ." error: ".OpenGL::gluErrorString($errno);
779           }
780
781           sub _combine {
782               my ($self, $x, $y, $z, $v0, $v1, $v2, $v3, $w0, $w1, $w2, $w3) = @_;
783               return ($x, $y, $z) if !$self->do_colors;
784               return ($x, $y, $z,
785                       $w0*$v0->[3] + $w1*$v1->[3] + $w2*$v2->[3] + $w3*$v3->[3],
786                       $w0*$v0->[4] + $w1*$v1->[4] + $w2*$v2->[4] + $w3*$v3->[4],
787                       $w0*$v0->[5] + $w1*$v1->[5] + $w2*$v2->[5] + $w3*$v3->[5],
788                       $w0*$v0->[6] + $w1*$v1->[6] + $w2*$v2->[6] + $w3*$v3->[6]);
789           }
790
791           1;
792

AUTHOR

794         Paul Seamons - paul AT seamons dot com - 2011
795
796
797
798perl v5.30.0                      2019-07-26                   Tessellation(3)
Impressum