1 /*
2 * MODULE NAME: ex_raw.c
3 *
4 * FUNCTION:
5 * This module contains code that draws extrusions with square
6 * ("raw join style") end styles. It also inserts colors and normals
7 * where necessary, if appropriate.
8 *
9 * HISTORY:
10 * written by Linas Vepstas August/September 1991
11 * split into multiple compile units, Linas, October 1991
12 * added normal vectors Linas, October 1991
13 * "code complete" (that is, I'm done), Linas Vepstas, October 1991
14 * work around OpenGL's lack of support for concave polys, June 1994
15 *
16 * Copyright (C) 1991,1994,2003 Linas Vepstas <linas@linas.org>
17 */
18
19
20 #include <stdlib.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <string.h> /* for the memcpy() subroutine */
24 #include <stdio.h> /* to get stderr defined */
25
26 #include "gle.h"
27
28 #include "port.h"
29 #include "vvector.h"
30 #include "tube_gc.h"
31 #include "extrude.h"
32 #include "intersect.h"
33 #include "segment.h"
34
35 /* ============================================================ */
36 #ifndef COLOR_SIGNATURE
37 /*
38 * The following routine is, in principle, very simple:
39 * all that it does is normalize the up vector, and makes
40 * sure that it is perpendicular to the initial polyline segment.
41 *
42 * In fact, this routine gets awfully complicated because:
43 * a) the first few segements of the polyline might be degenerate,
44 * b) up vecotr may be parallel to first few segments of polyline,
45 * c) etc.
46 *
47 */
48
up_sanity_check(gleDouble up[3],int npoints,gleDouble point_array[][3])49 void up_sanity_check (gleDouble up[3], /* up vector for contour */
50 int npoints, /* numpoints in poly-line */
51 gleDouble point_array[][3]) /* polyline */
52 {
53 int i;
54 double len;
55 double diff[3];
56
57 /* now, right off the bat, we should make sure that the up vector
58 * is in fact perpendicular to the polyline direction */
59 VEC_DIFF (diff, point_array[1], point_array[0]);
60 VEC_LENGTH (len, diff);
61 if (len == 0.0) {
62 /* This error message should go through an "official" error interface */
63 #ifndef WIN32
64 /* Win32 GUI programs do not have a valid error stream; and so
65 * although they compile, they will crash when run. */
66 fprintf (stderr, "Extrusion: Warning: initial segment zero length \n");
67 #endif /* WIN32 */
68
69 /* loop till we find something that ain't of zero length */
70 for (i=1; i<npoints-2; i++) {
71 VEC_DIFF (diff, point_array[i+1], point_array[i]);
72 VEC_LENGTH (len, diff);
73 if (len != 0.0) break;
74 }
75 }
76
77 /* normalize diff to be of unit length */
78 len = 1.0 / len;
79 VEC_SCALE (diff, len, diff);
80
81 /* we want to take only perpendicular component of up w.r.t. the
82 * initial segment */
83 VEC_PERP (up, up, diff);
84
85 VEC_LENGTH (len, up);
86 if (len == 0.0) {
87 /* This error message should go through an "official" error interface */
88 #ifndef WIN32
89 /* Win32 GUI programs do not have a valid error stream; and so
90 * although they compile, they will crash when run. */
91 fprintf (stderr, "Extrusion: Warning: "
92 "contour up vector parallel to tubing direction \n");
93 #endif /* WIN32 */
94
95 /* do like the error message says ... */
96 VEC_COPY (up, diff);
97 }
98
99 }
100
101 /* ============================================================ */
102 /*
103 * This routine does what it says: It draws the end-caps for the
104 * "raw" join style.
105 */
106
draw_raw_style_end_cap(int ncp,gleDouble contour[][2],gleDouble zval,int frontwards)107 void draw_raw_style_end_cap (int ncp, /* number of contour points */
108 gleDouble contour[][2], /* 2D contour */
109 gleDouble zval, /* where to draw cap */
110 int frontwards) /* front or back cap */
111 {
112 int j;
113
114 #ifdef GL_32
115 gleDouble point[3];
116 #endif /* GL_32 */
117
118 #ifdef OPENGL_10
119 GLUtriangulatorObj *tobj;
120 double *pts;
121 #endif /* OPENGL_10 */
122
123
124 #ifdef GL_32
125 /* Old-style gl handles concave polygons no problem, so the code is
126 * simple. New-style gl is a lot more tricky. */
127 point [2] = zval;
128 BGNPOLYGON ();
129 /* draw the loop counter clockwise for the front cap */
130 if (frontwards) {
131 for (j=0; j<ncp; j++) {
132 point [0] = contour[j][0];
133 point [1] = contour[j][1];
134 V3F (point, j, FRONT_CAP);
135 }
136
137 } else {
138 /* the sense of the loop is reversed for backfacing culling */
139 for (j=ncp-1; j>-1; j--) {
140 point [0] = contour[j][0];
141 point [1] = contour[j][1];
142 V3F (point, j, BACK_CAP);
143 }
144 }
145 ENDPOLYGON ();
146 #endif /* GL_32 */
147
148 #ifdef OPENGL_10
149 /* malloc the @#$%^&* array that OpenGL wants ! */
150 pts = (double *) malloc (3*ncp*sizeof(double));
151 tobj = gluNewTess ();
152 gluTessCallback (tobj, GLU_BEGIN, glBegin);
153 gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
154 gluTessCallback (tobj, GLU_END, glEnd);
155 gluBeginPolygon (tobj);
156
157 /* draw the loop counter clockwise for the front cap */
158 if (frontwards) {
159 for (j=0; j<ncp; j++) {
160 pts [3*j] = contour[j][0];
161 pts [3*j+1] = contour[j][1];
162 pts [3*j+2] = zval;
163 gluTessVertex (tobj, &pts[3*j], &pts[3*j]);
164 }
165
166 } else {
167 /* the sense of the loop is reversed for backfacing culling */
168 for (j=ncp-1; j>-1; j--) {
169 pts [3*j] = contour[j][0];
170 pts [3*j+1] = contour[j][1];
171 pts [3*j+2] = zval;
172 gluTessVertex (tobj, &pts[3*j], &pts[3*j]);
173 }
174 }
175
176 gluEndPolygon (tobj);
177 free (pts);
178 gluDeleteTess (tobj);
179 #endif /* OPENGL_10 */
180 }
181
182 #endif /* COLOR_SIGNATURE */
183 /* ============================================================ */
184 /* This routine does what it says: It draws a counter-clockwise cap
185 * from a 3D contour loop list
186 */
187
188 static void
draw_front_contour_cap(int ncp,gleDouble contour[][3])189 draw_front_contour_cap (int ncp, /* number of contour points */
190 gleDouble contour[][3]) /* 3D contour */
191 {
192 int j;
193
194 #ifdef OPENGL_10
195 GLUtriangulatorObj *tobj;
196 #endif /* OPENGL_10 */
197
198 #ifdef GL_32
199 /* old-style gl handles concave polygons no problem, so the code is
200 * simple. New-style gl is a lot more tricky. */
201 /* draw the end cap */
202 BGNPOLYGON ();
203
204 for (j=0; j<ncp; j++) {
205 V3F (contour[j], j, FRONT_CAP);
206 }
207 ENDPOLYGON ();
208 #endif /* GL_32 */
209
210 #ifdef OPENGL_10
211 tobj = gluNewTess ();
212 gluTessCallback (tobj, GLU_BEGIN, glBegin);
213 gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
214 gluTessCallback (tobj, GLU_END, glEnd);
215 gluBeginPolygon (tobj);
216
217 for (j=0; j<ncp; j++) {
218 gluTessVertex (tobj, contour[j], contour[j]);
219 }
220 gluEndPolygon (tobj);
221 gluDeleteTess (tobj);
222 #endif /* OPENGL_10 */
223 }
224
225
226 /* ============================================================ */
227 /* This routine does what it says: It draws a clockwise cap
228 * from a 3D contour loop list
229 */
230
231 static void
draw_back_contour_cap(int ncp,gleDouble contour[][3])232 draw_back_contour_cap (int ncp, /* number of contour points */
233 gleDouble contour[][3]) /* 3D contour */
234 {
235 int j;
236
237 #ifdef OPENGL_10
238 GLUtriangulatorObj *tobj;
239 #endif /* OPENGL_10 */
240
241 #ifdef GL_32
242 /* old-style gl handles concave polygons no problem, so the code is
243 * simple. New-style gl is a lot more tricky. */
244
245 /* draw the end cap */
246 /* draw the loop clockwise for the back cap */
247 /* the sense of the loop is reversed for backfacing culling */
248 BGNPOLYGON ();
249
250 for (j=ncp-1; j>-1; j--) {
251 V3F (contour[j], j, BACK_CAP);
252 }
253 ENDPOLYGON ();
254 #endif /* GL_32 */
255
256 #ifdef OPENGL_10
257 tobj = gluNewTess ();
258 gluTessCallback (tobj, GLU_BEGIN, glBegin);
259 gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
260 gluTessCallback (tobj, GLU_END, glEnd);
261 gluBeginPolygon (tobj);
262
263 /* draw the end cap */
264 /* draw the loop clockwise for the back cap */
265 /* the sense of the loop is reversed for backfacing culling */
266 for (j=ncp-1; j>-1; j--) {
267 gluTessVertex (tobj, contour[j], contour[j]);
268 }
269 gluEndPolygon (tobj);
270 gluDeleteTess (tobj);
271 #endif /* OPENGL_10 */
272 }
273
274 /* ============================================================ */
275 /* This routine draws a segment of raw-join-style tubing.
276 * Essentially, we assume that the proper transformations have already
277 * been performed to properly orient the tube segment -- our only task
278 * left is to render */
279 /* PLAIN - NO COLOR, NO NORMAL */
280
281 static void
draw_raw_segment_plain(int ncp,gleDouble contour[][2],int inext,gleDouble len)282 draw_raw_segment_plain (int ncp, /* number of contour points */
283 gleDouble contour[][2], /* 2D contour */
284 int inext,
285 gleDouble len)
286
287 {
288 int j;
289 double point[3];
290
291 /* draw the tube segment */
292 BGNTMESH (inext, len);
293 for (j=0; j<ncp; j++) {
294 point [0] = contour[j][0];
295 point [1] = contour[j][1];
296 point [2] = 0.0;
297 V3F (point, j, FRONT);
298
299 point [2] = - len;
300 V3F (point, j, BACK);
301 }
302
303 if (__TUBE_CLOSE_CONTOUR) {
304 /* connect back up to first point of contour */
305 point [0] = contour[0][0];
306 point [1] = contour[0][1];
307 point [2] = 0.0;
308 V3F (point, 0, FRONT);
309
310 point [2] = - len;
311 V3F (point, 0, BACK);
312 }
313
314 ENDTMESH ();
315
316 /* draw the endcaps, if the join style calls for it */
317 if (__TUBE_DRAW_CAP) {
318
319 /* draw the front cap */
320 draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
321
322 /* draw the back cap */
323 draw_raw_style_end_cap (ncp, contour, -len, FALSE);
324 }
325 }
326
327 /* ============================================================ */
328 /* This routine draws a segment of raw-join-style tubing.
329 * Essentially, we assume that the proper transformations have already
330 * been performed to properly orient the tube segment -- our only task
331 * left is to render */
332 /* COLOR -- DRAW ONLY COLOR */
333
334 static void
draw_raw_segment_color(int ncp,gleDouble contour[][2],gleColor color_array[],int inext,gleDouble len)335 draw_raw_segment_color (int ncp, /* number of contour points */
336 gleDouble contour[][2], /* 2D contour */
337 gleColor color_array[], /* color of polyline */
338 int inext,
339 gleDouble len)
340
341 {
342 int j;
343 double point[3];
344
345 /* draw the tube segment */
346 BGNTMESH (inext, len);
347 for (j=0; j<ncp; j++) {
348 point [0] = contour[j][0];
349 point [1] = contour[j][1];
350 point [2] = 0.0;
351 C3F (color_array[inext-1]);
352 V3F (point, j, FRONT);
353
354 point [2] = - len;
355 C3F (color_array[inext]);
356 V3F (point, j, BACK);
357 }
358
359 if (__TUBE_CLOSE_CONTOUR) {
360 /* connect back up to first point of contour */
361 point [0] = contour[0][0];
362 point [1] = contour[0][1];
363 point [2] = 0.0;
364
365 C3F (color_array[inext-1]);
366 V3F (point, 0, FRONT);
367
368 point [2] = - len;
369 C3F (color_array[inext]);
370 V3F (point, 0, BACK);
371 }
372
373 ENDTMESH ();
374
375 /* draw the endcaps, if the join style calls for it */
376 if (__TUBE_DRAW_CAP) {
377
378 /* draw the front cap */
379 C3F (color_array[inext-1]);
380 draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
381
382 /* draw the back cap */
383 C3F (color_array[inext]);
384 draw_raw_style_end_cap (ncp, contour, -len, FALSE);
385 }
386
387 }
388
389 /* ============================================================ */
390 /* This routine draws a segment of raw-join-style tubing.
391 * Essentially, we assume that the proper transformations have already
392 * been performed to properly orient the tube segment -- our only task
393 * left is to render */
394 /* EDGE_N -- DRAW ONLY EDGE NORMALS */
395
396 static void
draw_raw_segment_edge_n(int ncp,gleDouble contour[][2],gleDouble cont_normal[][2],int inext,gleDouble len)397 draw_raw_segment_edge_n (int ncp, /* number of contour points */
398 gleDouble contour[][2], /* 2D contour */
399 gleDouble cont_normal[][2],/* 2D normal vecs */
400 int inext,
401 gleDouble len)
402
403 {
404 int j;
405 double point[3];
406 double norm[3];
407
408 /* draw the tube segment */
409 norm [2] = 0.0;
410 BGNTMESH (inext, len);
411 for (j=0; j<ncp; j++) {
412 norm [0] = cont_normal[j][0];
413 norm [1] = cont_normal[j][1];
414 N3F (norm);
415
416 point [0] = contour[j][0];
417 point [1] = contour[j][1];
418 point [2] = 0.0;
419 V3F (point, j, FRONT);
420
421 point [2] = - len;
422 V3F (point, j, BACK);
423 }
424
425 if (__TUBE_CLOSE_CONTOUR) {
426 /* connect back up to first point of contour */
427 norm [0] = cont_normal[0][0];
428 norm [1] = cont_normal[0][1];
429 norm [2] = 0.0;
430 N3F (norm);
431
432 point [0] = contour[0][0];
433 point [1] = contour[0][1];
434 point [2] = 0.0;
435 V3F (point, 0, FRONT);
436
437 point [2] = - len;
438 V3F (point, 0, BACK);
439 }
440
441 ENDTMESH ();
442
443 /* draw the endcaps, if the join style calls for it */
444 if (__TUBE_DRAW_CAP) {
445
446 /* draw the front cap */
447 norm [0] = norm [1] = 0.0;
448 norm [2] = 1.0;
449 N3F (norm);
450 draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
451
452 /* draw the back cap */
453 norm [2] = -1.0;
454 N3F (norm);
455 draw_raw_style_end_cap (ncp, contour, -len, FALSE);
456 }
457
458 }
459
460 /* ============================================================ */
461 /* This routine draws a segment of raw-join-style tubing.
462 * Essentially, we assume that the proper transformations have already
463 * been performed to properly orient the tube segment -- our only task
464 * left is to render */
465 /* C_AND_EDGE_N -- DRAW EDGE NORMALS AND COLORS */
466
467 static void
draw_raw_segment_c_and_edge_n(int ncp,gleDouble contour[][2],gleColor color_array[],gleDouble cont_normal[][2],int inext,gleDouble len)468 draw_raw_segment_c_and_edge_n (int ncp, /* number of contour points */
469 gleDouble contour[][2], /* 2D contour */
470 gleColor color_array[], /* color of polyline */
471 gleDouble cont_normal[][2],/* 2D normal vecs */
472 int inext,
473 gleDouble len)
474
475 {
476 int j;
477 double point[3];
478 double norm[3];
479
480 /* draw the tube segment */
481 norm [2] = 0.0;
482 BGNTMESH (inext, len);
483 for (j=0; j<ncp; j++) {
484 C3F (color_array[inext-1]);
485
486 norm [0] = cont_normal[j][0];
487 norm [1] = cont_normal[j][1];
488 N3F (norm);
489
490 point [0] = contour[j][0];
491 point [1] = contour[j][1];
492 point [2] = 0.0;
493 V3F (point, j, FRONT);
494
495 C3F (color_array[inext]);
496 N3F (norm);
497
498 point [2] = - len;
499 V3F (point, j, BACK);
500 }
501
502 if (__TUBE_CLOSE_CONTOUR) {
503 /* connect back up to first point of contour */
504 C3F (color_array[inext-1]);
505
506 norm [0] = cont_normal[0][0];
507 norm [1] = cont_normal[0][1];
508 N3F (norm);
509
510 point [0] = contour[0][0];
511 point [1] = contour[0][1];
512 point [2] = 0.0;
513 V3F (point, 0, FRONT);
514
515
516 C3F (color_array[inext]);
517 norm [0] = cont_normal[0][0];
518 norm [1] = cont_normal[0][1];
519 N3F (norm);
520
521 point [2] = - len;
522 V3F (point, 0, BACK);
523 }
524
525 ENDTMESH ();
526
527 /* draw the endcaps, if the join style calls for it */
528 if (__TUBE_DRAW_CAP) {
529
530 /* draw the front cap */
531 C3F (color_array[inext-1]);
532 norm [0] = norm [1] = 0.0;
533 norm [2] = 1.0;
534 N3F (norm);
535 draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
536
537 /* draw the back cap */
538 C3F (color_array[inext]);
539 norm [2] = -1.0;
540 N3F (norm);
541 draw_raw_style_end_cap (ncp, contour, -len, FALSE);
542 }
543
544 }
545
546 /* ============================================================ */
547 /* This routine draws a segment of raw-join-style tubing.
548 * Essentially, we assume that the proper transformations have already
549 * been performed to properly orient the tube segment -- our only task
550 * left is to render */
551 /* FACET_N -- DRAW ONLY FACET NORMALS */
552
553 static void
draw_raw_segment_facet_n(int ncp,gleDouble contour[][2],gleDouble cont_normal[][2],int inext,gleDouble len)554 draw_raw_segment_facet_n (int ncp, /* number of contour points */
555 gleDouble contour[][2], /* 2D contour */
556 gleDouble cont_normal[][2],/* 2D normal vecs */
557 int inext,
558 gleDouble len)
559
560 {
561 int j;
562 double point[3];
563 double norm[3];
564
565 /* draw the tube segment */
566 norm [2] = 0.0;
567 BGNTMESH (inext, len);
568 for (j=0; j<ncp-1; j++) {
569 /* facet normals require one normal per four vertices */
570 norm [0] = cont_normal[j][0];
571 norm [1] = cont_normal[j][1];
572 N3F (norm);
573
574 point [0] = contour[j][0];
575 point [1] = contour[j][1];
576 point [2] = 0.0;
577 V3F (point, j, FRONT);
578
579 point [2] = - len;
580 V3F (point, j, BACK);
581
582 point [0] = contour[j+1][0];
583 point [1] = contour[j+1][1];
584 point [2] = 0.0;
585 V3F (point, j+1, FRONT);
586
587 point [2] = - len;
588 V3F (point, j+1, BACK);
589 }
590
591 if (__TUBE_CLOSE_CONTOUR) {
592 /* connect back up to first point of contour */
593 norm [0] = cont_normal[ncp-1][0];
594 norm [1] = cont_normal[ncp-1][1];
595 N3F (norm);
596
597 point [0] = contour[ncp-1][0];
598 point [1] = contour[ncp-1][1];
599 point [2] = 0.0;
600 V3F (point, ncp-1, FRONT);
601
602 point [2] = - len;
603 V3F (point, ncp-1, BACK);
604
605 point [0] = contour[0][0];
606 point [1] = contour[0][1];
607 point [2] = 0.0;
608 V3F (point, 0, FRONT);
609
610 point [2] = - len;
611 V3F (point, 0, BACK);
612 }
613
614 ENDTMESH ();
615
616 /* draw the endcaps, if the join style calls for it */
617 if (__TUBE_DRAW_CAP) {
618
619 /* draw the front cap */
620 norm [0] = norm [1] = 0.0;
621 norm [2] = 1.0;
622 N3F (norm);
623 draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
624
625 /* draw the back cap */
626 norm [2] = -1.0;
627 N3F (norm);
628 draw_raw_style_end_cap (ncp, contour, -len, FALSE);
629 }
630
631 }
632
633 /* ============================================================ */
634 /* This routine draws a segment of raw-join-style tubing.
635 * Essentially, we assume that the proper transformations have already
636 * been performed to properly orient the tube segment -- our only task
637 * left is to render */
638 /* C_AND_FACET_N -- DRAW FACET NORMALS AND COLORS */
639
640 static void
draw_raw_segment_c_and_facet_n(int ncp,gleDouble contour[][2],gleColor color_array[],gleDouble cont_normal[][2],int inext,gleDouble len)641 draw_raw_segment_c_and_facet_n (int ncp, /* number of contour points */
642 gleDouble contour[][2], /* 2D contour */
643 gleColor color_array[], /* color of polyline */
644 gleDouble cont_normal[][2],/* 2D normal vecs */
645 int inext,
646 gleDouble len)
647
648 {
649 int j;
650 double point[3];
651 double norm[3];
652
653 /* draw the tube segment */
654 norm [2] = 0.0;
655 BGNTMESH (inext, len);
656 for (j=0; j<ncp-1; j++) {
657 /* facet normals require one normal per four vertices;
658 * However, we have to respecify normal each time at each vertex
659 * so that the lighting equation gets triggered. (V3F does NOT
660 * automatically trigger the lighting equations -- it only
661 * triggers when there is a local light) */
662
663 C3F (color_array[inext-1]);
664
665 norm [0] = cont_normal[j][0];
666 norm [1] = cont_normal[j][1];
667 N3F (norm);
668
669 point [0] = contour[j][0];
670 point [1] = contour[j][1];
671 point [2] = 0.0;
672 V3F (point, j, FRONT);
673
674 C3F (color_array[inext]);
675 N3F (norm);
676 point [2] = - len;
677 V3F (point, j, BACK);
678
679
680 C3F (color_array[inext-1]);
681 N3F (norm);
682
683 point [0] = contour[j+1][0];
684 point [1] = contour[j+1][1];
685 point [2] = 0.0;
686 V3F (point, j+1, FRONT);
687
688 C3F (color_array[inext]);
689 N3F (norm);
690 point [2] = - len;
691 V3F (point, j+1, BACK);
692 }
693
694 if (__TUBE_CLOSE_CONTOUR) {
695 /* connect back up to first point of contour */
696 point [0] = contour[ncp-1][0];
697 point [1] = contour[ncp-1][1];
698 point [2] = 0.0;
699 C3F (color_array[inext-1]);
700
701 norm [0] = cont_normal[ncp-1][0];
702 norm [1] = cont_normal[ncp-1][1];
703 N3F (norm);
704 V3F (point, ncp-1, FRONT);
705
706 C3F (color_array[inext]);
707 N3F (norm);
708
709 point [2] = - len;
710 V3F (point, ncp-1, BACK);
711
712 C3F (color_array[inext-1]);
713
714 norm [0] = cont_normal[0][0];
715 norm [1] = cont_normal[0][1];
716 N3F (norm);
717
718 point [0] = contour[0][0];
719 point [1] = contour[0][1];
720 point [2] = 0.0;
721 V3F (point, 0, FRONT);
722
723 C3F (color_array[inext]);
724 N3F (norm);
725
726 point [2] = - len;
727 V3F (point, 0, BACK);
728 }
729
730 ENDTMESH ();
731
732 /* draw the endcaps, if the join style calls for it */
733 if (__TUBE_DRAW_CAP) {
734
735 /* draw the front cap */
736 C3F (color_array[inext-1]);
737 norm [0] = norm [1] = 0.0;
738 norm [2] = 1.0;
739 N3F (norm);
740 draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
741
742 /* draw the back cap */
743 C3F (color_array[inext]);
744 norm [2] = -1.0;
745 N3F (norm);
746 draw_raw_style_end_cap (ncp, contour, -len, FALSE);
747 }
748
749 }
750
751 /* ============================================================ */
752 /* This routine draws "raw" style extrusions. By "raw" style, it is
753 * meant extrusions with square ends: ends that are cut at 90 degrees to
754 * the length of the extrusion. End caps are NOT drawn, unless the end cap
755 * style is indicated.
756 */
757
extrusion_raw_join(int ncp,gleDouble contour[][2],gleDouble cont_normal[][2],gleDouble up[3],int npoints,gleDouble point_array[][3],gleColor color_array[],gleDouble xform_array[][2][3])758 void extrusion_raw_join (int ncp, /* number of contour points */
759 gleDouble contour[][2], /* 2D contour */
760 gleDouble cont_normal[][2],/* 2D contour normal vecs */
761 gleDouble up[3], /* up vector for contour */
762 int npoints, /* numpoints in poly-line */
763 gleDouble point_array[][3], /* polyline */
764 gleColor color_array[], /* color of polyline */
765 gleDouble xform_array[][2][3]) /* 2D contour xforms */
766 {
767 int i, j;
768 int inext;
769 gleDouble m[4][4];
770 gleDouble len;
771 gleDouble diff[3];
772 gleDouble bi_0[3]; /* bisecting plane */
773 gleDouble yup[3]; /* alternate up vector */
774 gleDouble nrmv[3];
775 short no_norm, no_cols, no_xform; /*booleans */
776 char *mem_anchor = 0x0;
777 gleDouble *front_loop=0x0, *back_loop=0x0; /* countour loops */
778 gleDouble *front_norm=0x0, *back_norm=0x0; /* countour loops */
779 gleDouble *tmp;
780
781 nrmv[0] = nrmv[1] = 0.0; /* used for drawing end caps */
782 /* use some local variables for needed booleans */
783 no_norm = (cont_normal == NULL);
784 no_cols = (color_array == NULL);
785 no_xform = (xform_array == NULL);
786
787 /* alloc loop arrays if needed */
788 if (! no_xform) {
789 mem_anchor = malloc (4 * ncp * 3 * sizeof(gleDouble));
790 front_loop = (gleDouble *) mem_anchor;
791 back_loop = front_loop + 3*ncp;
792 front_norm = back_loop + 3*ncp;
793 back_norm = front_norm + 3*ncp;
794 }
795
796 /* By definition, the contour passed in has its up vector pointing in
797 * the y direction */
798 if (up == NULL) {
799 yup[0] = 0.0;
800 yup[1] = 1.0;
801 yup[2] = 0.0;
802 } else {
803 VEC_COPY (yup, up);
804 }
805
806 /* ========== "up" vector sanity check ========== */
807 (void) up_sanity_check (yup, npoints, point_array);
808
809 /* ignore all segments of zero length */
810 i = 1;
811 inext = i;
812 FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
813
814 /* first time through, get the loops */
815 if (! no_xform) {
816 for (j=0; j<ncp; j++) {
817 MAT_DOT_VEC_2X3 ((&front_loop[3*j]),
818 xform_array[inext-1], contour[j]);
819 front_loop[3*j+2] = 0.0;
820 }
821 if (!no_norm) {
822 for (j=0; j<ncp; j++) {
823 NORM_XFORM_2X2 ( (&front_norm[3*j]),
824 xform_array[inext-1],
825 cont_normal [j]);
826 front_norm[3*j+2] = 0.0;
827 back_norm[3*j+2] = 0.0;
828 }
829 }
830 }
831
832 /* draw tubing, not doing the first segment */
833 while (inext<npoints-1) {
834
835 /* get the two bisecting planes */
836 bisecting_plane (bi_0, point_array[i-1],
837 point_array[i],
838 point_array[inext]);
839
840 /* reflect the up vector in the bisecting plane */
841 VEC_REFLECT (yup, yup, bi_0);
842
843 /* rotate so that z-axis points down v2-v1 axis,
844 * and so that origen is at v1 */
845 uviewpoint (m, point_array[i], point_array[inext], yup);
846 PUSHMATRIX ();
847 MULTMATRIX (m);
848
849 /* There are six different cases we can have for presence and/or
850 * absecnce of colors and normals, and for interpretation of
851 * normals. The blechy set of nested if statements below
852 * branch to each of the six cases */
853 if (no_xform) {
854 if (no_cols) {
855 if (no_norm) {
856 draw_raw_segment_plain (ncp, contour, inext, len);
857 } else
858 if (__TUBE_DRAW_FACET_NORMALS) {
859 draw_raw_segment_facet_n (ncp, contour, cont_normal,
860 inext, len);
861 } else {
862 draw_raw_segment_edge_n (ncp, contour, cont_normal,
863 inext, len);
864 }
865 } else {
866 if (no_norm) {
867 draw_raw_segment_color (ncp, contour, color_array, inext, len);
868 } else
869 if (__TUBE_DRAW_FACET_NORMALS) {
870 draw_raw_segment_c_and_facet_n (ncp, contour,
871 color_array,
872 cont_normal,
873 inext, len);
874 } else {
875 draw_raw_segment_c_and_edge_n (ncp, contour,
876 color_array,
877 cont_normal,
878 inext, len);
879 }
880 }
881 } else {
882
883 /* else -- there are scales and offsets to deal with */
884 for (j=0; j<ncp; j++) {
885 MAT_DOT_VEC_2X3 ((&back_loop[3*j]),
886 xform_array[inext], contour[j]);
887 back_loop[3*j+2] = -len;
888 front_loop[3*j+2] = 0.0;
889 }
890
891 if (!no_norm) {
892 for (j=0; j<ncp; j++) {
893 NORM_XFORM_2X2 ( (&back_norm[3*j]),
894 xform_array[inext],
895 cont_normal [j]);
896 }
897 }
898
899 if (no_cols) {
900 if (no_norm) {
901 draw_segment_plain (ncp, (gleVector *) front_loop,
902 (gleVector *) back_loop,
903 inext, len);
904 } else
905 if (__TUBE_DRAW_FACET_NORMALS) {
906 draw_binorm_segment_facet_n (ncp, (gleVector *) front_loop,
907 (gleVector *) back_loop,
908 (gleVector *) front_norm,
909 (gleVector *) back_norm,
910 inext, len);
911 } else {
912 draw_binorm_segment_edge_n (ncp, (gleVector *) front_loop,
913 (gleVector *) back_loop,
914 (gleVector *) front_norm,
915 (gleVector *) back_norm,
916 inext, len);
917 }
918 if (__TUBE_DRAW_CAP) {
919 nrmv[2] = 1.0; N3F (nrmv);
920 draw_front_contour_cap (ncp, (gleVector *) front_loop);
921 nrmv[2] = -1.0; N3F (nrmv);
922 draw_back_contour_cap (ncp, (gleVector *) back_loop);
923 }
924 } else {
925 if (no_norm) {
926 draw_segment_color (ncp,
927 (gleVector *) front_loop,
928 (gleVector *) back_loop,
929 color_array[inext-1],
930 color_array[inext],
931 inext, len);
932 } else
933 if (__TUBE_DRAW_FACET_NORMALS) {
934 draw_binorm_segment_c_and_facet_n (ncp,
935 (gleVector *) front_loop,
936 (gleVector *) back_loop,
937 (gleVector *) front_norm,
938 (gleVector *) back_norm,
939 color_array[inext-1],
940 color_array[inext],
941 inext, len);
942 } else {
943 draw_binorm_segment_c_and_edge_n (ncp,
944 (gleVector *) front_loop,
945 (gleVector *) back_loop,
946 (gleVector *) front_norm,
947 (gleVector *) back_norm,
948 color_array[inext-1],
949 color_array[inext],
950 inext, len);
951 }
952 if (__TUBE_DRAW_CAP) {
953 C3F (color_array[inext-1]);
954 nrmv[2] = 1.0; N3F (nrmv);
955 draw_front_contour_cap (ncp, (gleVector *) front_loop);
956
957 C3F (color_array[inext]);
958 nrmv[2] = -1.0; N3F (nrmv);
959 draw_back_contour_cap (ncp, (gleVector *) back_loop);
960 }
961 }
962 }
963
964 /* pop this matrix, do the next set */
965 POPMATRIX ();
966
967 /* flop over transformed loops */
968 tmp = front_loop;
969 front_loop = back_loop;
970 back_loop = tmp;
971 tmp = front_norm;
972 front_norm = back_norm;
973 back_norm = tmp;
974
975 i = inext;
976 /* ignore all segments of zero length */
977 FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
978
979 }
980
981 /* free previously allocated memory, if any */
982 if (!no_xform) {
983 free (mem_anchor);
984 }
985 }
986
987 /* ============================================================ */
988