Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/camera/context.cc
3203 views
1
//
2
// "$Id: context.cc,v 1.1 2003/02/06 09:37:53 jpr Exp $"
3
//
4
// GLPcontext class functions for the GLP library, an OpenGL printing
5
// toolkit.
6
//
7
// The GLP library is distributed under the terms of the GNU Library
8
// General Public License which is described in the file "COPYING.LIB".
9
// If you use this library in your program, please include a line reading
10
// "OpenGL Printing Toolkit by Michael Sweet" in your version or copyright
11
// output.
12
//
13
// Contents:
14
//
15
// ~GLPcontext, StartPage, UpdatePage, EndPage,
16
// add_primitive, sort_primitive, get_vertex, delete_all
17
//
18
// Revision History:
19
//
20
// $Log: context.cc,v $
21
// Revision 1.1 2003/02/06 09:37:53 jpr
22
// *** empty log message ***
23
//
24
// 2003/02/01 Juha Ruokolainen / CSC - IT Center for Science Ltd.
25
// Fixed some bugs in add_primitive. Changed the list of primitives
26
// to a binary tree of primitives. Sorting now works correctly.
27
// Added handling of GL_LINE_RESET_TOKEN, but the line patterns etc. are
28
// still silently ignored.
29
//
30
// Revision 1.2 1996/07/13 12:52:02 mike
31
// Fixed delete_all() - was not setting bboxes list pointer to NULL at end.
32
//
33
// Revision 1.1 1996/06/27 00:58:11 mike
34
// Initial revision
35
//
36
37
//
38
// Include necessary headers.
39
//
40
41
#include <../../config.h>
42
43
#include "glp.h"
44
#include <math.h>
45
#include <stdlib.h>
46
#ifdef HAVE_STRING_H
47
#include <string.h>
48
#endif
49
50
//#define DEBUG
51
52
53
#define min(a,b) ((a) < (b) ? (a) : (b))
54
#define max(a,b) ((a) > (b) ? (a) : (b))
55
56
57
//
58
// GLPcontext destructor; like the constructor, this just does the basics.
59
// You'll want to implement your own...
60
//
61
62
GLPcontext :: ~GLPcontext(void)
63
{
64
// Free any memory we've allocated...
65
66
delete_all();
67
68
// if (feedback != NULL)
69
// delete feedback;
70
// if (colormap != NULL)
71
// delete colormap;
72
}
73
74
75
//
76
// 'StartPage' function for RGBA windows; this should perform any necessary
77
// output initialization (e.g. send 'start of page' commands, etc) and enable
78
// feedback mode...
79
//
80
81
int
82
GLPcontext :: StartPage(int mode)
83
{
84
// Initialize feedback mode...
85
86
feedmode = mode;
87
88
#ifdef DEBUG
89
cout << "RGBA feedmode = " << mode << "\n" << flush;
90
#endif /* DEBUG */
91
92
glFeedbackBuffer(feedsize, GL_3D_COLOR, feedback);
93
glRenderMode(GL_FEEDBACK);
94
95
// You'd put any other 'start page' things here...
96
97
return (0);
98
}
99
100
101
//
102
// 'StartPage' function for color index windows; this does the same thing as
103
// the RGBA start page function, and also copies the given colormap into our
104
// class colormap structure for later use...
105
//
106
107
int
108
GLPcontext :: StartPage(int mode,
109
int size,
110
GLPrgba *rgba)
111
{
112
// Initialize feedback mode...
113
114
feedmode = mode;
115
116
#ifdef DEBUG
117
cout << "Index feedmode = " << mode << "\n" << flush;
118
#endif /* DEBUG */
119
120
glFeedbackBuffer(feedsize, GL_3D_COLOR, feedback);
121
glRenderMode(GL_FEEDBACK);
122
123
// Copy the colormap over, removing the old one as necessary...
124
125
if (colormap != NULL)
126
delete colormap;
127
128
colorsize = size;
129
colormap = new GLPrgba[size];
130
memcpy(colormap, rgba, size * sizeof(GLPrgba));
131
132
// You'd put any other 'start page' things here...
133
134
return (0);
135
}
136
137
138
//
139
// 'UpdatePage' function; this does most of the dirty work, adding feedback
140
// data to the current primitive list.
141
//
142
// If the 'more' argument is TRUE then the current rendering mode is put back
143
// into 'GL_FEEDBACK' mode...
144
//
145
// Normally you won't redefine this function...
146
//
147
#include <stdio.h>
148
149
int
150
GLPcontext :: UpdatePage(GLboolean more)
151
{
152
int i, used, count, v;
153
GLfloat *current;
154
GLPvertex vertices[3];
155
GLboolean depth,
156
shade;
157
GLint shademodel;
158
159
160
#ifdef DEBUG
161
cout << "UpdatePage(" << (more ? "GL_TRUE" : "GL_FALSE") << ")\n" << flush;
162
#endif /* DEBUG */
163
164
// Get the current depth test state and shade model...
165
166
depth = glIsEnabled(GL_DEPTH_TEST);
167
glGetIntegerv(GL_SHADE_MODEL, &shademodel);
168
shade = shademodel == GL_SMOOTH;
169
170
// Figure out how many feedback entries there are and put the current
171
// OpenGL context back in feedback mode if 'more' is true...
172
173
used = glRenderMode(more ? GL_FEEDBACK : GL_RENDER);
174
fprintf( stderr, "yseD: %d\n", used );
175
if (used <= 0) return (GLP_NO_FEEDBACK);
176
177
#ifdef DEBUG
178
cout << "glGetError() after glRenderMode returned " << glGetError() << "\n" << flush;
179
cout << "First: used = " << used << ", feedback[0] = " << feedback[0] << "\n" << flush;
180
#endif /* DEBUG */
181
182
// Parse the feedback buffer...
183
184
current = feedback;
185
while (used > 0)
186
{
187
#ifdef DEBUG
188
cout << "Loop: used = " << used << "\n" << flush;
189
#endif /* DEBUG */
190
191
switch ((int)*current)
192
{
193
case GL_POINT_TOKEN :
194
current ++;
195
used --;
196
i = get_vertex(vertices + 0, current);
197
current += i;
198
used -= i;
199
add_primitive(depth, shade, 1, vertices);
200
break;
201
case GL_LINE_TOKEN: case GL_LINE_RESET_TOKEN:
202
current ++;
203
used --;
204
i = get_vertex(vertices + 0, current);
205
current += i;
206
used -= i;
207
i = get_vertex(vertices + 1, current);
208
current += i;
209
used -= i;
210
add_primitive(depth, shade, 2, vertices);
211
break;
212
213
case GL_POLYGON_TOKEN :
214
// Get the number of vertices...
215
216
count = (int)current[1];
217
218
current += 2;
219
used -= 2;
220
221
// Loop through and add a series of triangles...
222
223
v = 0;
224
while (count > 0 && used > 0)
225
{
226
i = get_vertex( vertices + v, current );
227
current += i;
228
used -= i;
229
count --;
230
231
// Add a triangle if we have 3 vertices...
232
233
if (v == 2)
234
{
235
add_primitive( depth, shade, 3, vertices );
236
vertices[1] = vertices[2];
237
v = 0;
238
}
239
else
240
v++;
241
};
242
break;
243
244
case GL_BITMAP_TOKEN :
245
case GL_DRAW_PIXEL_TOKEN :
246
case GL_COPY_PIXEL_TOKEN :
247
current ++;
248
used --;
249
i = get_vertex(vertices + 0, current);
250
current += i;
251
used -= i;
252
break;
253
254
case GL_PASS_THROUGH_TOKEN :
255
#ifdef DEBUG
256
std::cout << "UpdatePage: Ignoring passthrough token " << current[1] << "...\n" << std::flush;
257
#endif /* DEBUG */
258
current += 2;
259
used -= 2;
260
break;
261
262
default :
263
std::cout << "UpdatePage: Ignoring unknown token " << current[0] << "...\n" << std::flush;
264
current ++;
265
used --;
266
break;
267
};
268
};
269
270
return (GLP_SUCCESS);
271
}
272
273
274
//
275
// 'EndPage' function; this does nothing except parse the bounding boxes
276
// and output any remaining primitives. It then frees the bounding box
277
// and primitive lists...
278
//
279
280
int
281
GLPcontext :: EndPage(void)
282
{
283
GLPbbox *bbox; // Current bounding box
284
GLPprimitive *prim; // Current primitive
285
286
287
#ifdef DEBUG
288
cout << "EndPage()\n" << flush;
289
#endif /* DEBUG */
290
291
// Stop doing feedback...
292
293
UpdatePage(GL_FALSE);
294
295
if (bboxes == NULL) return (GLP_NO_FEEDBACK);
296
297
// Loop through all bounding boxes and primitives...
298
for (bbox = bboxes; bbox != NULL; bbox = bbox->next)
299
{
300
};
301
302
// Delete everything from the bounding box and primitive lists...
303
304
delete_all();
305
306
#ifdef DEBUG
307
cout << "EndPage() - done.\n" << flush;
308
#endif /* DEBUG */
309
310
return (GLP_SUCCESS);
311
}
312
313
314
//
315
// 'SetOptions' function; this just sets the 'options' member to whatever is
316
// passed in.
317
//
318
319
void
320
GLPcontext :: SetOptions(int print_options) // I - New printing options
321
{
322
options = print_options;
323
}
324
325
326
//
327
// 'add_primitive' function; add a primitive to the list of primitives and
328
// bounding boxes for the current context.
329
//
330
331
void
332
GLPcontext :: add_primitive(GLboolean depth, // I - Depth testing enabled?
333
GLboolean shade, // I - Smooth shading?
334
int num_verts,// I - Number of vertices
335
GLPvertex *verts) // I - Vertices
336
{
337
int i, // Looping var
338
count; // Count of intersections
339
GLfloat min[3], // Minimum (x,y) coords
340
max[3]; // Maximum (x,y) coords
341
GLPprimitive *newprim,*pprim,*ppprim; // New primitive
342
GLPbbox *bbox, // Current bounding box
343
*joinbbox, // Bounding box to join with
344
*nextbbox; // Next bounding box...
345
346
347
#ifdef DEBUG
348
cout << "add_primitive(" << (depth ? "GL_TRUE" : "GL_FALSE") << ", "
349
<< (shade ? "GL_TRUE" : "GL_FALSE") << ", "
350
<< num_verts << ", "
351
<< (int)verts << ")\n" << flush;
352
#endif /* DEBUG */
353
354
// First create the new primitive and compute the bounding box for it...
355
356
newprim = new GLPprimitive;
357
358
newprim->left = NULL;
359
newprim->right = NULL;
360
newprim->shade = shade;
361
newprim->num_verts = num_verts;
362
memcpy( newprim->verts, verts, sizeof(GLPvertex) * num_verts );
363
364
min[0] = min[1] = min[2] = 1e20;
365
max[0] = max[1] = max[2] = -1e20;
366
367
for (i = 0; i < num_verts; i ++)
368
{
369
if ( verts[i].xyz[0] < min[0] ) min[0] = verts[i].xyz[0];
370
if ( verts[i].xyz[1] < min[1] ) min[1] = verts[i].xyz[1];
371
if ( verts[i].xyz[2] < min[2] ) min[2] = verts[i].xyz[2];
372
373
if ( verts[i].xyz[0] > max[0] ) max[0] = verts[i].xyz[0];
374
if ( verts[i].xyz[1] > max[1] ) max[1] = verts[i].xyz[1];
375
if ( verts[i].xyz[2] > max[2] ) max[2] = verts[i].xyz[2];
376
};
377
378
newprim->zmin = min[2];
379
newprim->zmax = max[2];
380
381
// Stretch the bbox out to the nearest 64 pixels to improve performance...
382
min[0] = floor( min[0] * 0.015625 ) * 64.0;
383
min[1] = floor( min[1] * 0.015625 ) * 64.0;
384
max[0] = ceil( max[0] * 0.015625 ) * 64.0;
385
max[1] = ceil( max[1] * 0.015625 ) * 64.0;
386
387
// Now search the current bounding box list to see if this primitive lies
388
// inside an existing bbox, partially inside, or completely outside...
389
//
390
// The 'count' variable counts the number of corners that lie inside the
391
// current bounding box. If 'count' is 0, then the bbox is completely
392
// outside the current bbox. Values between 1 and 3 indicate a partially
393
// inside primitive. A value of 4 means that the primitive is completely
394
// inside the bbox.
395
//
396
// If the primitive lies completely outside any bboxes that are out there
397
// already, then a new bbox is created with the primitive in it.
398
//
399
// If the primitive lies partially inside the bbox, the bbox is expanded to
400
// include the primitive, and a 'join' operation is performed with any
401
// neighboring bboxes that intersect with the expanded bbox. Finall, the
402
// primitive is added to the bbox using the 'sort_primitive()' function
403
// (this handles depth buffering if enabled).
404
//
405
// If the primitive lies completely inside the bbox, it is added with
406
// 'sort_primitive()'.
407
408
for (bbox = bboxes; bbox != NULL; bbox = bbox->next)
409
{
410
count = 0;
411
412
if ( min[0] > bbox->min[0] && min[0] < bbox->max[0] ) count++;
413
if ( max[0] > bbox->min[0] && max[0] < bbox->max[0] ) count++;
414
if ( min[1] > bbox->min[1] && min[1] < bbox->max[1] ) count++;
415
if ( max[1] > bbox->min[1] && max[1] < bbox->max[1] ) count++;
416
417
if ( count > 0 ) break;
418
};
419
420
if (bbox == NULL)
421
{
422
// New bbox...
423
424
bbox = new GLPbbox;
425
426
bbox->prev = NULL;
427
bbox->next = bboxes;
428
if (bboxes != NULL) bboxes->prev = bbox;
429
bboxes = bbox;
430
431
bbox->min[0] = min[0];
432
bbox->max[0] = max[0];
433
bbox->min[1] = min[1];
434
bbox->max[1] = max[1];
435
bbox->min[2] = min[2];
436
bbox->max[2] = max[2];
437
bbox->primitives = newprim;
438
bbox->lastprim = newprim;
439
}
440
else if (count < 4)
441
{
442
// Partially inside...
443
444
if ( min[0] < bbox->min[0] ) bbox->min[0] = min[0];
445
if ( max[0] > bbox->max[0] ) bbox->max[0] = max[0];
446
if ( min[1] < bbox->min[1] ) bbox->min[1] = min[1];
447
if ( max[1] > bbox->max[1] ) bbox->max[1] = max[1];
448
449
// Incrementally join bounding boxes until no more boxes are joined...
450
451
do
452
{
453
count = 0;
454
for (joinbbox = bboxes; joinbbox != NULL; joinbbox = nextbbox)
455
{
456
nextbbox = joinbbox->next;
457
458
if (joinbbox == bbox)
459
continue;
460
else if (( bbox->min[0] > joinbbox->min[0] && bbox->min[0] < joinbbox->max[0]) ||
461
( bbox->max[0] > joinbbox->min[0] && bbox->max[0] < joinbbox->max[0]) ||
462
( bbox->min[1] > joinbbox->min[1] && bbox->min[1] < joinbbox->max[1]) ||
463
( bbox->max[1] > joinbbox->min[1] && bbox->max[1] < joinbbox->max[1]))
464
{
465
// Join this one...
466
467
count++;
468
469
if (joinbbox->prev == NULL)
470
bboxes = joinbbox->next;
471
else
472
(joinbbox->prev)->next = joinbbox->next;
473
474
if (nextbbox != NULL)
475
nextbbox->prev = joinbbox->prev;
476
477
for (i = 0; i < 3; i ++)
478
{
479
if ( joinbbox->min[i] < bbox->min[i] ) bbox->min[i] = joinbbox->min[i];
480
if ( joinbbox->max[i] > bbox->max[i] ) bbox->max[i] = joinbbox->max[i];
481
};
482
483
add_subtree( &bbox->primitives, joinbbox->primitives );
484
delete joinbbox;
485
};
486
};
487
}
488
while (count > 0);
489
490
// Add the primitive to this bbox...
491
492
add_tree( &bbox->primitives, newprim);
493
}
494
else
495
{
496
// Primitive lies completely inside the bbox, so just add it...
497
add_tree( &bbox->primitives, newprim);
498
};
499
}
500
501
502
//
503
// 'get_vertex' function; get a vertex from the feedback buffer...
504
//
505
506
int
507
GLPcontext :: get_vertex(GLPvertex *v, // O - Vertex pointer
508
GLfloat *p) // I - Data pointer
509
{
510
int i; // Color index
511
512
513
v->xyz[0] = p[0];
514
v->xyz[1] = p[1];
515
v->xyz[2] = p[2];
516
517
#ifdef DEBUG
518
cout << "{ " << p[0] << ", " << p[1] << ", " << p[2] << "}, " << flush;
519
#endif /* DEBUG */
520
521
if (feedmode == GL_COLOR_INDEX && colorsize > 0)
522
{
523
// Color index value...
524
i = (int)(p[3] + 0.5);
525
526
v->rgba[0] = colormap[i][0];
527
v->rgba[1] = colormap[i][1];
528
v->rgba[2] = colormap[i][2];
529
v->rgba[3] = colormap[i][3];
530
531
return (4);
532
}
533
else
534
{
535
// RGBA value...
536
537
v->rgba[0] = p[3];
538
v->rgba[1] = p[4];
539
v->rgba[2] = p[5];
540
v->rgba[3] = p[6];
541
542
return (7);
543
};
544
}
545
546
547
//
548
// 'delete_all' function; delete all bounding boxes and primitives from
549
// the current context.
550
//
551
552
void GLPcontext :: delete_tree( GLPprimitive *tree )
553
{
554
if ( !tree ) return;
555
delete_tree( tree->left );
556
delete_tree( tree->right );
557
delete tree;
558
}
559
560
void
561
GLPcontext :: delete_all(void)
562
{
563
GLPbbox *bbox, // Current bounding box
564
*nextbbox; // Next bounding box
565
GLPprimitive *prim, // Current primitive
566
*nextprim; // Next primitive
567
568
569
#ifdef DEBUG
570
cout << "delete_all()\n" << flush;
571
#endif /* DEBUG */
572
573
for (bbox = bboxes, nextbbox = NULL; bbox != NULL; bbox = nextbbox)
574
{
575
delete_tree( bbox->primitives );
576
nextbbox = bbox->next;
577
delete bbox;
578
};
579
580
bboxes = NULL;
581
582
delete_tree( tree );
583
tree = NULL;
584
585
#ifdef DEBUG
586
cout << "delete_all(): done.\n" << flush;
587
#endif /* DEBUG */
588
}
589
590
591
void GLPcontext::add_subtree( GLPprimitive **ptree, GLPprimitive *prim )
592
{
593
GLPprimitive *left, *right;
594
595
if ( !prim ) return;
596
597
left = prim->left;
598
right = prim->right;
599
600
prim->left = NULL;
601
prim->right = NULL;
602
add_tree( ptree, prim );
603
604
add_subtree( ptree, left );
605
add_subtree( ptree, right );
606
}
607
608
void GLPcontext::add_tree( GLPprimitive **ptree, GLPprimitive *prim )
609
{
610
static int count=0;
611
if ( !*ptree )
612
{
613
*ptree = prim;
614
} else {
615
if ( (prim->zmin+prim->zmax) == ((*ptree)->zmin+(*ptree)->zmax) )
616
{
617
if ( count++ ) {
618
prim->right = (*ptree)->left;
619
(*ptree)->left = prim;
620
count = 0;
621
} else {
622
prim->left = (*ptree)->right;
623
(*ptree)->right = prim;
624
}
625
} else if ( (prim->zmin+prim->zmax) > ((*ptree)->zmin+(*ptree)->zmax) )
626
{
627
if ( (*ptree)->left )
628
add_tree( &(*ptree)->left, prim );
629
else
630
(*ptree)->left = prim;
631
} else {
632
if ( (*ptree)->right )
633
add_tree( &(*ptree)->right, prim );
634
else
635
(*ptree)->right = prim;
636
}
637
}
638
}
639
640
//
641
// End of "$Id: context.cc,v 1.1 2003/02/06 09:37:53 jpr Exp $".
642
//
643
644