From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / glx / gllist.c
1 /* xscreensaver, Copyright (c) 1998-2014 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 #include "gllist.h"
13
14 void
15 renderList (const struct gllist *list, int wire_p)
16 {
17   while (list)
18     {
19       if (!wire_p || list->primitive == GL_LINES ||
20           list->primitive == GL_POINTS)
21         {
22           glInterleavedArrays (list->format, 0, list->data);
23           glDrawArrays (list->primitive, 0, list->points);
24         }
25       else
26         {
27           /* For wireframe, do it the hard way: treat every tuple of
28              points as its own line loop.
29            */
30           const GLfloat *p = (GLfloat *) list->data;
31           int i, j, tick, skip, stride;
32
33           switch (list->primitive) {
34           case GL_QUADS: tick = 4; break;
35           case GL_TRIANGLES: tick = 3; break;
36           default: abort(); break; /* write me */
37           }
38
39           switch (list->format) {
40           case GL_C3F_V3F: case GL_N3F_V3F: skip = 3; stride = 6; break;
41           default: abort(); break; /* write me */
42           }
43
44           glBegin (GL_LINE_LOOP);
45           for (i = 0, j = skip;
46                i < list->points;
47                i++, j += stride)
48             {
49               if (i && !(i % tick))
50                 {
51                   glEnd();
52                   glBegin (GL_LINE_LOOP);
53                 }
54               glVertex3f (p[j], p[j+1], p[j+2]);
55             }
56           glEnd();
57         }
58       list = list->next;
59     }
60 }
61
62
63 void
64 renderListNormals (const struct gllist *list, GLfloat length, int faces_p)
65 {
66   while (list)
67     {
68       const GLfloat *p = (GLfloat *) list->data;
69       int i, j, tick, skip, stride;
70       GLfloat v[3], n[3];
71
72       if (list->primitive == GL_LINES) continue;
73
74       if (! faces_p)
75         tick = 1;
76       else
77         switch (list->primitive) {
78         case GL_QUADS: tick = 4; break;
79         case GL_TRIANGLES: tick = 3; break;
80         default: abort(); break; /* write me */
81         }
82
83       switch (list->format) {
84       case GL_N3F_V3F: skip = 0; stride = 6; break;
85       case GL_C3F_V3F: continue; break;
86       default: abort(); break; /* write me */
87       }
88
89       v[0] = v[1] = v[2] = 0;
90       n[0] = n[1] = n[2] = 0;
91
92       for (i = 0, j = skip;
93            i <= list->points;
94            i++, j += stride)
95         {
96           if (i && !(i % tick))
97             {
98               n[0] /= tick;
99               n[1] /= tick;
100               n[2] /= tick;
101               v[0] /= tick;
102               v[1] /= tick;
103               v[2] /= tick;
104               glPushMatrix();
105               glTranslatef (v[0], v[1], v[2]);
106               glScalef (length, length, length);
107               glBegin (GL_LINES);
108               glVertex3f (0, 0, 0);
109               glVertex3f (n[0], n[1], n[2]);
110               glEnd();
111               glPopMatrix();
112               v[0] = v[1] = v[2] = 0;
113               n[0] = n[1] = n[2] = 0;
114             }
115
116           if (i == list->points) break;
117           n[0] += p[j];
118           n[1] += p[j+1];
119           n[2] += p[j+2];
120           v[0] += p[j+3];
121           v[1] += p[j+4];
122           v[2] += p[j+5];
123
124         }
125       list = list->next;
126     }
127 }