"Fossies" - the Fresh Open Source Software Archive 
Member "gfsview-snapshot-121130/gl/gfsgl2D.h" (30 Nov 2012, 26188 Bytes) of package /linux/privat/gfsview-snapshot-121130.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "gfsgl2D.h" see the
Fossies "Dox" file reference documentation.
1 /* Gerris - The GNU Flow Solver
2 * Copyright (C) 2001-2004 National Institute of Water and Atmospheric
3 * Research
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 * 02111-1307, USA.
19 */
20
21 /* GfsGlCells: Object */
22
23 static void gl_cell (FttCell * cell, GfsGl * gl)
24 {
25 FttVector p;
26 gdouble size = ftt_cell_size (cell)/2.;
27
28 ftt_cell_pos (cell, &p);
29 glBegin (GL_LINE_LOOP);
30 glVertex2d (p.x - size, p.y - size);
31 glVertex2d (p.x + size, p.y - size);
32 glVertex2d (p.x + size, p.y + size);
33 glVertex2d (p.x - size, p.y + size);
34 glEnd ();
35 gl->size++;
36 }
37
38 /* GfsGlSquares: Object */
39
40 static void gl_square (FttCell * cell, GfsGl * gl)
41 {
42 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
43 if (!GFS_HAS_DATA (cell, gls->v))
44 return;
45 FttVector p;
46 gdouble size = ftt_cell_size (cell)/1.999;
47 GtsColor c;
48
49 gl->size++;
50 ftt_cell_pos (cell, &p);
51 c = gfs_colormap_color (gls->cmap, gls->max > gls->min ?
52 (GFS_VALUE (cell, gls->v) - gls->min)/(gls->max - gls->min) :
53 0.5);
54 glColor3f (c.r, c.g, c.b);
55 glVertex2d (p.x - size, p.y - size);
56 glVertex2d (p.x + size, p.y - size);
57 glVertex2d (p.x + size, p.y + size);
58 glVertex2d (p.x - size, p.y + size);
59 }
60
61 static void gl_squares_draw (GfsGl * gl, GfsFrustum * f)
62 {
63 gl->size = 0;
64 glBegin (GL_QUADS);
65 gfs_gl_normal (gl);
66 gfs_gl_cell_traverse_visible_plane (gl, f, (FttCellTraverseFunc) gl_square, gl);
67 glEnd ();
68
69 (* GFS_GL_CLASS (GTS_OBJECT (gl)->klass->parent_class)->draw) (gl, f);
70 }
71
72 /* GfsGlSolid: Object */
73
74 #define CUT(d) (s->s[d] > 0. && s->s[d] < 1.)
75
76 static void gl_solid (FttCell * cell, GfsGl * gl)
77 {
78 if (GFS_IS_MIXED (cell)) {
79 GfsSolidVector * s = GFS_STATE (cell)->solid;
80 guint n = 0;
81 FttDirection d;
82 FttVector c, p[4];
83 gdouble h = ftt_cell_size (cell)/1.999;
84 static guint etod[] = { 3, 0, 2, 1 };
85
86 gl->size++;
87 ftt_cell_pos (cell, &c);
88 p[0].x = c.x - h; p[0].y = c.y - h;
89 p[1].x = c.x + h; p[1].y = c.y - h;
90 p[2].x = c.x + h; p[2].y = c.y + h;
91 p[3].x = c.x - h; p[3].y = c.y + h;
92
93 for (d = 0; d < FTT_NEIGHBORS; d++)
94 if (s->s[d] > 0. && s->s[d] < 1.)
95 n++;
96 switch (n) {
97 case 2: {
98 guint k, m, n1 = 0;
99 FttVector r[2];
100 gboolean ins;
101 static guint ctoc[4][2] = {{0,2},{2,1},{1,3},{3,0}};
102
103 for (m = 0; m < 4 && !CUT (etod[m]); m++);
104 ins = CUT (ctoc[m][0]) ? s->s[ctoc[m][1]] : (s->s[ctoc[m][0]] != 1.);
105 for (k = m; k < m + 4; k++) {
106 guint i = k % 4, i1 = (i + 1) % 4;
107 if (CUT (etod[i])) {
108 gdouble a = ins ? s->s[etod[i]] : 1. - s->s[etod[i]];
109 r[n1].x = (1. - a)*p[i].x + a*p[i1].x;
110 r[n1++].y = (1. - a)*p[i].y + a*p[i1].y;
111 ins = !ins;
112 if (n1 == 2) {
113 glVertex2d (r[0].x, r[0].y);
114 glVertex2d (r[1].x, r[1].y);
115 n1 = 0;
116 }
117 }
118 }
119 break;
120 }
121 case 4:
122 break;
123 default:
124 #if 0
125 g_assert_not_reached ();
126 #else
127 {
128 FttVector p;
129 ftt_cell_pos (cell, &p);
130 g_warning ("(%g,%g): %d", p.x, p.y, n);
131 }
132 #endif
133 }
134 }
135 }
136
137 static void gl_solid_draw (GfsGl * gl, GfsFrustum * f)
138 {
139 gl->size = 0;
140 glMatrixMode (GL_PROJECTION);
141 glPushMatrix ();
142 glTranslatef (0., 0., gl->p->lc);
143 glBegin (GL_LINES);
144 glNormal3d (0., 0., 1.);
145 gfs_gl_cell_traverse_visible_plane (gl, f, (FttCellTraverseFunc) gl_solid, gl);
146 glEnd ();
147 glPopMatrix ();
148 }
149
150 static void gl_solid_init (GfsGl * gl)
151 {
152 GtsColor c = { 0., 1., 0. };
153
154 gl->lc = c;
155 }
156
157 static gboolean gl_solid_relevant (GfsSimulation * sim)
158 {
159 return (sim->solids->items != NULL);
160 }
161
162 static void gl_solid_class_init (GfsGlClass * klass)
163 {
164 klass->draw = gl_solid_draw;
165 klass->relevant = gl_solid_relevant;
166 }
167
168 GfsGlClass * gfs_gl_solid_class (void)
169 {
170 static GfsGlClass * klass = NULL;
171
172 if (klass == NULL) {
173 GtsObjectClassInfo gfs_gl_solid_info = {
174 "GfsGlSolid",
175 sizeof (GfsGl),
176 sizeof (GfsGlClass),
177 (GtsObjectClassInitFunc) gl_solid_class_init,
178 (GtsObjectInitFunc) gl_solid_init,
179 (GtsArgSetFunc) NULL,
180 (GtsArgGetFunc) NULL
181 };
182 klass = gts_object_class_new (GTS_OBJECT_CLASS (gfs_gl_class ()), &gfs_gl_solid_info);
183 }
184
185 return klass;
186 }
187
188 /* GfsGlFractions: Object */
189
190 static void gl_fractions (FttCell * cell, GfsGl * gl)
191 {
192 GfsSolidVector * s = GFS_STATE (cell)->solid;
193 FttVector c;
194 gdouble h = ftt_cell_size (cell)*0.45;
195
196 gl->size++;
197 ftt_cell_pos (cell, &c);
198 glVertex2d (c.x + h, c.y - h*s->s[0]);
199 glVertex2d (c.x + h, c.y + h*s->s[0]);
200 glVertex2d (c.x - h, c.y - h*s->s[1]);
201 glVertex2d (c.x - h, c.y + h*s->s[1]);
202 glVertex2d (c.x - h*s->s[2], c.y + h);
203 glVertex2d (c.x + h*s->s[2], c.y + h);
204 glVertex2d (c.x - h*s->s[3], c.y - h);
205 glVertex2d (c.x + h*s->s[3], c.y - h);
206 }
207
208 static void gl_fractions_draw (GfsGl * gl, GfsFrustum * f)
209 {
210 gl->size = 0;
211 glMatrixMode (GL_PROJECTION);
212 glPushMatrix ();
213 glTranslatef (0., 0., gl->p->lc);
214 glBegin (GL_LINES);
215 gfs_gl_cell_traverse_visible_mixed (gl, f, (FttCellTraverseFunc) gl_fractions, gl);
216 glEnd ();
217 glPopMatrix ();
218 }
219
220 /* GfsGlBoundaries: Object */
221
222 static void gl_boundaries (FttCell * cell, GfsGl * gl)
223 {
224 if (!GFS_IS_MIXED (cell)) {
225 FttDirection d;
226 FttCellNeighbors n;
227 gdouble h = ftt_cell_size (cell)/2.;
228 FttVector p;
229
230 ftt_cell_neighbors (cell, &n);
231 ftt_cell_pos (cell, &p);
232 for (d = 0; d < FTT_NEIGHBORS; d++)
233 if (!n.c[d] || GFS_CELL_IS_BOUNDARY (n.c[d])) {
234 static FttVector dp[FTT_NEIGHBORS][2] = {
235 {{1.,-1.,0.},{1.,1.,0.}},
236 {{-1.,1.,0.},{-1.,-1,0.}},
237 {{1.,1.,0.},{-1.,1.,0.}},
238 {{-1.,-1.,0.},{1.,-1.,0.}}
239 };
240 gl->size++;
241 glVertex2d (p.x + dp[d][0].x*h, p.y + dp[d][0].y*h);
242 glVertex2d (p.x + dp[d][1].x*h, p.y + dp[d][1].y*h);
243 }
244 }
245 }
246
247 /* GfsGlLevels: Object */
248
249 /**
250 * ftt_face_gl:
251 * @face: a #FttCellFace.
252 *
253 * Creates an OpenGL representation of @face.
254 */
255 static void ftt_face_gl (const FttCellFace * face)
256 {
257 gdouble size;
258 FttVector p;
259 #if FTT_2D
260 static FttVector dp[FTT_NEIGHBORS][2] = {
261 {{1.,-1.,0.},{1.,1.,0.}},
262 {{-1.,1.,0.},{-1.,-1,0.}},
263 {{1.,1.,0.},{-1.,1.,0.}},
264 {{-1.,-1.,0.},{1.,-1.,0.}}
265 };
266 #else /* FTT_3D */
267 static FttVector dp[FTT_NEIGHBORS][4] = {
268 {{1.,-1.,1.},{1.,-1.,-1.},{1.,1.,-1.},{1.,1.,1.}},
269 {{-1.,-1.,1.},{-1.,-1.,-1.},{-1.,1.,-1.},{-1.,1.,1.}},
270 {{1.,1.,1.},{1.,1.,-1.},{-1,1.,-1.},{-1.,1.,1.}},
271 {{1.,-1.,1.},{1.,-1.,-1.},{-1,-1.,-1.},{-1.,-1.,1.}},
272 {{1.,-1.,1.},{1.,1.,1.},{-1.,1.,1.},{-1.,-1.,1.}},
273 {{1.,-1.,-1.},{1.,1.,-1.},{-1.,1.,-1.},{-1.,-1.,-1.}},
274 };
275 #endif /* FTT_3D */
276
277 g_return_if_fail (face != NULL);
278
279 size = ftt_cell_size (face->cell)/2.;
280 ftt_cell_pos (face->cell, &p);
281 #if FTT_2D
282 glVertex2d (p.x + dp[face->d][0].x*size, p.y + dp[face->d][0].y*size);
283 glVertex2d (p.x + dp[face->d][1].x*size, p.y + dp[face->d][1].y*size);
284 #else /* FTT_3D */
285 #if 0
286 fprintf (fp,
287 "OFF 4 1 4 "
288 "%g %g %g "
289 "%g %g %g "
290 "%g %g %g "
291 "%g %g %g "
292 "4 0 1 2 3\n",
293 p.x + dp[face->d][0].x*size,
294 p.y + dp[face->d][0].y*size,
295 p.z + dp[face->d][0].z*size,
296 p.x + dp[face->d][1].x*size,
297 p.y + dp[face->d][1].y*size,
298 p.z + dp[face->d][1].z*size,
299 p.x + dp[face->d][2].x*size,
300 p.y + dp[face->d][2].y*size,
301 p.z + dp[face->d][2].z*size,
302 p.x + dp[face->d][3].x*size,
303 p.y + dp[face->d][3].y*size,
304 p.z + dp[face->d][3].z*size);
305 #endif
306 #endif /* FTT_3D */
307 }
308
309 static void gl_face (FttCell * cell, GfsGlLevels * gl)
310 {
311 FttCellNeighbors n;
312 FttCellFace f;
313 gboolean drawn = FALSE;
314
315 ftt_cell_neighbors (cell, &n);
316 f.cell = cell;
317 for (f.d = 0; f.d < FTT_NEIGHBORS; f.d++) {
318 f.neighbor = n.c[f.d];
319 if (f.neighbor &&
320 floor (GFS_VALUE (cell, gl->v)) !=
321 floor (GFS_VALUE (f.neighbor, gl->v))) {
322 ftt_face_gl (&f);
323 drawn = TRUE;
324 }
325 }
326 if (drawn)
327 GFS_GL (gl)->size++;
328 }
329
330 /* GfsGlVectors: Object */
331
332 static void gl_vector (FttCell * cell, GfsGl * gl)
333 {
334 GfsGlVectors * gls = GFS_GL_VECTORS (gl);
335 if (gls->use_scalar && !GFS_HAS_DATA (cell, GFS_GL_SCALAR (gl)->v))
336 return;
337
338 FttComponent c;
339 FttVector pos, f;
340
341 gl->size++;
342 if (gls->use_scalar) {
343 GfsGlScalar * gla = GFS_GL_SCALAR (gl);
344 GtsColor c = gfs_colormap_color (gla->cmap, gla->max > gla->min ?
345 (GFS_VALUE (cell, gla->v) - gla->min)/
346 (gla->max - gla->min) :
347 0.5);
348 glColor3f (c.r, c.g, c.b);
349 }
350 gfs_cell_cm (cell, &pos);
351 for (c = 0; c < FTT_DIMENSION; c++)
352 (&f.x)[c] = GFS_VALUE (cell, gls->v[c]);
353 f.x *= gls->scale;
354 f.y *= gls->scale;
355 glVertex2d (pos.x + f.x - (f.x - f.y/2.)/5., pos.y + f.y - (f.x/2. + f.y)/5.);
356 glVertex2d (pos.x + f.x, pos.y + f.y);
357 glVertex2d (pos.x + f.x, pos.y + f.y);
358 glVertex2d (pos.x + f.x - (f.x + f.y/2.)/5., pos.y + f.y + (f.x/2. - f.y)/5.);
359 glVertex2d (pos.x, pos.y);
360 glVertex2d (pos.x + f.x, pos.y + f.y);
361 }
362
363 /* GfsGlEllipses: Object */
364
365 static void gl_ellipse (FttCell * cell, GfsGl * gl)
366 {
367 GfsGlEllipses * gls = GFS_GL_ELLIPSES (gl);
368 if (gls->use_scalar && !GFS_HAS_DATA (cell, GFS_GL_SCALAR (gl)->v))
369 return;
370 FttVector pos;
371 gdouble t;
372
373 gl->size++;
374 if (gls->use_scalar) {
375 GfsGlScalar * gla = GFS_GL_SCALAR (gl);
376 GtsColor c = gfs_colormap_color (gla->cmap, gla->max > gla->min ?
377 (GFS_VALUE (cell, gla->v) - gla->min)/
378 (gla->max - gla->min) :
379 0.5);
380 glColor3f (c.r, c.g, c.b);
381 }
382 gfs_cell_cm (cell, &pos);
383 glBegin (GL_LINE_LOOP);
384 for (t = 0.; t < 2.*M_PI; t += 2.*M_PI/20.) {
385 gdouble cost = cos (t), sint = sin (t);
386
387 glVertex2d (pos.x + gls->scale*(GFS_VALUE (cell, gls->v[0])*cost +
388 GFS_VALUE (cell, gls->v[2])*sint),
389 pos.y + gls->scale*(GFS_VALUE (cell, gls->v[1])*cost +
390 GFS_VALUE (cell, gls->v[3])*sint));
391 }
392 glEnd ();
393 }
394
395 /* GfsGlLocate: Object */
396
397 static void gl_locate (FttCell * cell, GfsGl * gl)
398 {
399 gl_cell (cell, gl);
400 }
401
402 /* GfsGlLinear: Object */
403
404 #define param(v) (gls->max > gls->min ? ((v) - gls->min)/(gls->max - gls->min) : 0.5)
405 #define color(v) (gfs_colormap_color (gls->cmap, param (v)))
406
407 static void gl_linear_color_constant (FttCell * cell, GfsGl * gl)
408 {
409 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
410 if (!GFS_HAS_DATA (cell, gls->v))
411 return;
412 FttVector p;
413 gdouble v, size = ftt_cell_size (cell)/1.999;
414 GtsColor c;
415 FttDirection d[2];
416
417 gl->size++;
418 ftt_cell_pos (cell, &p);
419 d[0] = FTT_LEFT; d[1] = FTT_BOTTOM;
420 v = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
421 c = color (v);
422 glColor3f (c.r, c.g, c.b);
423 glVertex2d (p.x - size, p.y - size);
424 d[0] = FTT_RIGHT; d[1] = FTT_BOTTOM;
425 v = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
426 c = color (v);
427 glColor3f (c.r, c.g, c.b);
428 glVertex2d (p.x + size, p.y - size);
429 d[0] = FTT_RIGHT; d[1] = FTT_TOP;
430 v = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
431 c = color (v);
432 glColor3f (c.r, c.g, c.b);
433 glVertex2d (p.x + size, p.y + size);
434 d[0] = FTT_LEFT; d[1] = FTT_TOP;
435 v = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
436 c = color (v);
437 glColor3f (c.r, c.g, c.b);
438 glVertex2d (p.x - size, p.y + size);
439 }
440
441 static void gl_linear_texture_constant (FttCell * cell, GfsGl * gl)
442 {
443 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
444 if (!GFS_HAS_DATA (cell, gls->v))
445 return;
446 FttVector p;
447 gdouble v1, v2, v3, v4, p1, p2, p3, p4;
448 gdouble size = ftt_cell_size (cell)/1.999;
449 FttDirection d[2];
450
451 gl->size++;
452 ftt_cell_pos (cell, &p);
453
454 d[0] = FTT_LEFT; d[1] = FTT_BOTTOM;
455 v1 = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
456 p1 = param (v1);
457 d[0] = FTT_RIGHT; d[1] = FTT_BOTTOM;
458 v2 = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
459 p2 = param (v2);
460 d[0] = FTT_RIGHT; d[1] = FTT_TOP;
461 v3 = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
462 p3 = param (v3);
463 d[0] = FTT_LEFT; d[1] = FTT_TOP;
464 v4 = gfs_cell_corner_value (cell, d, gls->v, gl->maxlevel);
465 p4 = param (v4);
466
467 glBegin (GL_TRIANGLE_FAN);
468 glTexCoord1d ((p1 + p2 + p3 + p4)/4.);
469 glVertex2d (p.x, p.y);
470 glTexCoord1d (p1);
471 glVertex2d (p.x - size, p.y - size);
472 glTexCoord1d (p2);
473 glVertex2d (p.x + size, p.y - size);
474 glTexCoord1d (p3);
475 glVertex2d (p.x + size, p.y + size);
476 glTexCoord1d (p4);
477 glVertex2d (p.x - size, p.y + size);
478 glTexCoord1d (p1);
479 glVertex2d (p.x - size, p.y - size);
480 glEnd ();
481 }
482
483 typedef struct {
484 gdouble p, z;
485 FttVector n;
486 } Vertex;
487
488 static void new_vertex (FttCell * cell, FttDirection * d, GfsGl * gl, Vertex * v)
489 {
490 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
491 GfsGlLinear * gll = GFS_GL_LINEAR (gl);
492 GfsInterpolator inter;
493 gfs_cell_corner_interpolator (cell, d, gl->maxlevel, FALSE, &inter);
494 gdouble val = 0.;
495 guint i;
496 v->z = 0.;
497 v->n.x = v->n.y = 0.;
498 v->n.z = 1.;
499 for (i = 0; i < inter.n; i++) {
500 val += inter.w[i]*GFS_VALUE (inter.c[i], gls->v);
501 v->z += inter.w[i]*GFS_VALUE (inter.c[i], gll->vf->v);
502 v->n.x -= inter.w[i]*GFS_VALUE (inter.c[i], gll->nx);
503 v->n.y -= inter.w[i]*GFS_VALUE (inter.c[i], gll->ny);
504 }
505 v->p = val;
506 if (gll->reversed) {
507 v->n.x = - v->n.x;
508 v->n.y = - v->n.y;
509 v->n.z = - 1.;
510 }
511 }
512
513 static void gl_linear_color (FttCell * cell, GfsGl * gl)
514 {
515 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
516 if (!GFS_HAS_DATA (cell, gls->v))
517 return;
518 gboolean use_scalar = GFS_GL_LINEAR (gl)->use_scalar != NULL;
519 FttVector p;
520 Vertex v;
521 gdouble size = ftt_cell_size (cell)/1.999;
522 GtsColor c;
523 FttDirection d[2];
524
525 gl->size++;
526 ftt_cell_pos (cell, &p);
527 d[0] = FTT_LEFT; d[1] = FTT_BOTTOM;
528 new_vertex (cell, d, gl, &v);
529 if (use_scalar) {
530 c = color (v.p);
531 glColor3f (c.r, c.g, c.b);
532 }
533 glNormal3d (v.n.x, v.n.y, v.n.z);
534 glVertex3d (p.x - size, p.y - size, v.z);
535 d[0] = FTT_RIGHT; d[1] = FTT_BOTTOM;
536 new_vertex (cell, d, gl, &v);
537 if (use_scalar) {
538 c = color (v.p);
539 glColor3f (c.r, c.g, c.b);
540 }
541 glNormal3d (v.n.x, v.n.y, v.n.z);
542 glVertex3d (p.x + size, p.y - size, v.z);
543 d[0] = FTT_RIGHT; d[1] = FTT_TOP;
544 new_vertex (cell, d, gl, &v);
545 if (use_scalar) {
546 c = color (v.p);
547 glColor3f (c.r, c.g, c.b);
548 }
549 glNormal3d (v.n.x, v.n.y, v.n.z);
550 glVertex3d (p.x + size, p.y + size, v.z);
551 d[0] = FTT_LEFT; d[1] = FTT_TOP;
552 new_vertex (cell, d, gl, &v);
553 if (use_scalar) {
554 c = color (v.p);
555 glColor3f (c.r, c.g, c.b);
556 }
557 glNormal3d (v.n.x, v.n.y, v.n.z);
558 glVertex3d (p.x - size, p.y + size, v.z);
559 }
560
561 static void gl_linear_texture (FttCell * cell, GfsGl * gl)
562 {
563 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
564 if (!GFS_HAS_DATA (cell, gls->v))
565 return;
566 FttVector p;
567 Vertex v[4];
568 gboolean use_scalar = GFS_GL_LINEAR (gl)->use_scalar != NULL;
569 gdouble size = ftt_cell_size (cell)/1.999;
570 FttDirection d[2];
571
572 gl->size++;
573 ftt_cell_pos (cell, &p);
574
575 d[0] = FTT_LEFT; d[1] = FTT_BOTTOM;
576 new_vertex (cell, d, gl, &v[0]);
577 d[0] = FTT_RIGHT; d[1] = FTT_BOTTOM;
578 new_vertex (cell, d, gl, &v[1]);
579 d[0] = FTT_RIGHT; d[1] = FTT_TOP;
580 new_vertex (cell, d, gl, &v[2]);
581 d[0] = FTT_LEFT; d[1] = FTT_TOP;
582 new_vertex (cell, d, gl, &v[3]);
583
584 glBegin (GL_TRIANGLE_FAN);
585 if (use_scalar)
586 glTexCoord1d (param ((v[0].p + v[1].p + v[2].p + v[3].p)/4.));
587 glNormal3d ((v[0].n.x + v[1].n.x + v[2].n.x + v[3].n.x)/4.,
588 (v[0].n.y + v[1].n.y + v[2].n.y + v[3].n.y)/4.,
589 (v[0].n.z + v[1].n.z + v[2].n.z + v[3].n.z)/4.);
590 glVertex3d (p.x, p.y, (v[0].z + v[1].z + v[2].z + v[3].z)/4.);
591 if (use_scalar)
592 glTexCoord1d (param (v[0].p));
593 glNormal3d (v[0].n.x, v[0].n.y, v[0].n.z);
594 glVertex3d (p.x - size, p.y - size, v[0].z);
595 if (use_scalar)
596 glTexCoord1d (param (v[1].p));
597 glNormal3d (v[1].n.x, v[1].n.y, v[1].n.z);
598 glVertex3d (p.x + size, p.y - size, v[1].z);
599 if (use_scalar)
600 glTexCoord1d (param (v[2].p));
601 glNormal3d (v[2].n.x, v[2].n.y, v[2].n.z);
602 glVertex3d (p.x + size, p.y + size, v[2].z);
603 if (use_scalar)
604 glTexCoord1d (param (v[3].p));
605 glNormal3d (v[3].n.x, v[3].n.y, v[3].n.z);
606 glVertex3d (p.x - size, p.y + size, v[3].z);
607 if (use_scalar)
608 glTexCoord1d (param (v[0].p));
609 glNormal3d (v[0].n.x, v[0].n.y, v[0].n.z);
610 glVertex3d (p.x - size, p.y - size, v[0].z);
611 glEnd ();
612 }
613
614 static void gl_linear_draw (GfsGl * gl, GfsFrustum * f)
615 {
616 gboolean constant = (gfs_function_get_constant_value (GFS_GL_LINEAR (gl)->vf->f) == 0.);
617 gl->size = 0;
618 glShadeModel (GL_SMOOTH);
619 if (constant)
620 gfs_gl_normal (gl);
621 if (gfs_gl_vector_format (gl)) {
622 glBegin (GL_QUADS);
623 gfs_gl_cell_traverse_visible_plane (gl, f, (FttCellTraverseFunc)
624 (constant ?
625 gl_linear_color_constant :
626 gl_linear_color), gl);
627 glEnd ();
628 }
629 else {
630 if (GFS_GL_LINEAR (gl)->use_scalar) {
631 glEnable (GL_TEXTURE_1D);
632 gfs_colormap_texture (GFS_GL_SCALAR (gl)->cmap);
633 glColor3f (1., 1., 1.);
634 gfs_gl_cell_traverse_visible_plane (gl, f, (FttCellTraverseFunc)
635 (constant ?
636 gl_linear_texture_constant :
637 gl_linear_texture), gl);
638 glDisable (GL_TEXTURE_1D);
639 }
640 else
641 gfs_gl_cell_traverse_visible_plane (gl, f, (FttCellTraverseFunc)
642 (constant ?
643 gl_linear_texture_constant :
644 gl_linear_texture), gl);
645 }
646
647 if (GFS_GL_LINEAR (gl)->use_scalar)
648 (* GFS_GL_CLASS (GTS_OBJECT (gl)->klass->parent_class)->draw) (gl, f);
649 }
650
651 /* GfsGlIsoline: Object */
652
653 typedef struct {
654 FttVector p;
655 gdouble v;
656 } VertexIsoline;
657
658 static gdouble inter (VertexIsoline * v1, VertexIsoline * v2, gdouble v)
659 {
660 if ((v1->v > v && v2->v <= v) || (v1->v <= v && v2->v > v)) {
661 gdouble a = (v - v1->v)/(v2->v - v1->v);
662 glVertex3d (v1->p.x + a*(v2->p.x - v1->p.x),
663 v1->p.y + a*(v2->p.y - v1->p.y),
664 v1->p.z + a*(v2->p.z - v1->p.z));
665 #if DEBUG
666 fprintf (stderr, " %g %g %g\n",
667 v1->p.x + a*(v2->p.x - v1->p.x),
668 v1->p.y + a*(v2->p.y - v1->p.y),
669 v1->p.z + a*(v2->p.z - v1->p.z));
670 #endif
671 return a;
672 }
673 return -1;
674 }
675
676 static void vertex_isoline (FttCell * cell, FttDirection * d, GfsGl * gl, VertexIsoline * v)
677 {
678 ftt_corner_pos (cell, d, &v->p);
679 if ((v->p.z = gfs_function_get_constant_value (GFS_GL_LINEAR (gl)->vf->f)) != 0.) {
680 GfsInterpolator inter;
681 guint i;
682 gfs_cell_corner_interpolator (cell, d, gl->maxlevel, FALSE, &inter);
683 v->v = v->p.z = 0.;
684 for (i = 0; i < inter.n; i++) {
685 v->v += inter.w[i]*GFS_VALUE (inter.c[i], GFS_GL_SCALAR (gl)->v);
686 v->p.z += inter.w[i]*GFS_VALUE (inter.c[i], GFS_GL_LINEAR (gl)->vf->v);
687 }
688 }
689 else
690 v->v = gfs_cell_corner_value (cell, d, GFS_GL_SCALAR (gl)->v, gl->maxlevel);
691 }
692
693 /* the directions corresponding to the corners */
694 static FttDirection neighbor[4] = { FTT_BOTTOM, FTT_RIGHT, FTT_TOP, FTT_LEFT };
695 /* the corners corresponding to the directions */
696 static FttDirection icorner[4] = { 1, 3, 2, 0 };
697
698 static void set_used (FttCell * cell, gint i, GfsGl * gl)
699 {
700 int v = GFS_VALUE (cell, GFS_GL_ISOLINE (gl)->used);
701 v |= (1 << (i + 1));
702 GFS_VALUE (cell, GFS_GL_ISOLINE (gl)->used) = v;
703 }
704
705 static gboolean get_used (FttCell * cell, gint i, GfsGl * gl)
706 {
707 return (((int) GFS_VALUE (cell, GFS_GL_ISOLINE (gl)->used)) & (1 << (i + 1))) != 0;
708 }
709
710 static gboolean get_visible (FttCell * cell, GfsGl * gl)
711 {
712 return GFS_VALUE (cell, GFS_GL_ISOLINE (gl)->used) != 0.;
713 }
714
715 static void follow_isoline (FttCell * cell, gint start, GfsGl * gl, gdouble val)
716 {
717 while (cell &&
718 !GFS_CELL_IS_BOUNDARY (cell) &&
719 get_visible (cell, gl) &&
720 GFS_HAS_DATA (cell, GFS_GL_SCALAR (gl)->v)) {
721 set_used (cell, start, gl);
722
723 gint i1 = (start + 1) % 4;
724 VertexIsoline v1, v2;
725 vertex_isoline (cell, corner[i1], gl, &v1);
726 FttCell * next = NULL;
727 while (i1 != start && !get_used (cell, i1, gl)) {
728 gint i2 = (i1 + 1) % 4;
729 vertex_isoline (cell, corner[i2], gl, &v2);
730 gdouble a;
731 if ((a = inter (&v1, &v2, val)) >= 0.) {
732 gl->size++;
733 set_used (cell, i1, gl);
734 FttDirection d = neighbor[i1];
735 FttCell * n = ftt_cell_neighbor (cell, d);
736 if (n) {
737 if (!FTT_CELL_IS_LEAF (n) && !get_visible (n, gl)) {
738 FttCellChildren child;
739 ftt_cell_children_direction (n, FTT_OPPOSITE_DIRECTION (d), &child);
740 gboolean visible0 = (child.c[0] && get_visible (child.c[0], gl));
741 gboolean visible1 = (child.c[1] && get_visible (child.c[1], gl));
742 if (visible0) {
743 if (visible1) {
744 if (d == FTT_LEFT || d == FTT_BOTTOM)
745 n = child.c[a > 0.5];
746 else
747 n = child.c[a < 0.5];
748 }
749 else
750 n = child.c[0];
751 }
752 else if (visible1)
753 n = child.c[1];
754 else /* invisible children */
755 n = NULL;
756 }
757 }
758 next = n;
759 start = (i1 + 2) % 4;
760 break;
761 }
762 i1 = i2;
763 v1 = v2;
764 }
765 cell = next;
766 }
767 }
768
769 static void gl_isoline (FttCell * cell, GfsGl * gl)
770 {
771 if (!GFS_HAS_DATA (cell, GFS_GL_SCALAR (gl)->v))
772 return;
773 gdouble val = GFS_GL_ISOLINE (gl)->val;
774
775 gint i1 = 0;
776 VertexIsoline v1, v2;
777 vertex_isoline (cell, corner[i1], gl, &v1);
778 do {
779 gint i2 = (i1 + 1) % 4;
780 vertex_isoline (cell, corner[i2], gl, &v2);
781 if (!get_used (cell, i1, gl) && v1.v > val && v2.v <= val) {
782 #if DEBUG
783 fprintf (stderr, "# glBegin (GL_LINE_LOOP) %g\n", val);
784 glColor3f (rand()/(float)RAND_MAX, rand()/(float)RAND_MAX, rand()/(float)RAND_MAX);
785 #endif
786 #if 0 /* fixme: this should work but the openGL drivers seem to be buggy... */
787 FttCell * n = ftt_cell_neighbor (cell, neighbor[i1]);
788 g_assert (n);
789 GFS_VALUE (n, GFS_GL_ISOLINE (gl)->used[(i1 + 2) % 4]) = TRUE;
790 glBegin (GL_LINE_LOOP);
791 #else
792 glBegin (GL_LINE_STRIP); /* ... and this seems to work OK */
793 #endif
794 inter (&v1, &v2, val);
795 follow_isoline (cell, i1, gl, val);
796 glEnd ();
797 #if DEBUG
798 fprintf (stderr, "# glEnd ()\n\n");
799 #endif
800 }
801 i1 = i2;
802 v1 = v2;
803 } while (i1 != 0);
804 }
805
806 static gboolean neighbor_is_boundary (FttCell * cell, GfsGl * gl, FttDirection d)
807 {
808 if (!cell || GFS_CELL_IS_BOUNDARY (cell))
809 return TRUE;
810 gdouble r = ftt_cell_size (cell)*GFS_DIAGONAL;
811 FttVector p;
812 ftt_cell_pos (cell, &p);
813 return (gfs_sphere_in_frustum (&p, r, GFS_GL_ISOLINE (gl)->f) == GTS_OUT);
814 }
815
816 static void gl_boundary_isoline (FttCell * cell, GfsGl * gl)
817 {
818 if (!GFS_HAS_DATA (cell, GFS_GL_SCALAR (gl)->v))
819 return;
820 gdouble val = GFS_GL_ISOLINE (gl)->val;
821
822 FttCellNeighbors n;
823 ftt_cell_neighbors (cell, &n);
824 FttDirection d;
825 for (d = 0; d < FTT_NEIGHBORS; d++) {
826 gint i1 = icorner[d];
827 if (!get_used (cell, i1, gl) && neighbor_is_boundary (n.c[d], gl, d)) {
828 VertexIsoline v1, v2;
829 vertex_isoline (cell, corner[i1], gl, &v1);
830 gint i2 = (i1 + 1) % 4;
831 vertex_isoline (cell, corner[i2], gl, &v2);
832 if (v1.v > val && v2.v <= val) {
833 #if DEBUG
834 fprintf (stderr, "# glBegin (GL_LINE_STRIP) %g\n", val);
835 glColor3f (rand()/(float)RAND_MAX, rand()/(float)RAND_MAX, rand()/(float)RAND_MAX);
836 #endif
837 glBegin (GL_LINE_STRIP);
838 inter (&v1, &v2, val);
839 follow_isoline (cell, i1, gl, val);
840 glEnd ();
841 #if DEBUG
842 fprintf (stderr, "# glEnd ()\n\n");
843 #endif
844 }
845 }
846 }
847 }
848
849 static void set_visible (FttCell * cell, GfsVariable * v)
850 {
851 GFS_VALUE (cell, v) = 1.;
852 }
853
854 static void gl_isoline_draw (GfsGl * gl, GfsFrustum * f)
855 {
856 GfsGlIsoline * gli = GFS_GL_ISOLINE (gl);
857 gl_isoline_update_levels (gl);
858
859 gli->used = gfs_temporary_variable (GFS_DOMAIN (gl->sim));
860 gfs_domain_cell_traverse (GFS_DOMAIN (gl->sim), FTT_PRE_ORDER, FTT_TRAVERSE_ALL, -1,
861 (FttCellTraverseFunc) gfs_cell_reset, gli->used);
862 gli->f = f;
863
864 gl->size = 0;
865 glMatrixMode (GL_PROJECTION);
866 glPushMatrix ();
867 glTranslatef (0., 0., gl->p->lc);
868 gfs_gl_normal (gl);
869 int i;
870 for (i = 0; i < gli->levels->len; i++) {
871 gli->val = g_array_index (gli->levels, gdouble, i);
872 gfs_gl_cell_traverse_visible_iso (gl, f, gli->min, gli->max, gli->val,
873 (FttCellTraverseFunc) set_visible, gli->used);
874 gfs_gl_cell_traverse_visible_iso (gl, f, gli->min, gli->max, gli->val,
875 (FttCellTraverseFunc) gl_boundary_isoline, gl);
876 gfs_gl_cell_traverse_visible_iso (gl, f, gli->min, gli->max, gli->val,
877 (FttCellTraverseFunc) gl_isoline, gl);
878 gfs_gl_cell_traverse_visible_iso (gl, f, gli->min, gli->max, gli->val,
879 (FttCellTraverseFunc) gfs_cell_reset, gli->used);
880 }
881 glPopMatrix ();
882
883 gts_object_destroy (GTS_OBJECT (gli->used));
884 }
885
886 /* GfsGlVOF: Object */
887
888 static void gl_vof (FttCell * cell, GfsGl * gl)
889 {
890 FttVector p[2], m;
891 if (gfs_vof_facet (cell, GFS_VARIABLE_TRACER_VOF (GFS_GL_VOF (gl)->vf->v), p, &m) == 2) {
892 if (GFS_GL_VOF (gl)->use_scalar) {
893 GfsGlScalar * gls = GFS_GL_SCALAR (gl);
894 GtsColor c = gfs_colormap_color (gls->cmap, gls->max > gls->min ?
895 (GFS_VALUE (cell, gls->v) - gls->min)/
896 (gls->max - gls->min) :
897 0.5);
898 glColor3f (c.r, c.g, c.b);
899 }
900 glVertex2d (p[0].x, p[0].y);
901 glVertex2d (p[1].x, p[1].y);
902 gl->size++;
903 }
904 }
905
906 static gboolean is_vof (FttCell * cell, gpointer data)
907 {
908 gdouble f = GFS_VALUE (cell, GFS_GL_VOF (data)->vf->v);
909
910 return !GFS_IS_FULL (f);
911 }
912
913 static void gl_vof_draw (GfsGl * gl, GfsFrustum * f)
914 {
915 if (GFS_IS_VARIABLE_TRACER_VOF (GFS_GL_VOF (gl)->vf->v)) {
916 gl->size = 0;
917 glMatrixMode (GL_PROJECTION);
918 glPushMatrix ();
919 glTranslatef (0., 0., gl->p->lc);
920 glBegin (GL_LINES);
921 gfs_gl_cell_traverse_visible_condition (gl, f, is_vof, gl, (FttCellTraverseFunc) gl_vof, gl);
922 glEnd ();
923 glPopMatrix ();
924 }
925 }
926
927 static void gl_vof_cut (GfsGl * gl, FttCell * cell, GfsGl2D * plane)
928 {
929 }
930
931 /* GfsGlStreamline: Object */
932
933 static void draw_point (GtsPoint * p)
934 {
935 glVertex3d (p->x, p->y, p->z);
936 }
937
938 static void gl_streamline_draw (GfsGlStreamline * s,
939 GfsGlStreamlines * gls)
940 {
941 glBegin (GL_LINE_STRIP);
942 g_list_foreach (s->l, (GFunc) draw_point, NULL);
943 glEnd ();
944 }