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
22 #elif defined(HAVE_ANDROID)
30 #endif /* HAVE_JWZGLES */
34 typedef struct { GLfloat x, y, z; } XYZ;
38 unit_tube (int faces, int smooth, int caps_p, int wire_p)
42 GLfloat step = M_PI * 2 / faces;
45 GLfloat x, y, x0=0, y0=0;
49 struct { XYZ p; XYZ n; GLfloat s, t; } *array;
51 arraysize = (faces+1) * 6;
52 array = (void *) calloc (arraysize, sizeof(*array));
57 /* #### texture coords are currently not being computed */
74 for (i = 0; i < faces; i++)
76 array[out].p.x = x; /* bottom point A */
81 array[out].n = array[out].p; /* its own normal */
84 array[out].n.x = x0; /* mid-plane normal */
91 array[out].p.x = x; /* top point A */
94 array[out].n = array[out-1].n; /* same normal */
107 array[out].p.x = x; /* top point B */
110 array[out].n = array[out-1].n; /* same normal */
114 array[out] = array[out-3]; /* bottom point A */
117 array[out] = array[out-2]; /* top point B */
120 array[out].p.x = x; /* bottom point B */
123 array[out].n = array[out-1].n; /* same normal */
130 if (out >= arraysize) abort();
133 glEnableClientState (GL_VERTEX_ARRAY);
134 glEnableClientState (GL_NORMAL_ARRAY);
135 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
137 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
138 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
139 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
142 glDrawArrays ((wire_p ? GL_LINES :
143 (smooth ? GL_TRIANGLE_STRIP : GL_TRIANGLES)),
150 for (z = 0; z <= 1; z++)
160 array[out].n.y = (z == 0 ? -1 : 1);
166 for (i = (z == 0 ? 0 : faces);
167 (z == 0 ? i <= faces : i >= 0);
168 i += (z == 0 ? 1 : -1)) {
169 GLfloat x = cos (th);
170 GLfloat y = sin (th);
172 array[out] = array[0]; /* same normal and texture */
178 th += (z == 0 ? step : -step);
181 if (out >= arraysize) abort();
184 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
185 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
186 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
189 glDrawArrays ((wire_p ? GL_LINE_LOOP : GL_TRIANGLE_FAN), 0, out);
199 unit_cone (int faces, int smooth, int cap_p, int wire_p)
203 GLfloat step = M_PI * 2 / faces;
206 GLfloat x, y, x0, y0;
209 struct { XYZ p; XYZ n; GLfloat s, t; } *array;
211 arraysize = (faces+1) * 3;
212 array = (void *) calloc (arraysize, sizeof(*array));
213 if (! array) abort();
217 /* #### texture coords are currently not being computed */
229 for (i = 0; i < faces; i++)
231 array[out].p.x = x; /* bottom point A */
236 array[out].n = array[out].p; /* its own normal */
239 array[out].n.x = x0; /* mid-plane normal */
246 array[out].p.x = 0; /* tip point */
250 array[out].n.x = x0; /* mid-plane normal */
262 array[out].p.x = x; /* bottom point B */
267 array[out].n = array[out].p; /* its own normal */
269 array[out].n = array[out-1].n; /* same normal as other two */
273 if (out >= arraysize) abort();
277 glEnableClientState (GL_VERTEX_ARRAY);
278 glEnableClientState (GL_NORMAL_ARRAY);
279 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
281 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
282 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
283 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
286 glDrawArrays ((wire_p ? GL_LINES : GL_TRIANGLES), 0, out);
307 for (i = 0, th = 0; i <= faces; i++)
309 GLfloat x = cos (th);
310 GLfloat y = sin (th);
312 array[out] = array[0]; /* same normal and texture */
319 if (out >= arraysize) abort();
322 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
323 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
324 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
327 glDrawArrays ((wire_p ? GL_LINE_LOOP : GL_TRIANGLE_FAN), 0, out);
337 tube_1 (GLfloat x1, GLfloat y1, GLfloat z1,
338 GLfloat x2, GLfloat y2, GLfloat z2,
339 GLfloat diameter, GLfloat cap_size,
340 int faces, int smooth, int caps_p, int wire_p,
343 GLfloat length, X, Y, Z;
346 if (diameter <= 0) abort();
352 if (X == 0 && Y == 0 && Z == 0)
355 length = sqrt (X*X + Y*Y + Z*Z);
359 glTranslatef(x1, y1, z1);
360 glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1);
361 glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
362 glScalef (diameter, length, diameter);
364 /* extend the endpoints of the tube by the cap size in both directions */
367 GLfloat c = cap_size/length;
368 glTranslatef (0, -c, 0);
369 glScalef (1, 1+c+c, 1);
373 polys = unit_cone (faces, smooth, caps_p, wire_p);
375 polys = unit_tube (faces, smooth, caps_p, wire_p);
383 tube (GLfloat x1, GLfloat y1, GLfloat z1,
384 GLfloat x2, GLfloat y2, GLfloat z2,
385 GLfloat diameter, GLfloat cap_size,
386 int faces, int smooth, int caps_p, int wire_p)
388 return tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size,
389 faces, smooth, caps_p, wire_p,
395 cone (GLfloat x1, GLfloat y1, GLfloat z1,
396 GLfloat x2, GLfloat y2, GLfloat z2,
397 GLfloat diameter, GLfloat cap_size,
398 int faces, int smooth, int cap_p, int wire_p)
400 return tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size,
401 faces, smooth, cap_p, wire_p,