1 /* tube, Copyright (c) 2001-2012 Jamie Zawinski <jwz@jwz.org>
2 * Utility functions to create tubes and cones in GL.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
27 #endif /* HAVE_JWZGLES */
31 typedef struct { GLfloat x, y, z; } XYZ;
35 unit_tube (int faces, int smooth, int caps_p, int wire_p)
39 GLfloat step = M_PI * 2 / faces;
42 GLfloat x, y, x0=0, y0=0;
46 struct { XYZ p; XYZ n; GLfloat s, t; } *array;
48 arraysize = (faces+1) * 6;
49 array = (void *) calloc (arraysize, sizeof(*array));
54 /* #### texture coords are currently not being computed */
71 for (i = 0; i < faces; i++)
73 array[out].p.x = x; /* bottom point A */
78 array[out].n = array[out].p; /* its own normal */
81 array[out].n.x = x0; /* mid-plane normal */
88 array[out].p.x = x; /* top point A */
91 array[out].n = array[out-1].n; /* same normal */
104 array[out].p.x = x; /* top point B */
107 array[out].n = array[out-1].n; /* same normal */
111 array[out] = array[out-3]; /* bottom point A */
114 array[out] = array[out-2]; /* top point B */
117 array[out].p.x = x; /* bottom point B */
120 array[out].n = array[out-1].n; /* same normal */
127 if (out >= arraysize) abort();
130 glEnableClientState (GL_VERTEX_ARRAY);
131 glEnableClientState (GL_NORMAL_ARRAY);
132 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
134 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
135 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
136 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
139 glDrawArrays ((wire_p ? GL_LINES :
140 (smooth ? GL_TRIANGLE_STRIP : GL_TRIANGLES)),
147 for (z = 0; z <= 1; z++)
157 array[out].n.y = (z == 0 ? -1 : 1);
163 for (i = (z == 0 ? 0 : faces);
164 (z == 0 ? i <= faces : i >= 0);
165 i += (z == 0 ? 1 : -1)) {
166 GLfloat x = cos (th);
167 GLfloat y = sin (th);
169 array[out] = array[0]; /* same normal and texture */
175 th += (z == 0 ? step : -step);
178 if (out >= arraysize) abort();
181 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
182 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
183 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
186 glDrawArrays ((wire_p ? GL_LINE_LOOP : GL_TRIANGLE_FAN), 0, out);
196 unit_cone (int faces, int smooth, int cap_p, int wire_p)
200 GLfloat step = M_PI * 2 / faces;
203 GLfloat x, y, x0, y0;
206 struct { XYZ p; XYZ n; GLfloat s, t; } *array;
208 arraysize = (faces+1) * 3;
209 array = (void *) calloc (arraysize, sizeof(*array));
210 if (! array) abort();
214 /* #### texture coords are currently not being computed */
226 for (i = 0; i < faces; i++)
228 array[out].p.x = x; /* bottom point A */
233 array[out].n = array[out].p; /* its own normal */
236 array[out].n.x = x0; /* mid-plane normal */
243 array[out].p.x = 0; /* tip point */
247 array[out].n.x = x0; /* mid-plane normal */
259 array[out].p.x = x; /* bottom point B */
264 array[out].n = array[out].p; /* its own normal */
266 array[out].n = array[out-1].n; /* same normal as other two */
270 if (out >= arraysize) abort();
274 glEnableClientState (GL_VERTEX_ARRAY);
275 glEnableClientState (GL_NORMAL_ARRAY);
276 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
278 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
279 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
280 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
283 glDrawArrays ((wire_p ? GL_LINES : GL_TRIANGLES), 0, out);
304 for (i = 0, th = 0; i <= faces; i++)
306 GLfloat x = cos (th);
307 GLfloat y = sin (th);
309 array[out] = array[0]; /* same normal and texture */
316 if (out >= arraysize) abort();
319 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
320 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
321 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
324 glDrawArrays ((wire_p ? GL_LINE_LOOP : GL_TRIANGLE_FAN), 0, out);
334 tube_1 (GLfloat x1, GLfloat y1, GLfloat z1,
335 GLfloat x2, GLfloat y2, GLfloat z2,
336 GLfloat diameter, GLfloat cap_size,
337 int faces, int smooth, int caps_p, int wire_p,
340 GLfloat length, X, Y, Z;
343 if (diameter <= 0) abort();
349 if (X == 0 && Y == 0 && Z == 0)
352 length = sqrt (X*X + Y*Y + Z*Z);
356 glTranslatef(x1, y1, z1);
357 glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1);
358 glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
359 glScalef (diameter, length, diameter);
361 /* extend the endpoints of the tube by the cap size in both directions */
364 GLfloat c = cap_size/length;
365 glTranslatef (0, -c, 0);
366 glScalef (1, 1+c+c, 1);
370 polys = unit_cone (faces, smooth, caps_p, wire_p);
372 polys = unit_tube (faces, smooth, caps_p, wire_p);
380 tube (GLfloat x1, GLfloat y1, GLfloat z1,
381 GLfloat x2, GLfloat y2, GLfloat z2,
382 GLfloat diameter, GLfloat cap_size,
383 int faces, int smooth, int caps_p, int wire_p)
385 return tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size,
386 faces, smooth, caps_p, wire_p,
392 cone (GLfloat x1, GLfloat y1, GLfloat z1,
393 GLfloat x2, GLfloat y2, GLfloat z2,
394 GLfloat diameter, GLfloat cap_size,
395 int faces, int smooth, int cap_p, int wire_p)
397 return tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size,
398 faces, smooth, cap_p, wire_p,