xenocara/app/xlockmore/modes/glx/tube.c

215 lines
4.6 KiB
C
Raw Normal View History

2006-11-26 04:07:42 -07:00
/* tube, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
* Utility functions to create tubes and cones in GL.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*/
#ifdef STANDALONE
#include "xlockmore.h" /* from the xlockmore distribution */
#else /* !STANDALONE */
#include "xlock.h" /* from the xlockmore distribution */
#endif /* !STANDALONE */
#include <GL/glx.h>
static void
unit_tube (int faces, Bool smooth, Bool wire)
{
int i;
GLfloat step = M_PI * 2 / faces;
GLfloat s2 = step/2;
GLfloat th;
GLfloat x, y, x0 = 0.0, y0 = 0.0;
int z = 0;
/* side walls
*/
glFrontFace(GL_CCW);
glBegin (wire ? GL_LINES : (smooth ? GL_QUAD_STRIP : GL_QUADS));
th = 0;
x = 1;
y = 0;
if (!smooth)
{
x0 = cos (s2);
y0 = sin (s2);
}
if (smooth) faces++;
for (i = 0; i < faces; i++)
{
if (smooth)
glNormal3f(x, 0, y);
else
glNormal3f(x0, 0, y0);
glVertex3f(x, 0, y);
glVertex3f(x, 1, y);
th += step;
x = cos (th);
y = sin (th);
if (!smooth)
{
x0 = cos (th + s2);
y0 = sin (th + s2);
glVertex3f(x, 1, y);
glVertex3f(x, 0, y);
}
}
glEnd();
/* End caps
*/
for (z = 0; z <= 1; z++)
{
glFrontFace(z == 0 ? GL_CCW : GL_CW);
glNormal3f(0, (z == 0 ? -1 : 1), 0);
glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
if (! wire) glVertex3f(0, z, 0);
for (i = 0, th = 0; i <= faces; i++)
{
GLfloat x = cos (th);
GLfloat y = sin (th);
glVertex3f(x, z, y);
th += step;
}
glEnd();
}
}
static void
unit_cone (int faces, Bool smooth, Bool wire)
{
int i;
GLfloat step = M_PI * 2 / faces;
GLfloat s2 = step/2;
GLfloat th;
GLfloat x, y, x0, y0;
/* side walls
*/
glFrontFace(GL_CW);
glBegin(wire ? GL_LINES : GL_TRIANGLES);
th = 0;
x = 1;
y = 0;
x0 = cos (s2);
y0 = sin (s2);
for (i = 0; i < faces; i++)
{
glNormal3f(x0, 0, y0);
glVertex3f(0, 1, 0);
if (smooth) glNormal3f(x, 0, y);
glVertex3f(x, 0, y);
th += step;
x0 = cos (th + s2);
y0 = sin (th + s2);
x = cos (th);
y = sin (th);
if (smooth) glNormal3f(x, 0, y);
glVertex3f(x, 0, y);
}
glEnd();
/* End cap
*/
glFrontFace(GL_CCW);
glNormal3f(0, -1, 0);
glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
if (! wire) glVertex3f(0, 0, 0);
for (i = 0, th = 0; i <= faces; i++)
{
GLfloat x = cos (th);
GLfloat y = sin (th);
glVertex3f(x, 0, y);
th += step;
}
glEnd();
}
static void
tube_1 (GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat diameter, GLfloat cap_size,
int faces, Bool smooth, Bool wire,
Bool cone_p)
{
GLfloat length, angle, a, b, c;
if (diameter <= 0)
return;
a = (x2 - x1);
b = (y2 - y1);
c = (z2 - z1);
length = sqrt (a*a + b*b + c*c);
angle = acos (a / length);
glPushMatrix();
glTranslatef(x1, y1, z1);
glScalef (length, length, length);
if (c == 0 && b == 0)
glRotatef (angle / (M_PI / 180), 0, 1, 0);
else
glRotatef (angle / (M_PI / 180), 0, -c, b);
glRotatef (-90, 0, 0, 1);
glScalef (diameter/length, 1, diameter/length);
/* extend the endpoints of the tube by the cap size in both directions */
if (cap_size != 0)
{
GLfloat c = cap_size/length;
glTranslatef (0, -c, 0);
glScalef (1, 1+c+c, 1);
}
if (cone_p)
unit_cone (faces, smooth, wire);
else
unit_tube (faces, smooth, wire);
glPopMatrix();
}
void
tube (GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat diameter, GLfloat cap_size,
int faces, Bool smooth, Bool wire)
{
tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size, faces, smooth, wire,
False);
}
void
cone (GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat diameter, GLfloat cap_size,
int faces, Bool smooth, Bool wire)
{
tube_1 (x1, y1, z1, x2, y2, z2, diameter, cap_size, faces, smooth, wire,
True);
}