source: trunk/source/visualization/externals/gl2ps/src/gl2ps.cc@ 932

Last change on this file since 932 was 930, checked in by garnier, 17 years ago

rien de special, juste un backup avant de commiter sur cvs

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