source: trunk/source/visualization/OpenInventor/src/gl2ps.cc@ 811

Last change on this file since 811 was 529, checked in by garnier, 18 years ago

r658@mac-90108: laurentgarnier | 2007-06-25 12:02:16 +0200
import de visualisation

  • Property svn:mime-type set to text/cpp
File size: 69.0 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26#ifdef G4VIS_BUILD_OI_DRIVER
27
28/*
29 * GL2PS, an OpenGL to PostScript Printing Library
30 * Copyright (C) 1999-2003 Christophe Geuzaine
31 *
32 * $Id: gl2ps.cc,v 1.11 2006/06/29 21:23:09 gunter Exp $
33 *
34 * E-mail: geuz@geuz.org
35 * URL: http://www.geuz.org/gl2ps/
36 *
37 * This library is free software; you can redistribute it and/or
38 * modify it under the terms of the GNU Library General Public
39 * License as published by the Free Software Foundation; either
40 * version 2 of the License, or (at your option) any later version.
41 *
42 * This library is distributed in the hope that it will be useful,
43 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45 * Library General Public License for more details.
46 *
47 * You should have received a copy of the GNU Library General Public
48 * License along with this library; if not, write to the Free
49 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
50 *
51 */
52
53#include <string.h>
54#include <sys/types.h>
55#include <stdarg.h>
56#include <time.h>
57#include "Geant4_gl2ps.h"
58
59/* The gl2ps context. gl2ps is not thread safe (we should create a
60 local GL2PScontext during gl2psBeginPage). */
61
62GL2PScontext *gl2ps = NULL;
63
64/* Some 'system' utility routines */
65
66void gl2psMsg(GLint level, const char *fmt, ...){
67 va_list args;
68
69 if(!(gl2ps->options & GL2PS_SILENT)){
70 switch(level){
71 case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break;
72 case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break;
73 case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
74 }
75 va_start(args, fmt);
76 vfprintf(stderr, fmt, args);
77 va_end(args);
78 fprintf(stderr, "\n");
79 }
80 /*
81 if(level == GL2PS_ERROR) exit(1);
82 */
83}
84
85void *gl2psMalloc(size_t size){
86 void *ptr;
87
88 if(!size) return(NULL);
89 ptr = malloc(size);
90 if(!ptr){
91 gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory");
92 exit(1);
93 }
94 return(ptr);
95}
96
97void *gl2psRealloc(void *ptr, size_t size){
98 if(!size) return(NULL);
99 ptr = realloc(ptr, size);
100 if(!ptr){
101 gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory");
102 exit(1);
103 }
104 return(ptr);
105}
106
107void gl2psFree(void *ptr){
108 if(!ptr) return;
109 free(ptr);
110}
111
112/* The list handling routines */
113
114void gl2psListRealloc(GL2PSlist *list, GLint n){
115 if(n <= 0) return;
116 if(!list->array){
117 list->nmax = ((n - 1) / list->incr + 1) * list->incr;
118 list->array = (char *)gl2psMalloc(list->nmax * list->size);
119 }
120 else{
121 if(n > list->nmax){
122 list->nmax = ((n - 1) / list->incr + 1) * list->incr;
123 list->array = (char *)gl2psRealloc(list->array,
124 list->nmax * list->size);
125 }
126 }
127}
128
129GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size){
130 GL2PSlist *list;
131
132 if(n < 0) n = 0;
133 if(incr <= 0) incr = 1;
134 list = (GL2PSlist *)gl2psMalloc(sizeof(GL2PSlist));
135 list->nmax = 0;
136 list->incr = incr;
137 list->size = size;
138 list->n = 0;
139 list->array = NULL;
140 gl2psListRealloc(list, n);
141 return(list);
142}
143
144void gl2psListReset(GL2PSlist *list){
145 list->n = 0;
146}
147
148void gl2psListDelete(GL2PSlist *list){
149 gl2psFree(list->array);
150 gl2psFree(list);
151}
152
153void gl2psListAdd(GL2PSlist *list, void *data){
154 list->n++;
155 gl2psListRealloc(list, list->n);
156 memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
157}
158
159GLint gl2psListNbr(GL2PSlist *list){
160 return(list->n);
161}
162
163void *gl2psListPointer(GL2PSlist *list, GLint index){
164 if((index < 0) || (index >= list->n)){
165 gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer");
166 return(&list->array[0]);
167 }
168 return(&list->array[index * list->size]);
169}
170
171void gl2psListSort(GL2PSlist *list,
172 int (*fcmp)(const void *a, const void *b)){
173 qsort(list->array, list->n, list->size, fcmp);
174}
175
176void gl2psListAction(GL2PSlist *list,
177 void (*action)(void *data, void *dummy)){
178 GLint i, dummy;
179
180 for(i = 0; i < gl2psListNbr(list); i++){
181 (*action)(gl2psListPointer(list, i), &dummy);
182 }
183}
184
185void gl2psListActionInverse(GL2PSlist *list,
186 void (*action)(void *data, void *dummy)){
187 GLint i, dummy;
188
189 for(i = gl2psListNbr(list); i > 0; i--){
190 (*action)(gl2psListPointer(list, i-1), &dummy);
191 }
192}
193
194/* The 3D sorting routines */
195
196GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane){
197 return(plane[0] * point[0] +
198 plane[1] * point[1] +
199 plane[2] * point[2] +
200 plane[3]);
201}
202
203GLfloat gl2psPsca(GLfloat *a, GLfloat *b){
204 return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
205}
206
207void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c){
208 c[0] = a[1]*b[2] - a[2]*b[1];
209 c[1] = a[2]*b[0] - a[0]*b[2];
210 c[2] = a[0]*b[1] - a[1]*b[0];
211}
212
213GLfloat gl2psNorm(GLfloat *a){
214 return std::sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
215}
216
217void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c){
218 GLfloat norm;
219
220 gl2psPvec(a, b, c);
221 if(!GL2PS_ZERO(norm = gl2psNorm(c))){
222 c[0] = c[0] / norm;
223 c[1] = c[1] / norm;
224 c[2] = c[2] / norm;
225 }
226 else{
227 /* The plane is still wrong, despite our tests in
228 gl2psGetPlane... Let's return a dummy value (this is a hack: we
229 should do more tests in GetPlane): */
230 c[0] = c[1] = 0.;
231 c[2] = 1.;
232 }
233}
234
235void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane){
236 GL2PSxyz v = {0., 0., 0.}, w = {0., 0., 0.};
237
238 switch(prim->type){
239 case GL2PS_TRIANGLE :
240 case GL2PS_QUADRANGLE :
241 v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
242 v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
243 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
244 w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
245 w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
246 w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
247 if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
248 (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
249 plane[0] = plane[1] = 0.;
250 plane[2] = 1.;
251 plane[3] = -prim->verts[0].xyz[2];
252 }
253 else{
254 gl2psGetNormal(v, w, plane);
255 plane[3] =
256 - plane[0] * prim->verts[0].xyz[0]
257 - plane[1] * prim->verts[0].xyz[1]
258 - plane[2] * prim->verts[0].xyz[2];
259 }
260 break;
261 case GL2PS_LINE :
262 v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
263 v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
264 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
265 if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
266 plane[0] = plane[1] = 0.;
267 plane[2] = 1.;
268 plane[3] = -prim->verts[0].xyz[2];
269 }
270 else{
271 if(GL2PS_ZERO(v[0])) w[0] = 1.;
272 else if(GL2PS_ZERO(v[1])) w[1] = 1.;
273 else w[2] = 1.;
274 gl2psGetNormal(v, w, plane);
275 plane[3] =
276 - plane[0] * prim->verts[0].xyz[0]
277 - plane[1] * prim->verts[0].xyz[1]
278 - plane[2] * prim->verts[0].xyz[2];
279 }
280 break;
281 case GL2PS_POINT :
282 case GL2PS_PIXMAP :
283 case GL2PS_TEXT :
284 plane[0] = plane[1] = 0.;
285 plane[2] = 1.;
286 plane[3] = -prim->verts[0].xyz[2];
287 break;
288 default :
289 gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree");
290 plane[0] = plane[1] = plane[3] = 0.;
291 plane[2] = 1.;
292 break;
293 }
294}
295
296void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane,
297 GL2PSvertex *c){
298 GL2PSxyz v;
299 GLfloat sect;
300
301 v[0] = b->xyz[0] - a->xyz[0];
302 v[1] = b->xyz[1] - a->xyz[1];
303 v[2] = b->xyz[2] - a->xyz[2];
304 sect = - gl2psComparePointPlane(a->xyz, plane) / gl2psPsca(plane, v);
305
306 c->xyz[0] = a->xyz[0] + v[0] * sect;
307 c->xyz[1] = a->xyz[1] + v[1] * sect;
308 c->xyz[2] = a->xyz[2] + v[2] * sect;
309
310 c->rgba[0] = (1.-sect) * a->rgba[0] + sect * b->rgba[0];
311 c->rgba[1] = (1.-sect) * a->rgba[1] + sect * b->rgba[1];
312 c->rgba[2] = (1.-sect) * a->rgba[2] + sect * b->rgba[2];
313 c->rgba[3] = (1.-sect) * a->rgba[3] + sect * b->rgba[3];
314}
315
316void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane,
317 GL2PSprimitive *child, GLshort numverts,
318 GLshort *index0, GLshort *index1){
319 GLshort i;
320
321 if(numverts > 4){
322 gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
323 numverts = 4;
324 }
325
326 switch(numverts){
327 case 1 : child->type = GL2PS_POINT; break;
328 case 2 : child->type = GL2PS_LINE; break;
329 case 3 : child->type = GL2PS_TRIANGLE; break;
330 case 4 : child->type = GL2PS_QUADRANGLE; break;
331 }
332 child->boundary = 0; /* not done! */
333 child->depth = parent->depth; /* should not be used in this case */
334 child->culled = parent->culled;
335 child->dash = parent->dash;
336 child->width = parent->width;
337 child->numverts = numverts;
338 child->verts = (GL2PSvertex *)gl2psMalloc(numverts * sizeof(GL2PSvertex));
339
340 for(i = 0; i < numverts; i++){
341 if(index1[i] < 0){
342 child->verts[i] = parent->verts[index0[i]];
343 }
344 else{
345 gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
346 plane, &child->verts[i]);
347 }
348 }
349}
350
351void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
352 GLshort i, GLshort j){
353 GLint k;
354
355 for(k = 0; k < *nb; k++){
356 if((index0[k] == i && index1[k] == j) ||
357 (index1[k] == i && index0[k] == j)) return;
358 }
359 index0[*nb] = i;
360 index1[*nb] = j;
361 (*nb)++;
362}
363
364GLshort gl2psGetIndex(GLshort i, GLshort num){
365 return(i < num-1) ? i+1 : 0;
366}
367
368GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane){
369 GLint type = GL2PS_COINCIDENT;
370 GLshort i, j;
371 GLfloat d[5];
372
373 for(i = 0; i < prim->numverts; i++){
374 d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
375 }
376
377 if(prim->numverts < 2){
378 return 0;
379 }
380 else{
381 for(i = 0; i < prim->numverts; i++){
382 j = gl2psGetIndex(i, prim->numverts);
383 if(d[j] > GL2PS_EPSILON){
384 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF;
385 else if(type != GL2PS_IN_BACK_OF) return 1;
386 if(d[i] < -GL2PS_EPSILON) return 1;
387 }
388 else if(d[j] < -GL2PS_EPSILON){
389 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF;
390 else if(type != GL2PS_IN_FRONT_OF) return 1;
391 if(d[i] > GL2PS_EPSILON) return 1;
392 }
393 }
394 }
395 return 0;
396}
397
398GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
399 GL2PSprimitive **front, GL2PSprimitive **back){
400 GLshort i, j, in=0, out=0, in0[5], in1[5], out0[5], out1[5];
401 GLint type;
402 GLfloat d[5];
403
404 type = GL2PS_COINCIDENT;
405
406 for(i = 0; i < prim->numverts; i++){
407 d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
408 }
409
410 switch(prim->type){
411 case GL2PS_POINT :
412 if(d[0] > GL2PS_EPSILON) type = GL2PS_IN_BACK_OF;
413 else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
414 else type = GL2PS_COINCIDENT;
415 break;
416 default :
417 for(i = 0; i < prim->numverts; i++){
418 j = gl2psGetIndex(i, prim->numverts);
419 if(d[j] > GL2PS_EPSILON){
420 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF;
421 else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING;
422 if(d[i] < -GL2PS_EPSILON){
423 gl2psAddIndex(in0, in1, &in, i, j);
424 gl2psAddIndex(out0, out1, &out, i, j);
425 type = GL2PS_SPANNING;
426 }
427 gl2psAddIndex(out0, out1, &out, j, -1);
428 }
429 else if(d[j] < -GL2PS_EPSILON){
430 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF;
431 else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
432 if(d[i] > GL2PS_EPSILON){
433 gl2psAddIndex(in0, in1, &in, i, j);
434 gl2psAddIndex(out0, out1, &out, i, j);
435 type = GL2PS_SPANNING;
436 }
437 gl2psAddIndex(in0, in1, &in, j, -1);
438 }
439 else{
440 gl2psAddIndex(in0, in1, &in, j, -1);
441 gl2psAddIndex(out0, out1, &out, j, -1);
442 }
443 }
444 break;
445 }
446
447 if(type == GL2PS_SPANNING){
448 *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
449 *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
450 gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
451 gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
452 }
453
454 return type;
455}
456
457void gl2psDivideQuad(GL2PSprimitive *quad,
458 GL2PSprimitive **t1, GL2PSprimitive **t2){
459 *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
460 *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
461 (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
462 (*t1)->numverts = (*t2)->numverts = 3;
463 (*t1)->depth = (*t2)->depth = quad->depth;
464 (*t1)->culled = (*t2)->culled = quad->culled;
465 (*t1)->dash = (*t2)->dash = quad->dash;
466 (*t1)->width = (*t2)->width = quad->width;
467 (*t1)->verts = (GL2PSvertex *)gl2psMalloc(3 * sizeof(GL2PSvertex));
468 (*t2)->verts = (GL2PSvertex *)gl2psMalloc(3 * sizeof(GL2PSvertex));
469 (*t1)->verts[0] = quad->verts[0];
470 (*t1)->verts[1] = quad->verts[1];
471 (*t1)->verts[2] = quad->verts[2];
472 (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
473 (*t2)->verts[0] = quad->verts[0];
474 (*t2)->verts[1] = quad->verts[2];
475 (*t2)->verts[2] = quad->verts[3];
476 (*t1)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 4) ? 2 : 0);
477}
478
479int gl2psCompareDepth(const void *a, const void *b){
480 GL2PSprimitive *q, *w;
481 GLfloat diff;
482
483 q = *(GL2PSprimitive**)a;
484 w = *(GL2PSprimitive**)b;
485 diff = q->depth - w->depth;
486 if(diff > 0.){
487 return 1;
488 }
489 else if(diff < 0.){
490 return -1;
491 }
492 else{
493 return 0;
494 }
495}
496
497int gl2psTrianglesFirst(const void *a, const void *b){
498 GL2PSprimitive *q, *w;
499
500 q = *(GL2PSprimitive**)a;
501 w = *(GL2PSprimitive**)b;
502 return(q->type < w->type ? 1 : -1);
503}
504
505GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root){
506 GLint i, j, count, best = 1000000, index = 0;
507 GL2PSprimitive *prim1, *prim2;
508 GL2PSplane plane;
509 GLint maxp;
510
511 if(gl2ps->options & GL2PS_BEST_ROOT){
512 *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
513 maxp = gl2psListNbr(primitives);
514 if(maxp > gl2ps->maxbestroot){
515 maxp = gl2ps->maxbestroot;
516 }
517 for(i = 0; i < maxp; i++){
518 prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i);
519 gl2psGetPlane(prim1, plane);
520 count = 0;
521 for(j = 0; j < gl2psListNbr(primitives); j++){
522 if(j != i){
523 prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
524 count += gl2psTestSplitPrimitive(prim2, plane);
525 }
526 if(count > best) break;
527 }
528 if(count < best){
529 best = count;
530 index = i;
531 *root = prim1;
532 if(!count) return index;
533 }
534 }
535 /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */
536 return index;
537 }
538 else{
539 *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
540 return 0;
541 }
542}
543
544void gl2psFreePrimitive(void *a, void *){
545 GL2PSprimitive *q;
546
547 q = *(GL2PSprimitive**)a;
548 gl2psFree(q->verts);
549 if(q->type == GL2PS_TEXT){
550 gl2psFree(q->text->str);
551 gl2psFree(q->text->fontname);
552 gl2psFree(q->text);
553 }
554 if(q->type == GL2PS_PIXMAP){
555 gl2psFree(q->image->pixels);
556 gl2psFree(q->image);
557 }
558 gl2psFree(q);
559}
560
561void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list){
562 GL2PSprimitive *t1, *t2;
563
564 if(prim->type != GL2PS_QUADRANGLE){
565 gl2psListAdd(list, &prim);
566 }
567 else{
568 gl2psDivideQuad(prim, &t1, &t2);
569 gl2psListAdd(list, &t1);
570 gl2psListAdd(list, &t2);
571 gl2psFreePrimitive(&prim, NULL);
572 }
573
574}
575
576void gl2psFreeBspTree(GL2PSbsptree **tree){
577 if(*tree){
578 if((*tree)->back) gl2psFreeBspTree(&(*tree)->back);
579 if((*tree)->primitives){
580 gl2psListAction((*tree)->primitives, gl2psFreePrimitive);
581 gl2psListDelete((*tree)->primitives);
582 }
583 if((*tree)->front) gl2psFreeBspTree(&(*tree)->front);
584 gl2psFree(*tree);
585 *tree = NULL;
586 }
587}
588
589GLboolean gl2psGreater(GLfloat f1, GLfloat f2){
590 if(f1 > f2) return 1;
591 else return 0;
592}
593
594GLboolean gl2psLess(GLfloat f1, GLfloat f2){
595 if(f1 < f2) return 1;
596 else return 0;
597}
598
599void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives){
600 GL2PSprimitive *prim, *frontprim, *backprim;
601 GL2PSlist *frontlist, *backlist;
602 GLint i, index;
603
604 tree->front = NULL;
605 tree->back = NULL;
606 tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
607 index = gl2psFindRoot(primitives, &prim);
608 gl2psGetPlane(prim, tree->plane);
609 gl2psAddPrimitiveInList(prim, tree->primitives);
610
611 frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
612 backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
613
614 for(i = 0; i < gl2psListNbr(primitives); i++){
615 if(i != index){
616 prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i);
617 switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
618 case GL2PS_COINCIDENT:
619 gl2psAddPrimitiveInList(prim, tree->primitives);
620 break;
621 case GL2PS_IN_BACK_OF:
622 gl2psAddPrimitiveInList(prim, backlist);
623 break;
624 case GL2PS_IN_FRONT_OF:
625 gl2psAddPrimitiveInList(prim, frontlist);
626 break;
627 case GL2PS_SPANNING:
628 gl2psAddPrimitiveInList(backprim, backlist);
629 gl2psAddPrimitiveInList(frontprim, frontlist);
630 gl2psFreePrimitive(&prim, NULL);
631 break;
632 }
633 }
634 }
635
636 if(gl2psListNbr(tree->primitives)){
637 gl2psListSort(tree->primitives, gl2psTrianglesFirst);
638 }
639
640 if(gl2psListNbr(frontlist)){
641 gl2psListSort(frontlist, gl2psTrianglesFirst);
642 tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
643 gl2psBuildBspTree(tree->front, frontlist);
644 }
645 else{
646 gl2psListDelete(frontlist);
647 }
648
649 if(gl2psListNbr(backlist)){
650 gl2psListSort(backlist, gl2psTrianglesFirst);
651 tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
652 gl2psBuildBspTree(tree->back, backlist);
653 }
654 else{
655 gl2psListDelete(backlist);
656 }
657
658 gl2psListDelete(primitives);
659}
660
661void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon,
662 GLboolean (*compare)(GLfloat f1, GLfloat f2),
663 void (*action)(void *data, void *dummy)){
664 GLfloat result;
665
666 if(!tree) return;
667
668 result = gl2psComparePointPlane(eye, tree->plane);
669
670 if(compare(result, epsilon)){
671 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action);
672 gl2psListAction(tree->primitives, action);
673 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action);
674 }
675 else if(compare(-epsilon, result)){
676 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action);
677 gl2psListAction(tree->primitives, action);
678 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action);
679 }
680 else{
681 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action);
682 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action);
683 }
684}
685
686/* The 2D sorting routines (for occlusion culling) */
687
688GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane){
689 GLfloat n;
690
691 plane[0] = b[1] - a[1];
692 plane[1] = a[0] - b[0];
693 n = std::sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
694 plane[2]=0.;
695 if(n != 0.){
696 plane[0] /= n;
697 plane[1] /= n;
698 plane[3] = -plane[0]*a[0]-plane[1]*a[1];
699 return 1;
700 }
701 else{
702 plane[0] = -1.0;
703 plane[1] = 0.;
704 plane[3] = a[0];
705 return 0;
706 }
707}
708
709void gl2psFreeBspImageTree(GL2PSbsptree2d **tree){
710 if(*tree){
711 if((*tree)->back) gl2psFreeBspImageTree(&(*tree)->back);
712 if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front);
713 gl2psFree(*tree);
714 *tree = NULL;
715 }
716}
717
718GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane){
719 GLfloat pt_dis;
720
721 pt_dis = gl2psComparePointPlane(point, plane);
722 if(pt_dis > GL2PS_EPSILON) return GL2PS_POINT_INFRONT;
723 else if(pt_dis < -GL2PS_EPSILON) return GL2PS_POINT_BACK;
724 else return GL2PS_POINT_COINCIDENT;
725}
726
727void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim,
728 GL2PSbsptree2d **tree){
729 GLint ret = 0;
730 GLint i;
731 GLint offset = 0;
732 GL2PSbsptree2d *head = NULL, *cur = NULL;
733
734 if((*tree == NULL) && (prim->numverts > 2)){
735 head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
736 for(i = 0; i < prim->numverts-1; i++){
737 if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz,
738 prim->verts[i+1].xyz,
739 head->plane)){
740 if(prim->numverts-i > 3){
741 offset++;
742 }
743 else{
744 gl2psFree(head);
745 return;
746 }
747 }
748 else{
749 break;
750 }
751 }
752 head->back = NULL;
753 head->front = NULL;
754 for(i = 2+offset; i < prim->numverts; i++){
755 ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane);
756 if(ret != GL2PS_POINT_COINCIDENT) break;
757 }
758 switch(ret){
759 case GL2PS_POINT_INFRONT :
760 cur = head;
761 for(i = 1+offset; i < prim->numverts-1; i++){
762 if(cur->front == NULL){
763 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
764 }
765 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
766 prim->verts[i+1].xyz,
767 cur->front->plane)){
768 cur = cur->front;
769 cur->front = NULL;
770 cur->back = NULL;
771 }
772 }
773 if(cur->front == NULL){
774 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
775 }
776 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
777 prim->verts[offset].xyz,
778 cur->front->plane)){
779 cur->front->front = NULL;
780 cur->front->back = NULL;
781 }
782 else{
783 gl2psFree(cur->front);
784 cur->front = NULL;
785 }
786 break;
787 case GL2PS_POINT_BACK :
788 for(i = 0; i < 4; i++){
789 head->plane[i] = -head->plane[i];
790 }
791 cur = head;
792 for(i = 1+offset; i < prim->numverts-1; i++){
793 if(cur->front == NULL){
794 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
795 }
796 if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
797 prim->verts[i].xyz,
798 cur->front->plane)){
799 cur = cur->front;
800 cur->front = NULL;
801 cur->back = NULL;
802 }
803 }
804 if(cur->front == NULL){
805 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
806 }
807 if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
808 prim->verts[i].xyz,
809 cur->front->plane)){
810 cur->front->front = NULL;
811 cur->front->back = NULL;
812 }
813 else{
814 gl2psFree(cur->front);
815 cur->front = NULL;
816 }
817 break;
818 default:
819 gl2psFree(head);
820 return;
821 }
822 (*tree) = head;
823 }
824}
825
826GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane){
827 GLint i;
828 GLint pos;
829
830 pos = gl2psCheckPoint(prim->verts[0].xyz, plane);
831 for(i = 1; i < prim->numverts; i++){
832 pos |= gl2psCheckPoint(prim->verts[i].xyz, plane);
833 if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK)) return GL2PS_SPANNING;
834 }
835 if(pos & GL2PS_POINT_INFRONT) return GL2PS_IN_FRONT_OF;
836 else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF;
837 else return GL2PS_COINCIDENT;
838}
839
840GL2PSprimitive* gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent,
841 GLshort numverts,
842 GL2PSvertex *vertx){
843 GLint i;
844 GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
845
846 switch(numverts){
847 case 1 : child->type = GL2PS_POINT; break;
848 case 2 : child->type = GL2PS_LINE; break;
849 case 3 : child->type = GL2PS_TRIANGLE; break;
850 case 4 : child->type = GL2PS_QUADRANGLE; break;
851 }
852 child->boundary = 0; /* not done! */
853 child->depth = parent->depth;
854 child->culled = parent->culled;
855 child->dash = parent->dash;
856 child->width = parent->width;
857 child->numverts = numverts;
858 child->verts = (GL2PSvertex *)gl2psMalloc(numverts * sizeof(GL2PSvertex));
859 for(i = 0; i < numverts; i++){
860 child->verts[i] = vertx[i];
861 }
862 return child;
863}
864
865void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
866 GL2PSplane plane,
867 GL2PSprimitive **front,
868 GL2PSprimitive **back){
869
870 /* cur will hold the position of current vertex
871 prev will holds the position of previous vertex
872 prev0 will holds the position of vertex number 0
873 v1 and v2 represent the current and previous vertexs respectively
874 flag will represents that should the current be checked against the plane */
875 GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
876
877 /* list of vertexs which will go in front and back Primitive */
878 GL2PSvertex *front_list = NULL, *back_list = NULL;
879
880 /* number of vertex in front and back list */
881 GLint front_count = 0, back_count = 0;
882
883 for(i = 0; i <= prim->numverts; i++){
884 v1 = i;
885 if(v1 == prim->numverts){
886 if(prim->numverts < 3) break;
887 v1 = 0;
888 v2 = prim->numverts-1;
889 cur = prev0;
890 }
891 else if(flag){
892 cur = gl2psCheckPoint(prim->verts[v1].xyz, plane);
893 if(i == 0){
894 prev0 = cur;
895 }
896 }
897 if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
898 (i < prim->numverts)){
899 if(cur == GL2PS_POINT_INFRONT){
900 front_count++;
901 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
902 sizeof(GL2PSvertex)*front_count);
903 front_list[front_count-1] = prim->verts[v1];
904 }
905 else if(cur == GL2PS_POINT_BACK){
906 back_count++;
907 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
908 sizeof(GL2PSvertex)*back_count);
909 back_list[back_count-1] = prim->verts[v1];
910 }
911 else{
912 front_count++;
913 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
914 sizeof(GL2PSvertex)*front_count);
915 front_list[front_count-1] = prim->verts[v1];
916 back_count++;
917 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
918 sizeof(GL2PSvertex)*back_count);
919 back_list[back_count-1] = prim->verts[v1];
920 }
921 flag = 1;
922 }
923 else if((prev != cur) && (cur != 0) && (prev != 0)){
924 if(v1 != 0){
925 v2 = v1-1;
926 i--;
927 }
928 front_count++;
929 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
930 sizeof(GL2PSvertex)*front_count);
931 gl2psCutEdge(&prim->verts[v2],
932 &prim->verts[v1],
933 plane,
934 &front_list[front_count-1]);
935 back_count++;
936 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
937 sizeof(GL2PSvertex)*back_count);
938 back_list[back_count-1] = front_list[front_count-1];
939 flag = 0;
940 }
941 prev = cur;
942 }
943 *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
944 *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
945 gl2psFree(front_list);
946 gl2psFree(back_list);
947}
948
949GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){
950 GLint ret = 0;
951 GL2PSprimitive *frontprim = NULL, *backprim = NULL;
952
953 if(*tree == NULL){
954 gl2psAddPlanesInBspTreeImage(prim, tree);
955 return 1;
956 }
957 else{
958 switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
959 case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
960 case GL2PS_IN_FRONT_OF:
961 if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
962 else return 0;
963 case GL2PS_SPANNING:
964 gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
965 ret = gl2psAddInBspImageTree(backprim, &(*tree)->back);
966 if((*tree)->front != NULL){
967 if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){
968 ret = 1;
969 }
970 }
971 gl2psFree(frontprim->verts);
972 gl2psFree(frontprim);
973 gl2psFree(backprim->verts);
974 gl2psFree(backprim);
975 return ret;
976 case GL2PS_COINCIDENT:
977 if(prim->numverts < 3) return 1;
978 else return 0;
979 }
980 }
981 return 0;
982}
983
984void gl2psAddInImageTree(void *a, void *){
985 GL2PSprimitive *prim = *(GL2PSprimitive **)a;
986
987 if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
988 prim->culled = 1;
989 }
990}
991
992/* Boundary contruction */
993
994void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list){
995 GL2PSprimitive *b;
996 GLshort i;
997 GL2PSxyz c;
998
999 c[0] = c[1] = c[2] = 0.;
1000 for(i = 0; i < prim->numverts; i++){
1001 c[0] += prim->verts[i].xyz[0];
1002 c[1] += prim->verts[i].xyz[1];
1003 }
1004 c[0] /= prim->numverts;
1005 c[1] /= prim->numverts;
1006
1007 for(i = 0; i < prim->numverts; i++){
1008 if(prim->boundary & (GLint)pow(2., i)){
1009 b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
1010 b->type = GL2PS_LINE;
1011 b->dash = prim->dash;
1012 b->depth = prim->depth; /* this is wrong */
1013 b->culled = prim->culled;
1014 b->width = prim->width;
1015 b->boundary = 0;
1016 b->numverts = 2;
1017 b->verts = (GL2PSvertex *)gl2psMalloc(2 * sizeof(GL2PSvertex));
1018
1019#if 0 /* need to work on boundary offset... */
1020 v[0] = c[0] - prim->verts[i].xyz[0];
1021 v[1] = c[1] - prim->verts[i].xyz[1];
1022 v[2] = 0.;
1023 norm = gl2psNorm(v);
1024 v[0] /= norm;
1025 v[1] /= norm;
1026 b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
1027 b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
1028 b->verts[0].xyz[2] = prim->verts[i].xyz[2];
1029 v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
1030 v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
1031 norm = gl2psNorm(v);
1032 v[0] /= norm;
1033 v[1] /= norm;
1034 b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
1035 b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
1036 b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
1037#else
1038 b->verts[0].xyz[0] = prim->verts[i].xyz[0];
1039 b->verts[0].xyz[1] = prim->verts[i].xyz[1];
1040 b->verts[0].xyz[2] = prim->verts[i].xyz[2];
1041 b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
1042 b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
1043 b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
1044#endif
1045
1046 b->verts[0].rgba[0] = 0.;
1047 b->verts[0].rgba[1] = 0.;
1048 b->verts[0].rgba[2] = 0.;
1049 b->verts[0].rgba[3] = 0.;
1050 b->verts[1].rgba[0] = 0.;
1051 b->verts[1].rgba[1] = 0.;
1052 b->verts[1].rgba[2] = 0.;
1053 b->verts[1].rgba[3] = 0.;
1054 gl2psListAdd(list, &b);
1055 }
1056 }
1057
1058}
1059
1060void gl2psBuildPolygonBoundary(GL2PSbsptree *tree){
1061 GLint i, n;
1062 GL2PSprimitive *prim;
1063
1064 if(!tree) return;
1065 gl2psBuildPolygonBoundary(tree->back);
1066 n = gl2psListNbr(tree->primitives);
1067 for(i = 0; i < n; i++){
1068 prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i);
1069 if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives);
1070 }
1071 gl2psBuildPolygonBoundary(tree->front);
1072}
1073
1074/* The feedback buffer parser */
1075
1076void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
1077 GL2PSvertex *verts, GLint offset,
1078 char dash, GLfloat width,
1079 char boundary){
1080 GLshort i;
1081 GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
1082 GL2PSprimitive *prim;
1083
1084 prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
1085 prim->type = type;
1086 prim->numverts = numverts;
1087 prim->verts = (GL2PSvertex *)gl2psMalloc(numverts * sizeof(GL2PSvertex));
1088 memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
1089 prim->boundary = boundary;
1090 prim->dash = dash;
1091 prim->width = width;
1092 prim->culled = 0;
1093
1094 if(gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET){
1095
1096 if(type == GL2PS_LINE){
1097 if(gl2ps->sort == GL2PS_SIMPLE_SORT){
1098 prim->verts[0].xyz[2] -= GL2PS_SIMPLE_OFFSET_LARGE;
1099 prim->verts[1].xyz[2] -= GL2PS_SIMPLE_OFFSET_LARGE;
1100 }
1101 else{
1102 prim->verts[0].xyz[2] -= GL2PS_SIMPLE_OFFSET;
1103 prim->verts[1].xyz[2] -= GL2PS_SIMPLE_OFFSET;
1104 }
1105 }
1106
1107 }
1108 else if(offset && type == GL2PS_TRIANGLE){
1109
1110 /* This needs some more work... */
1111
1112 if(gl2ps->sort == GL2PS_SIMPLE_SORT){
1113 factor = gl2ps->offset[0];
1114 units = gl2ps->offset[1];
1115 }
1116 else{
1117 factor = gl2ps->offset[0] / 800.;
1118 units = gl2ps->offset[1] / 800.;
1119 }
1120
1121 area =
1122 (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
1123 (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
1124 (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
1125 (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
1126 dZdX =
1127 (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
1128 (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
1129 (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
1130 (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) / area;
1131 dZdY =
1132 (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
1133 (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
1134 (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
1135 (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) / area;
1136
1137 maxdZ = std::sqrt(dZdX*dZdX + dZdY*dZdY);
1138
1139 dZ = factor * maxdZ + units;
1140
1141 prim->verts[0].xyz[2] += dZ;
1142 prim->verts[1].xyz[2] += dZ;
1143 prim->verts[2].xyz[2] += dZ;
1144 }
1145
1146 prim->depth = 0.;
1147 if(gl2ps->sort == GL2PS_SIMPLE_SORT){
1148 for(i = 0; i < numverts; i++){
1149 prim->depth += prim->verts[i].xyz[2];
1150 }
1151 prim->depth /= (GLfloat)numverts;
1152 }
1153
1154 gl2psListAdd(gl2ps->primitives, &prim);
1155}
1156
1157GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p){
1158 GLint i;
1159
1160 v->xyz[0] = p[0];
1161 v->xyz[1] = p[1];
1162 v->xyz[2] = GL2PS_DEPTH_FACT * p[2];
1163
1164 if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
1165 i = (GLint)(p[3] + 0.5);
1166 v->rgba[0] = gl2ps->colormap[i][0];
1167 v->rgba[1] = gl2ps->colormap[i][1];
1168 v->rgba[2] = gl2ps->colormap[i][2];
1169 v->rgba[3] = gl2ps->colormap[i][3];
1170 return 4;
1171 }
1172 else{
1173 v->rgba[0] = p[3];
1174 v->rgba[1] = p[4];
1175 v->rgba[2] = p[5];
1176 v->rgba[3] = p[6];
1177 return 7;
1178 }
1179}
1180
1181GLint gl2psParseFeedbackBuffer(void){
1182 char flag, dash = 0;
1183 GLshort boundary;
1184 GLint i, used, count, v, vtot, offset = 0;
1185 GLfloat lwidth = 1., psize = 1.;
1186 GLfloat *current;
1187 GL2PSvertex vertices[3];
1188
1189 used = glRenderMode(GL_RENDER);
1190
1191 if(used < 0){
1192 gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow");
1193 return GL2PS_OVERFLOW;
1194 }
1195
1196 if(used == 0){
1197 /* gl2psMsg(GL2PS_INFO, "Empty feedback buffer"); */
1198 return GL2PS_NO_FEEDBACK;
1199 }
1200
1201 current = gl2ps->feedback;
1202 boundary = gl2ps->boundary = 0;
1203
1204 while(used > 0){
1205
1206 if(boundary) gl2ps->boundary = 1;
1207
1208 switch((GLint)*current){
1209 case GL_POINT_TOKEN :
1210 current ++;
1211 used --;
1212 i = gl2psGetVertex(&vertices[0], current);
1213 current += i;
1214 used -= i;
1215 gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, dash, psize, 0);
1216 break;
1217 case GL_LINE_TOKEN :
1218 case GL_LINE_RESET_TOKEN :
1219 current ++;
1220 used --;
1221 i = gl2psGetVertex(&vertices[0], current);
1222 current += i;
1223 used -= i;
1224 i = gl2psGetVertex(&vertices[1], current);
1225 current += i;
1226 used -= i;
1227 gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, dash, lwidth, 0);
1228 break;
1229 case GL_POLYGON_TOKEN :
1230 count = (GLint)current[1];
1231 current += 2;
1232 used -= 2;
1233 v = vtot = 0;
1234 while(count > 0 && used > 0){
1235 i = gl2psGetVertex(&vertices[v], current);
1236 current += i;
1237 used -= i;
1238 count --;
1239 vtot++;
1240 if(v == 2){
1241 if(boundary){
1242 if(!count && vtot == 2) flag = 1|2|4;
1243 else if(!count) flag = 2|4;
1244 else if(vtot == 2) flag = 1|2;
1245 else flag = 2;
1246 }
1247 else
1248 flag = 0;
1249 gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices,
1250 offset, dash, 1, flag);
1251 vertices[1] = vertices[2];
1252 }
1253 else
1254 v ++;
1255 }
1256 break;
1257 case GL_BITMAP_TOKEN :
1258 case GL_DRAW_PIXEL_TOKEN :
1259 case GL_COPY_PIXEL_TOKEN :
1260 current ++;
1261 used --;
1262 i = gl2psGetVertex(&vertices[0], current);
1263 current += i;
1264 used -= i;
1265 break;
1266 case GL_PASS_THROUGH_TOKEN :
1267 switch((GLint)current[1]){
1268 case GL2PS_BEGIN_POLYGON_OFFSET_FILL : offset = 1; break;
1269 case GL2PS_END_POLYGON_OFFSET_FILL : offset = 0; break;
1270 case GL2PS_BEGIN_POLYGON_BOUNDARY : boundary = 1; break;
1271 case GL2PS_END_POLYGON_BOUNDARY : boundary = 0; break;
1272 case GL2PS_BEGIN_LINE_STIPPLE : dash = 4; break;
1273 case GL2PS_END_LINE_STIPPLE : dash = 0; break;
1274 case GL2PS_SET_POINT_SIZE :
1275 current += 2;
1276 used -= 2;
1277 psize = current[1];
1278 break;
1279 case GL2PS_SET_LINE_WIDTH :
1280 current += 2;
1281 used -= 2;
1282 lwidth = current[1];
1283 break;
1284 }
1285 current += 2;
1286 used -= 2;
1287 break;
1288 default :
1289 gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
1290 current ++;
1291 used --;
1292 break;
1293 }
1294 }
1295
1296 return GL2PS_SUCCESS;
1297}
1298
1299GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2){
1300 return !(rgba1[0] != rgba2[0] ||
1301 rgba1[1] != rgba2[1] ||
1302 rgba1[2] != rgba2[2]);
1303}
1304
1305GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim){
1306 int i;
1307
1308 for(i = 1; i < prim->numverts; i++){
1309 if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
1310 return 0;
1311 }
1312 }
1313 return 1;
1314}
1315
1316GLint gl2psPrintPrimitives(void);
1317
1318/* The PostScript routines. Other (vector) image formats should be
1319 easy to generate by creating the three corresponding routines
1320 (gl2psPrintXXXHeader, gl2psPrintXXXPrimitive, gl2psPrintXXXFooter,
1321 gl2psPrintXXXBeginViewport and gl2psPrintXXXEndViewport) for the
1322 new format. */
1323
1324void gl2psWriteByte(FILE *stream, unsigned char byte){
1325 unsigned char h = byte / 16;
1326 unsigned char l = byte % 16;
1327 fprintf(stream, "%x%x", h, l);
1328}
1329
1330int gl2psGetRGB(GLfloat *pixels, GLsizei width, GLsizei height, GLuint x, GLuint y,
1331 GLfloat *red, GLfloat *green, GLfloat *blue){
1332 /* OpenGL image is from down to up, PS image is up to down */
1333 GLfloat *pimag;
1334 pimag = pixels + 3 * (width * (height - 1 - y) + x);
1335 *red = *pimag; pimag++;
1336 *green = *pimag; pimag++;
1337 *blue = *pimag; pimag++;
1338 return 1;
1339}
1340
1341void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GLsizei width, GLsizei height,
1342 GLenum, GLenum, GLfloat *pixels,
1343 FILE *stream){
1344 typedef unsigned char Uchar;
1345 int status = 1, nbhex, nbyte;
1346 int row, col, ibyte,icase;
1347 float dr, dg, db, fgrey;
1348 Uchar red, green, blue, b, grey;
1349 /* Options */
1350 int shade = 0;
1351 //int nbit = 2;
1352 int nbit = 4;
1353 //int nbit = 8;
1354
1355 if((width <= 0) || (height <= 0)) return;
1356
1357 /* Msg(INFO, "gl2psPrintPostScriptPixmap: x %g y %g w %d h %d", x, y, width, height); */
1358
1359 fprintf(stream, "gsave\n");
1360 fprintf(stream, "%.2f %.2f translate\n", x, y);
1361 fprintf(stream, "%d %d scale\n", width, height);
1362
1363 if(shade != 0){ /* grey */
1364 fprintf(stream, "/picstr %d string def\n", width);
1365 fprintf(stream, "%d %d %d\n", width, height, 8);
1366 fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height);
1367 fprintf(stream, "{ currentfile picstr readhexstring pop }\n");
1368 fprintf(stream, "image\n");
1369 for(row = 0; row < height; row++){
1370 for(col = 0; col < width; col++){
1371 status = gl2psGetRGB(pixels, width, height,
1372 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1373 fgrey = (0.30 * dr + 0.59 * dg + 0.11 * db);
1374 grey = (Uchar)(255. * fgrey);
1375 gl2psWriteByte(stream, grey);
1376 }
1377 fprintf(stream, "\n");
1378 }
1379 nbhex = width * height * 2;
1380 fprintf(stream, "%%%% nbhex digit :%d\n", nbhex);
1381 }
1382 else if(nbit == 2){
1383 int nrgb = width * 3;
1384 int nbits = nrgb * nbit;
1385 nbyte = nbits/8;
1386 if((nbyte*8)!=nbits) nbyte++;
1387 /* 2 bit for r and g and b */
1388 /* rgbs following each other */
1389 fprintf(stream, "/rgbstr %d string def\n", nbyte);
1390 fprintf(stream, "%d %d %d\n", width, height, nbit);
1391 fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height);
1392 fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n" );
1393 fprintf(stream, "false 3\n" );
1394 fprintf(stream, "colorimage\n" );
1395 for(row = 0; row < height; row++){
1396 icase = 1;
1397 col = 0;
1398 b = 0;
1399 for(ibyte = 0; ibyte < nbyte; ibyte++){
1400 if(icase==1) {
1401 if(col<width) {
1402 status = gl2psGetRGB(pixels, width, height,
1403 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1404 } else {
1405 dr = dg = db = 0;
1406 }
1407 col++;
1408 red = (Uchar)(3. * dr);
1409 green = (Uchar)(3. * dg);
1410 blue = (Uchar)(3. * db);
1411 b = red;
1412 b = (b<<2)+green;
1413 b = (b<<2)+blue;
1414 if(col<width) {
1415 status = gl2psGetRGB(pixels, width, height,
1416 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1417 } else {
1418 dr = dg = db = 0;
1419 }
1420 col++;
1421 red = (Uchar)(3. * dr);
1422 green = (Uchar)(3. * dg);
1423 blue = (Uchar)(3. * db);
1424 b = (b<<2)+red;
1425 gl2psWriteByte(stream, b);
1426 b = 0;
1427 icase++;
1428 } else if(icase==2) {
1429 b = green;
1430 b = (b<<2)+blue;
1431 if(col<width) {
1432 status = gl2psGetRGB(pixels, width, height,
1433 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1434 } else {
1435 dr = dg = db = 0;
1436 }
1437 col++;
1438 red = (Uchar)(3. * dr);
1439 green = (Uchar)(3. * dg);
1440 blue = (Uchar)(3. * db);
1441 b = (b<<2)+red;
1442 b = (b<<2)+green;
1443 gl2psWriteByte(stream, b);
1444 b = 0;
1445 icase++;
1446 } else if(icase==3) {
1447 b = blue;
1448 if(col<width) {
1449 status = gl2psGetRGB(pixels,width,height,
1450 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1451 } else {
1452 dr = dg = db = 0;
1453 }
1454 col++;
1455 red = (Uchar)(3. * dr);
1456 green = (Uchar)(3. * dg);
1457 blue = (Uchar)(3. * db);
1458 b = (b<<2)+red;
1459 b = (b<<2)+green;
1460 b = (b<<2)+blue;
1461 gl2psWriteByte(stream, b);
1462 b = 0;
1463 icase = 1;
1464 }
1465 }
1466 fprintf(stream, "\n");
1467 }
1468 }
1469 else if(nbit == 4){
1470 int nrgb = width * 3;
1471 int nbits = nrgb * nbit;
1472 nbyte = nbits/8;
1473 if((nbyte*8)!=nbits) nbyte++;
1474 /* 4 bit for r and g and b */
1475 /* rgbs following each other */
1476 fprintf(stream, "/rgbstr %d string def\n", nbyte);
1477 fprintf(stream, "%d %d %d\n", width, height,nbit);
1478 fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height);
1479 fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n");
1480 fprintf(stream, "false 3\n");
1481 fprintf(stream, "colorimage\n");
1482 for(row = 0; row < height; row++){
1483 col = 0;
1484 icase = 1;
1485 for(ibyte = 0; ibyte < nbyte; ibyte++){
1486 if(icase==1) {
1487 if(col<width) {
1488 status = gl2psGetRGB(pixels, width, height,
1489 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1490 } else {
1491 dr = dg = db = 0;
1492 }
1493 col++;
1494 red = (Uchar)(15. * dr);
1495 green = (Uchar)(15. * dg);
1496 fprintf(stream, "%x%x", red, green);
1497 icase++;
1498 } else if(icase==2) {
1499 blue = (Uchar)(15. * db);
1500 if(col<width) {
1501 status = gl2psGetRGB(pixels, width, height,
1502 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1503 } else {
1504 dr = dg = db = 0;
1505 }
1506 col++;
1507 red = (Uchar)(15. * dr);
1508 fprintf(stream,"%x%x",blue,red);
1509 icase++;
1510 } else if(icase==3) {
1511 green = (Uchar)(15. * dg);
1512 blue = (Uchar)(15. * db);
1513 fprintf(stream, "%x%x", green, blue);
1514 icase = 1;
1515 }
1516 }
1517 fprintf(stream, "\n");
1518 }
1519 }
1520 else{
1521 nbyte = width * 3;
1522 /* 8 bit for r and g and b */
1523 fprintf(stream, "/rgbstr %d string def\n", nbyte);
1524 fprintf(stream, "%d %d %d\n", width, height, 8);
1525 fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height);
1526 fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n");
1527 fprintf(stream, "false 3\n");
1528 fprintf(stream, "colorimage\n");
1529 for(row = 0; row < height; row++){
1530 for(col = 0; col < width; col++){
1531 status = gl2psGetRGB(pixels, width, height,
1532 col, row, &dr, &dg, &db) == 0 ? 0 : status;
1533 red = (Uchar)(255. * dr);
1534 gl2psWriteByte(stream, red);
1535 green = (Uchar)(255. * dg);
1536 gl2psWriteByte(stream, green);
1537 blue = (Uchar)(255. * db);
1538 gl2psWriteByte(stream, blue);
1539 }
1540 fprintf(stream, "\n");
1541 }
1542 }
1543
1544 if(status == 0){
1545 gl2psMsg(GL2PS_ERROR, "Problem to retreive some pixel rgb");
1546 }
1547 fprintf(stream, "grestore\n");
1548}
1549
1550void gl2psPrintPostScriptHeader(void){
1551 GLint index;
1552 GLfloat rgba[4];
1553 time_t now;
1554
1555 time(&now);
1556
1557 if(gl2ps->format == GL2PS_PS){
1558 fprintf(gl2ps->stream, "%%!PS-Adobe-3.0\n");
1559 }
1560 else{
1561 fprintf(gl2ps->stream, "%%!PS-Adobe-3.0 EPSF-3.0\n");
1562 }
1563
1564 fprintf(gl2ps->stream,
1565 "%%%%Title: %s\n"
1566 "%%%%Creator: GL2PS, an OpenGL to PostScript Printing Library, v. %g\n"
1567 "%%%%For: %s\n"
1568 "%%%%CreationDate: %s"
1569 "%%%%LanguageLevel: 3\n"
1570 "%%%%DocumentData: Clean7Bit\n"
1571 "%%%%Pages: 1\n",
1572 gl2ps->title, GL2PS_VERSION, gl2ps->producer, ctime(&now));
1573
1574 if(gl2ps->format == GL2PS_PS){
1575 fprintf(gl2ps->stream,
1576 "%%%%Orientation: %s\n"
1577 "%%%%DocumentMedia: Default %d %d 0 () ()\n",
1578 (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
1579 (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[3] : gl2ps->viewport[2],
1580 (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[2] : gl2ps->viewport[3]);
1581 }
1582
1583 fprintf(gl2ps->stream,
1584 "%%%%BoundingBox: %d %d %d %d\n"
1585 "%%%%Copyright: GNU LGPL (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>\n"
1586 "%%%%EndComments\n",
1587 (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[1] : gl2ps->viewport[0],
1588 (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[0] : gl2ps->viewport[1],
1589 (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[3] : gl2ps->viewport[2],
1590 (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[2] : gl2ps->viewport[3]);
1591
1592 /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
1593 Grayscale: r g b G
1594 Font choose: size fontname FC
1595 String primitive: (string) x y size fontname S
1596 Point primitive: x y size P
1597 Line width: width W
1598 Flat-shaded line: x2 y2 x1 y1 L
1599 Smooth-shaded line: x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 SL
1600 Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T
1601 Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */
1602
1603 fprintf(gl2ps->stream,
1604 "%%%%BeginProlog\n"
1605 "/gl2psdict 64 dict def gl2psdict begin\n"
1606 "1 setlinecap 1 setlinejoin\n"
1607 "/tryPS3shading %s def %% set to false to force subdivision\n"
1608 "/rThreshold %g def %% red component subdivision threshold\n"
1609 "/gThreshold %g def %% green component subdivision threshold\n"
1610 "/bThreshold %g def %% blue component subdivision threshold\n"
1611 "/BD { bind def } bind def\n"
1612 "/C { setrgbcolor } BD\n"
1613 "/G { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
1614 "/W { setlinewidth } BD\n"
1615 "/FC { findfont exch scalefont setfont } BD\n"
1616 "/S { FC moveto show } BD\n"
1617 "/P { newpath 0.0 360.0 arc closepath fill } BD\n"
1618 "/L { newpath moveto lineto stroke } BD\n"
1619 "/SL { C moveto C lineto stroke } BD\n"
1620 "/T { newpath moveto lineto lineto closepath fill } BD\n",
1621 (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true",
1622 gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
1623
1624 /* Smooth-shaded triangle with PostScript level 3 shfill operator:
1625 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
1626
1627 fprintf(gl2ps->stream,
1628 "/STshfill {\n"
1629 " /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
1630 " /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
1631 " /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
1632 " gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
1633 " /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
1634 " shfill grestore } BD\n");
1635
1636 /* Flat-shaded triangle with middle color:
1637 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */
1638
1639 fprintf(gl2ps->stream,
1640 /* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */
1641 "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */
1642 /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */
1643 " 3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */
1644 /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */
1645 " 3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */
1646 /* stack : x3 y3 x2 y2 x1 y1 r g b */
1647 " C T } BD\n");
1648
1649 /* Split triangle in four sub-triangles (at sides middle points) and call the
1650 STnoshfill procedure on each, interpolating the colors in RGB space:
1651 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit
1652 (in procedure comments key: (Vi) = xi yi ri gi bi) */
1653
1654 fprintf(gl2ps->stream,
1655 "/STsplit {\n"
1656 " 4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */
1657 " 4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */
1658 " 4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */
1659 " 4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */
1660 " 4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */
1661 " 5 copy 5 copy 25 15 roll\n"
1662 /* stack : (V3) (V13) (V13) (V13) (V2) (V1) */
1663 " 9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */
1664 " 9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */
1665 " 9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */
1666 " 9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */
1667 " 9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */
1668 " 5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n"
1669 /* stack : (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */
1670 " 4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */
1671 " 4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */
1672 " 4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */
1673 " 4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
1674 " 4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
1675 " 5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n"
1676 /* stack : (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
1677 " STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
1678
1679 /* Gouraud shaded triangle using recursive subdivision until the difference
1680 between corner colors does not exceed the thresholds:
1681 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill */
1682
1683 fprintf(gl2ps->stream,
1684 "/STnoshfill {\n"
1685 " 2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */
1686 " { STsplit }\n"
1687 " { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */
1688 " { STsplit }\n"
1689 " { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */
1690 " { STsplit }\n"
1691 " { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */
1692 " { STsplit }\n"
1693 " { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */
1694 " { STsplit }\n"
1695 " { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */
1696 " { STsplit }\n"
1697 " { 7 index 13 index sub abs rThreshold gt\n" /* |r2-r3|>rht */
1698 " { STsplit }\n"
1699 " { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */
1700 " { STsplit }\n"
1701 " { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */
1702 " { STsplit }\n"
1703 " { Tm }\n" /* all colors sufficiently similar */
1704 " ifelse }\n"
1705 " ifelse }\n"
1706 " ifelse }\n"
1707 " ifelse }\n"
1708 " ifelse }\n"
1709 " ifelse }\n"
1710 " ifelse }\n"
1711 " ifelse }\n"
1712 " ifelse } BD\n");
1713
1714 fprintf(gl2ps->stream,
1715 "tryPS3shading\n"
1716 "{ /shfill where\n"
1717 " { /ST { STshfill } BD }\n"
1718 " { /ST { STnoshfill } BD }\n"
1719 " ifelse }\n"
1720 "{ /ST { STnoshfill } BD }\n"
1721 "ifelse\n");
1722
1723 fprintf(gl2ps->stream,
1724 "end\n"
1725 "%%%%EndProlog\n"
1726 "%%%%BeginSetup\n"
1727 "/DeviceRGB setcolorspace\n"
1728 "gl2psdict begin\n"
1729 "%%%%EndSetup\n"
1730 "%%%%Page: 1 1\n"
1731 "%%%%BeginPageSetup\n");
1732
1733 if(gl2ps->options & GL2PS_LANDSCAPE){
1734 fprintf(gl2ps->stream,
1735 "%d 0 translate 90 rotate\n",
1736 gl2ps->viewport[3]);
1737 }
1738
1739 fprintf(gl2ps->stream,
1740 "%%%%EndPageSetup\n"
1741 "mark\n"
1742 "gsave\n"
1743 "1.0 1.0 scale\n");
1744
1745 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
1746 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
1747 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
1748 }
1749 else{
1750 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
1751 rgba[0] = gl2ps->colormap[index][0];
1752 rgba[1] = gl2ps->colormap[index][1];
1753 rgba[2] = gl2ps->colormap[index][2];
1754 rgba[3] = 0.;
1755 }
1756 fprintf(gl2ps->stream,
1757 "%g %g %g C\n"
1758 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
1759 "closepath fill\n",
1760 rgba[0], rgba[1], rgba[2],
1761 gl2ps->viewport[0], gl2ps->viewport[1], gl2ps->viewport[2],
1762 gl2ps->viewport[1], gl2ps->viewport[2], gl2ps->viewport[3],
1763 gl2ps->viewport[0], gl2ps->viewport[3]);
1764 }
1765}
1766
1767void gl2psPrintPostScriptColor(GL2PSrgba rgba){
1768 if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
1769 gl2ps->lastrgba[0] = rgba[0];
1770 gl2ps->lastrgba[1] = rgba[1];
1771 gl2ps->lastrgba[2] = rgba[2];
1772 fprintf(gl2ps->stream, "%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
1773 }
1774}
1775
1776void gl2psResetPostScriptColor(void){
1777 gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
1778}
1779
1780void gl2psPrintPostScriptPrimitive(void *a, void *){
1781 GL2PSprimitive *prim;
1782
1783 prim = *(GL2PSprimitive**)a;
1784
1785 if(gl2ps->options & GL2PS_OCCLUSION_CULL && prim->culled) return;
1786
1787 switch(prim->type){
1788 case GL2PS_PIXMAP :
1789 gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
1790 prim->image->width, prim->image->height,
1791 prim->image->format, prim->image->type,
1792 prim->image->pixels, gl2ps->stream);
1793 break;
1794 case GL2PS_TEXT :
1795 gl2psPrintPostScriptColor(prim->verts[0].rgba);
1796 fprintf(gl2ps->stream, "(%s) %g %g %d /%s S\n",
1797 prim->text->str, prim->verts[0].xyz[0], prim->verts[0].xyz[1],
1798 prim->text->fontsize, prim->text->fontname);
1799 break;
1800 case GL2PS_POINT :
1801 gl2psPrintPostScriptColor(prim->verts[0].rgba);
1802 fprintf(gl2ps->stream, "%g %g %g P\n",
1803 prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5*prim->width);
1804 break;
1805 case GL2PS_LINE :
1806 if(gl2ps->lastlinewidth != prim->width){
1807 gl2ps->lastlinewidth = prim->width;
1808 fprintf(gl2ps->stream, "%g W\n", gl2ps->lastlinewidth);
1809 }
1810 if(prim->dash){
1811 fprintf(gl2ps->stream, "[%d] 0 setdash\n", prim->dash);
1812 }
1813 if(gl2ps->shade && !gl2psVertsSameColor(prim)){
1814 gl2psResetPostScriptColor();
1815 fprintf(gl2ps->stream, "%g %g %g %g %g %g %g %g %g %g SL\n",
1816 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
1817 prim->verts[1].rgba[0], prim->verts[1].rgba[1],
1818 prim->verts[1].rgba[2], prim->verts[0].xyz[0],
1819 prim->verts[0].xyz[1], prim->verts[0].rgba[0],
1820 prim->verts[0].rgba[1], prim->verts[0].rgba[2]);
1821 }
1822 else{
1823 gl2psPrintPostScriptColor(prim->verts[0].rgba);
1824 fprintf(gl2ps->stream, "%g %g %g %g L\n",
1825 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
1826 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
1827 }
1828 if(prim->dash){
1829 fprintf(gl2ps->stream, "[] 0 setdash\n");
1830 }
1831 break;
1832 case GL2PS_TRIANGLE :
1833 if(gl2ps->shade && !gl2psVertsSameColor(prim)){
1834 gl2psResetPostScriptColor();
1835 fprintf(gl2ps->stream, "%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
1836 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
1837 prim->verts[2].rgba[0], prim->verts[2].rgba[1],
1838 prim->verts[2].rgba[2], prim->verts[1].xyz[0],
1839 prim->verts[1].xyz[1], prim->verts[1].rgba[0],
1840 prim->verts[1].rgba[1], prim->verts[1].rgba[2],
1841 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
1842 prim->verts[0].rgba[0], prim->verts[0].rgba[1],
1843 prim->verts[0].rgba[2]);
1844 }
1845 else{
1846 gl2psPrintPostScriptColor(prim->verts[0].rgba);
1847 fprintf(gl2ps->stream, "%g %g %g %g %g %g T\n",
1848 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
1849 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
1850 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
1851 }
1852 break;
1853 case GL2PS_QUADRANGLE :
1854 gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
1855 break;
1856 default :
1857 gl2psMsg(GL2PS_ERROR, "Unknown type of primitive to print");
1858 break;
1859 }
1860}
1861
1862void gl2psPrintPostScriptFooter(void){
1863 fprintf(gl2ps->stream,
1864 "grestore\n"
1865 "showpage\n"
1866 "cleartomark\n"
1867 "%%%%PageTrailer\n"
1868 "%%%%Trailer\n"
1869 "end\n"
1870 "%%%%EOF\n");
1871}
1872
1873void gl2psPrintPostScriptBeginViewport(GLint viewport[4]){
1874 GLint index;
1875 GLfloat rgba[4];
1876 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
1877
1878 glRenderMode(GL_FEEDBACK);
1879
1880 fprintf(gl2ps->stream,
1881 "gsave\n"
1882 "1.0 1.0 scale\n");
1883
1884 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
1885 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
1886 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
1887 }
1888 else{
1889 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
1890 rgba[0] = gl2ps->colormap[index][0];
1891 rgba[1] = gl2ps->colormap[index][1];
1892 rgba[2] = gl2ps->colormap[index][2];
1893 rgba[3] = 0.;
1894 }
1895 fprintf(gl2ps->stream,
1896 "%g %g %g C\n"
1897 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
1898 "closepath fill\n",
1899 rgba[0], rgba[1], rgba[2],
1900 x, y, x+w, y, x+w, y+h, x, y+h);
1901 fprintf(gl2ps->stream,
1902 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
1903 "closepath clip\n",
1904 x, y, x+w, y, x+w, y+h, x, y+h);
1905 }
1906
1907}
1908
1909GLint gl2psPrintPostScriptEndViewport(void){
1910 GLint res;
1911
1912 res = gl2psPrintPrimitives();
1913 fprintf(gl2ps->stream, "grestore\n");
1914 return res;
1915}
1916
1917/* The LaTeX routines */
1918
1919void gl2psPrintTeXHeader(void){
1920 char name[256];
1921 int i;
1922
1923 if(gl2ps->filename && strlen(gl2ps->filename) < 256){
1924 for(i = strlen(gl2ps->filename)-1; i >= 0; i--){
1925 if(gl2ps->filename[i] == '.'){
1926 strncpy(name, gl2ps->filename, i);
1927 name[i] = '\0';
1928 break;
1929 }
1930 }
1931 if(i <= 0) strcpy(name, gl2ps->filename);
1932 }
1933 else{
1934 strcpy(name, "untitled");
1935 }
1936
1937 fprintf(gl2ps->stream,
1938 "\\setlength{\\unitlength}{1pt}\n"
1939 "\\begin{picture}(0,0)\n"
1940 "\\includegraphics{%s}\n"
1941 "\\end{picture}%%\n"
1942 "%s\\begin{picture}(%d,%d)(0,0)\n",
1943 name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "",
1944 gl2ps->viewport[2], gl2ps->viewport[3]);
1945}
1946
1947void gl2psPrintTeXPrimitive(void *a, void *){
1948 GL2PSprimitive *prim;
1949
1950 prim = *(GL2PSprimitive**)a;
1951
1952 switch(prim->type){
1953 case GL2PS_TEXT :
1954 fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)[lb]{%s}}\n",
1955 prim->verts[0].xyz[0], prim->verts[0].xyz[1], prim->text->str);
1956 break;
1957 default :
1958 break;
1959 }
1960}
1961
1962void gl2psPrintTeXFooter(void){
1963 fprintf(gl2ps->stream, "\\end{picture}%s\n",
1964 (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : "");
1965}
1966
1967void gl2psPrintTeXBeginViewport(GLint){
1968}
1969
1970GLint gl2psPrintTeXEndViewport(void){
1971 return GL2PS_SUCCESS;
1972}
1973
1974/* The general primitive printing routine */
1975
1976GLint gl2psPrintPrimitives(void){
1977 GL2PSbsptree *root;
1978 GL2PSxyz eye = {0., 0., 100000.};
1979 GLint shademodel, res;
1980 void (*pprim)(void *a, void *b) = 0;
1981
1982 glGetIntegerv(GL_SHADE_MODEL, &shademodel);
1983 gl2ps->shade = (shademodel == GL_SMOOTH);
1984
1985 if(gl2ps->format == GL2PS_TEX){
1986 res = GL2PS_SUCCESS;
1987 }
1988 else{
1989 res = gl2psParseFeedbackBuffer();
1990 }
1991
1992 if(res == GL2PS_SUCCESS){
1993
1994 switch(gl2ps->format){
1995 case GL2PS_TEX :
1996 pprim = gl2psPrintTeXPrimitive;
1997 break;
1998 case GL2PS_PS :
1999 case GL2PS_EPS :
2000 pprim = gl2psPrintPostScriptPrimitive;
2001 break;
2002 }
2003
2004 switch(gl2ps->sort){
2005 case GL2PS_NO_SORT :
2006 gl2psListAction(gl2ps->primitives, pprim);
2007 gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
2008 /* reset the primitive list, waiting for the next viewport */
2009 gl2psListReset(gl2ps->primitives);
2010 break;
2011 case GL2PS_SIMPLE_SORT :
2012 gl2psListSort(gl2ps->primitives, gl2psCompareDepth);
2013 if(gl2ps->options & GL2PS_OCCLUSION_CULL){
2014 gl2psListAction(gl2ps->primitives, gl2psAddInImageTree);
2015 gl2psFreeBspImageTree(&gl2ps->imagetree);
2016 }
2017 gl2psListActionInverse(gl2ps->primitives, pprim);
2018 gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
2019 /* reset the primitive list, waiting for the next viewport */
2020 gl2psListReset(gl2ps->primitives);
2021 break;
2022 case GL2PS_BSP_SORT :
2023 root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
2024 gl2psBuildBspTree(root, gl2ps->primitives);
2025 if(gl2ps->boundary) gl2psBuildPolygonBoundary(root);
2026 if(gl2ps->options & GL2PS_OCCLUSION_CULL){
2027 gl2psTraverseBspTree(root, eye, -(float)GL2PS_EPSILON, gl2psLess,
2028 gl2psAddInImageTree);
2029 gl2psFreeBspImageTree(&gl2ps->imagetree);
2030 }
2031 gl2psTraverseBspTree(root, eye, (float)GL2PS_EPSILON, gl2psGreater,
2032 pprim);
2033 gl2psFreeBspTree(&root);
2034 /* reallocate the primitive list (it's been deleted by
2035 gl2psBuildBspTree) in case there is another viewport */
2036 gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
2037 break;
2038 default :
2039 gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", gl2ps->sort);
2040 res = GL2PS_ERROR;
2041 break;
2042 }
2043 fflush(gl2ps->stream);
2044
2045 }
2046
2047 return res;
2048}
2049
2050/* The public routines */
2051
2052GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
2053 GLint viewport[4], GLint format, GLint sort,
2054 GLint options, GLint colormode,
2055 GLint colorsize, GL2PSrgba *colormap,
2056 GLint nr, GLint ng, GLint nb, GLint buffersize,
2057 FILE *stream, const char *filename){
2058 int i;
2059
2060 gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext));
2061 gl2ps->maxbestroot = 10;
2062 gl2ps->format = format;
2063 gl2ps->title = title;
2064 gl2ps->producer = producer;
2065 gl2ps->filename = filename;
2066 gl2ps->sort = sort;
2067 gl2ps->options = options;
2068 for(i = 0; i < 4; i++){
2069 gl2ps->viewport[i] = viewport[i];
2070 }
2071 gl2ps->threshold[0] = nr ? 1./(GLfloat)nr : 0.032;
2072 gl2ps->threshold[1] = ng ? 1./(GLfloat)ng : 0.017;
2073 gl2ps->threshold[2] = nb ? 1./(GLfloat)nb : 0.05;
2074 gl2ps->colormode = colormode;
2075 gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
2076 for(i = 0; i < 4; i++){
2077 gl2ps->lastrgba[i] = -1.;
2078 }
2079 gl2ps->lastlinewidth = -1.;
2080 gl2ps->imagetree = NULL;
2081
2082 if(gl2ps->colormode == GL_RGBA){
2083 gl2ps->colorsize = 0;
2084 gl2ps->colormap = NULL;
2085 }
2086 else if(gl2ps->colormode == GL_COLOR_INDEX){
2087 if(!colorsize || !colormap){
2088 gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering");
2089 gl2psFree(gl2ps);
2090 gl2ps = NULL;
2091 return GL2PS_ERROR;
2092 }
2093 gl2ps->colorsize = colorsize;
2094 gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba));
2095 memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba));
2096 }
2097 else{
2098 gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage");
2099 gl2psFree(gl2ps);
2100 gl2ps = NULL;
2101 return GL2PS_ERROR;
2102 }
2103
2104 if(!stream){
2105 gl2psMsg(GL2PS_ERROR, "Bad file pointer");
2106 gl2psFree(gl2ps);
2107 gl2ps = NULL;
2108 return GL2PS_ERROR;
2109 }
2110 else{
2111 gl2ps->stream = stream;
2112 /* In case gl2psEndPage failed (e.g. due to a GL2PS_OVERFLOW) and
2113 we didn't reopen the stream before calling gl2psBeginPage
2114 again, we need to rewind the stream */
2115 rewind(gl2ps->stream);
2116 }
2117
2118 switch(gl2ps->format){
2119 case GL2PS_TEX :
2120 gl2psPrintTeXHeader();
2121 break;
2122 case GL2PS_PS :
2123 case GL2PS_EPS :
2124 gl2psPrintPostScriptHeader();
2125 break;
2126 default :
2127 gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", gl2ps->format);
2128 gl2psFree(gl2ps);
2129 gl2ps = NULL;
2130 return GL2PS_ERROR;
2131 }
2132
2133 gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
2134 gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
2135 glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
2136 glRenderMode(GL_FEEDBACK);
2137
2138 return GL2PS_SUCCESS;
2139}
2140
2141GL2PSDLL_API GLint gl2psEndPage(void){
2142 GLint res;
2143
2144 if(!gl2ps) return GL2PS_UNINITIALIZED;
2145
2146 res = gl2psPrintPrimitives();
2147
2148 /* print the footer even if gl2psPrintPrimitives didn't succeed, so
2149 that we end up with a valid file */
2150 switch(gl2ps->format){
2151 case GL2PS_TEX :
2152 gl2psPrintTeXFooter();
2153 break;
2154 case GL2PS_PS :
2155 case GL2PS_EPS :
2156 gl2psPrintPostScriptFooter();
2157 break;
2158 }
2159
2160 fflush(gl2ps->stream);
2161
2162 gl2psListDelete(gl2ps->primitives);
2163 gl2psFree(gl2ps->colormap);
2164 gl2psFree(gl2ps->feedback);
2165 gl2psFree(gl2ps);
2166 gl2ps = NULL;
2167
2168 return res;
2169}
2170
2171GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]){
2172 if(!gl2ps) return GL2PS_UNINITIALIZED;
2173
2174 switch(gl2ps->format){
2175 case GL2PS_EPS :
2176 gl2psPrintPostScriptBeginViewport(viewport);
2177 break;
2178 default :
2179 /* FIXME: handle other formats */
2180 break;
2181 }
2182
2183 return GL2PS_SUCCESS;
2184}
2185
2186GL2PSDLL_API GLint gl2psEndViewport(void){
2187 GLint res;
2188
2189 if(!gl2ps) return GL2PS_UNINITIALIZED;
2190
2191 switch(gl2ps->format){
2192 case GL2PS_EPS :
2193 res = gl2psPrintPostScriptEndViewport();
2194 break;
2195 default :
2196 /* FIXME: handle other formats */
2197 res = GL2PS_SUCCESS;
2198 break;
2199 }
2200
2201 return res;
2202}
2203
2204GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize){
2205 GLfloat pos[4];
2206 GL2PSprimitive *prim;
2207 GLboolean valid;
2208
2209 if(!gl2ps || !str) return GL2PS_UNINITIALIZED;
2210
2211 if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS;
2212
2213 glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
2214 if(!valid) return GL2PS_SUCCESS; /* the primitive is culled */
2215
2216 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
2217
2218 prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
2219 prim->type = GL2PS_TEXT;
2220 prim->boundary = 0;
2221 prim->numverts = 1;
2222 prim->verts = (GL2PSvertex *)gl2psMalloc(sizeof(GL2PSvertex));
2223 prim->verts[0].xyz[0] = pos[0];
2224 prim->verts[0].xyz[1] = pos[1];
2225 prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2];
2226 prim->depth = pos[2];
2227 prim->culled = 0;
2228 prim->dash = 0;
2229 prim->width = 1;
2230 glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
2231 prim->text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
2232 prim->text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
2233 strcpy(prim->text->str, str);
2234 prim->text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
2235 strcpy(prim->text->fontname, fontname);
2236 prim->text->fontsize = fontsize;
2237
2238 gl2psListAdd(gl2ps->primitives, &prim);
2239
2240 return GL2PS_SUCCESS;
2241}
2242
2243GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
2244 GLint xorig, GLint yorig,
2245 GLenum format, GLenum type,
2246 const void *pixels){
2247 int size;
2248 GLfloat pos[4];
2249 GL2PSprimitive *prim;
2250 GLboolean valid;
2251
2252 if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED;
2253
2254 if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
2255
2256 if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS;
2257
2258 if(format != GL_RGB || type != GL_FLOAT){
2259 gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for GL_RGB, GL_FLOAT pixels");
2260 return GL2PS_ERROR;
2261 }
2262
2263 glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
2264 if(!valid) return GL2PS_SUCCESS; /* the primitive is culled */
2265
2266 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
2267
2268 prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
2269 prim->type = GL2PS_PIXMAP;
2270 prim->boundary = 0;
2271 prim->numverts = 1;
2272 prim->verts = (GL2PSvertex *)gl2psMalloc(sizeof(GL2PSvertex));
2273 prim->verts[0].xyz[0] = pos[0] + xorig;
2274 prim->verts[0].xyz[1] = pos[1] + yorig;
2275 prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2];
2276 prim->depth = pos[2];
2277 prim->culled = 0;
2278 prim->dash = 0;
2279 prim->width = 1;
2280 glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
2281 prim->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
2282 prim->image->width = width;
2283 prim->image->height = height;
2284 prim->image->format = format;
2285 prim->image->type = type;
2286 size = height*width*3*sizeof(GLfloat); /* FIXME: generalize to other types/formats */
2287 prim->image->pixels = (GLfloat*)gl2psMalloc(size);
2288 memcpy(prim->image->pixels, pixels, size);
2289
2290 gl2psListAdd(gl2ps->primitives, &prim);
2291
2292 return GL2PS_SUCCESS;
2293}
2294
2295GL2PSDLL_API GLint gl2psEnable(GLint mode){
2296 if(!gl2ps) return GL2PS_UNINITIALIZED;
2297
2298 switch(mode){
2299 case GL2PS_POLYGON_OFFSET_FILL :
2300 glPassThrough(GL2PS_BEGIN_POLYGON_OFFSET_FILL);
2301 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]);
2302 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]);
2303 break;
2304 case GL2PS_POLYGON_BOUNDARY :
2305 glPassThrough(GL2PS_BEGIN_POLYGON_BOUNDARY);
2306 break;
2307 case GL2PS_LINE_STIPPLE :
2308 glPassThrough(GL2PS_BEGIN_LINE_STIPPLE);
2309 break;
2310 default :
2311 gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode);
2312 return GL2PS_WARNING;
2313 }
2314
2315 return GL2PS_SUCCESS;
2316}
2317
2318GL2PSDLL_API GLint gl2psDisable(GLint mode){
2319 if(!gl2ps) return GL2PS_UNINITIALIZED;
2320
2321 switch(mode){
2322 case GL2PS_POLYGON_OFFSET_FILL :
2323 glPassThrough(GL2PS_END_POLYGON_OFFSET_FILL);
2324 break;
2325 case GL2PS_POLYGON_BOUNDARY :
2326 glPassThrough(GL2PS_END_POLYGON_BOUNDARY);
2327 break;
2328 case GL2PS_LINE_STIPPLE :
2329 glPassThrough(GL2PS_END_LINE_STIPPLE);
2330 break;
2331 default :
2332 gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode);
2333 return GL2PS_WARNING;
2334 }
2335
2336 return GL2PS_SUCCESS;
2337}
2338
2339GL2PSDLL_API GLint gl2psPointSize(GLfloat value){
2340 if(!gl2ps) return GL2PS_UNINITIALIZED;
2341
2342 glPassThrough(GL2PS_SET_POINT_SIZE);
2343 glPassThrough(value);
2344
2345 return GL2PS_SUCCESS;
2346}
2347
2348GL2PSDLL_API GLint gl2psLineWidth(GLfloat value){
2349 if(!gl2ps) return GL2PS_UNINITIALIZED;
2350
2351 glPassThrough(GL2PS_SET_LINE_WIDTH);
2352 glPassThrough(value);
2353
2354 return GL2PS_SUCCESS;
2355}
2356
2357#endif
Note: See TracBrowser for help on using the repository browser.