X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=miniglut.c;h=92682024590c3e97ceb0d5f3ee52dfcddaed68a6;hb=02536825844445fbb648cf2a69c97760e7eef885;hp=788d8a135475445aa753caf392723af5c79c80d0;hpb=74b32cf95068bf04d84d080dc48dc8e89707562f;p=miniglut
diff --git a/miniglut.c b/miniglut.c
index 788d8a1..9268202 100644
--- a/miniglut.c
+++ b/miniglut.c
@@ -15,10 +15,26 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+/*#define MINIGLUT_GCC_NO_BUILTIN*/
+
#ifdef MINIGLUT_USE_LIBC
+#define _GNU_SOURCE
#include
+#include
+#else
+
+#if defined(__GNUC__) && !defined(MINIGLUT_GCC_NO_BUILTIN)
+#define mglut_sincosf(a, s, c) __builtin_sincosf(a, s, c)
+#define mglut_atan(x) __builtin_atan(x)
+#else
+static void mglut_sincosf(float angle, float *sptr, float *cptr);
+static float mglut_atan(float x);
#endif
+#endif
+
+#define PI 3.1415926536f
+
#if defined(__unix__)
#include
@@ -67,9 +83,9 @@ struct ctx_info {
};
static void create_window(const char *title);
-static void get_window_pos(Window win, int *x, int *y);
-static void get_window_size(Window win, int *w, int *h);
-static void get_screen_size(Window win, int *scrw, int *scrh);
+static void get_window_pos(int *x, int *y);
+static void get_window_size(int *w, int *h);
+static void get_screen_size(int *scrw, int *scrh);
static long get_msec(void);
static void panic(const char *msg);
@@ -273,16 +289,16 @@ int glutGet(unsigned int s)
int x, y;
switch(s) {
case GLUT_WINDOW_X:
- get_window_pos(win, &x, &y);
+ get_window_pos(&x, &y);
return x;
case GLUT_WINDOW_Y:
- get_window_pos(win, &x, &y);
+ get_window_pos(&x, &y);
return y;
case GLUT_WINDOW_WIDTH:
- get_window_size(win, &x, &y);
+ get_window_size(&x, &y);
return x;
case GLUT_WINDOW_HEIGHT:
- get_window_size(win, &x, &y);
+ get_window_size(&x, &y);
return y;
case GLUT_WINDOW_BUFFER_SIZE:
return ctx_info.rsize + ctx_info.gsize + ctx_info.bsize + ctx_info.asize;
@@ -311,10 +327,10 @@ int glutGet(unsigned int s)
case GLUT_WINDOW_CURSOR:
return cur_cursor;
case GLUT_SCREEN_WIDTH:
- get_screen_size(win, &x, &y);
+ get_screen_size(&x, &y);
return x;
case GLUT_SCREEN_HEIGHT:
- get_screen_size(win, &x, &y);
+ get_screen_size(&x, &y);
return y;
case GLUT_INIT_DISPLAY_MODE:
return init_mode;
@@ -375,28 +391,190 @@ int glutExtensionSupported(char *ext)
}
/* TODO */
-void glutSolidSphere(float rad)
+void glutSolidSphere(float rad, int slices, int stacks)
{
+ int i, j, k, gray;
+ float x, y, z, s, t, u, v, phi, theta, sintheta, costheta, sinphi, cosphi;
+ float du = 1.0f / (float)slices;
+ float dv = 1.0f / (float)stacks;
+
+ glBegin(GL_QUADS);
+ for(i=0; i> 1);
+ s = gray & 1 ? u + du : u;
+ t = gray & 2 ? v + dv : v;
+ theta = s * PI * 2.0f;
+ phi = t * PI;
+ mglut_sincosf(theta, &sintheta, &costheta);
+ mglut_sincosf(phi, &sinphi, &cosphi);
+ x = sintheta * sinphi;
+ y = costheta * sinphi;
+ z = cosphi;
+
+ glColor3f(s, t, 1);
+ glTexCoord2f(s, t);
+ glNormal3f(x, y, z);
+ glVertex3f(x * rad, y * rad, z * rad);
+ }
+ }
+ }
+ glEnd();
}
-void glutWireSphere(float rad)
+void glutWireSphere(float rad, int slices, int stacks)
{
+ glPushAttrib(GL_POLYGON_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glutSolidSphere(rad, slices, stacks);
+ glPopAttrib();
}
void glutSolidCube(float sz)
{
+ int i, j, idx, gray, flip, rotx;
+ float vpos[3], norm[3];
+ float rad = sz * 0.5f;
+
+ glBegin(GL_QUADS);
+ for(i=0; i<6; i++) {
+ flip = i & 1;
+ rotx = i >> 2;
+ idx = (~i & 2) - rotx;
+ norm[0] = norm[1] = norm[2] = 0.0f;
+ norm[idx] = flip ^ ((i >> 1) & 1) ? -1 : 1;
+ glNormal3fv(norm);
+ vpos[idx] = norm[idx] * rad;
+ for(j=0; j<4; j++) {
+ gray = j ^ (j >> 1);
+ vpos[i & 2] = (gray ^ flip) & 1 ? rad : -rad;
+ vpos[rotx + 1] = (gray ^ (rotx << 1)) & 2 ? rad : -rad;
+ glTexCoord2f(gray & 1, gray >> 1);
+ glVertex3fv(vpos);
+ }
+ }
+ glEnd();
}
void glutWireCube(float sz)
{
+ glPushAttrib(GL_POLYGON_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glutSolidCube(sz);
+ glPopAttrib();
+}
+
+static void draw_cylinder(float rbot, float rtop, float height, int slices, int stacks)
+{
+ int i, j, k, gray;
+ float x, y, z, s, t, u, v, theta, phi, sintheta, costheta, sinphi, cosphi, rad;
+ float du = 1.0f / (float)slices;
+ float dv = 1.0f / (float)stacks;
+
+ rad = rbot - rtop;
+ phi = mglut_atan((rad < 0 ? -rad : rad) / height);
+ mglut_sincosf(phi, &sinphi, &cosphi);
+
+ glBegin(GL_QUADS);
+ for(i=0; i> 1);
+ s = gray & 2 ? u + du : u;
+ t = gray & 1 ? v + dv : v;
+ rad = rbot + (rtop - rbot) * t;
+ theta = s * PI * 2.0f;
+ mglut_sincosf(theta, &sintheta, &costheta);
+
+ x = sintheta * cosphi;
+ y = costheta * cosphi;
+ z = sinphi;
+
+ glColor3f(s, t, 1);
+ glTexCoord2f(s, t);
+ glNormal3f(x, y, z);
+ glVertex3f(sintheta * rad, costheta * rad, t * height);
+ }
+ }
+ }
+ glEnd();
+}
+
+void glutSolidCone(float base, float height, int slices, int stacks)
+{
+ draw_cylinder(base, 0, height, slices, stacks);
+}
+
+void glutWireCone(float base, float height, int slices, int stacks)
+{
+ glPushAttrib(GL_POLYGON_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glutSolidCone(base, height, slices, stacks);
+ glPopAttrib();
+}
+
+void glutSolidCylinder(float rad, float height, int slices, int stacks)
+{
+ draw_cylinder(rad, rad, height, slices, stacks);
+}
+
+void glutWireCylinder(float rad, float height, int slices, int stacks)
+{
+ glPushAttrib(GL_POLYGON_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glutSolidCylinder(rad, height, slices, stacks);
+ glPopAttrib();
}
-void glutSolidTorus(float inner_rad, float outer_rad, float sides, float rings)
+void glutSolidTorus(float inner_rad, float outer_rad, int sides, int rings)
{
+ int i, j, k, gray;
+ float x, y, z, s, t, u, v, phi, theta, sintheta, costheta, sinphi, cosphi;
+ float du = 1.0f / (float)rings;
+ float dv = 1.0f / (float)sides;
+
+ glBegin(GL_QUADS);
+ for(i=0; i> 1);
+ s = gray & 1 ? u + du : u;
+ t = gray & 2 ? v + dv : v;
+ theta = s * PI * 2.0f;
+ phi = t * PI * 2.0f;
+ mglut_sincosf(theta, &sintheta, &costheta);
+ mglut_sincosf(phi, &sinphi, &cosphi);
+ x = sintheta * sinphi;
+ y = costheta * sinphi;
+ z = cosphi;
+
+ glColor3f(s, t, 1);
+ glTexCoord2f(s, t);
+ glNormal3f(x, y, z);
+
+ x = x * inner_rad + sintheta * outer_rad;
+ y = y * inner_rad + costheta * outer_rad;
+ z *= inner_rad;
+ glVertex3f(x, y, z);
+ }
+ }
+ }
+ glEnd();
}
-void glutWireTorus(float inner_rad, float outer_rad, float sides, float rings)
+void glutWireTorus(float inner_rad, float outer_rad, int sides, int rings)
{
+ glPushAttrib(GL_POLYGON_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glutSolidTorus(inner_rad, outer_rad, sides, rings);
+ glPopAttrib();
}
void glutSolidTeapot(float size)
@@ -716,7 +894,7 @@ static void create_window(const char *title)
glXMakeCurrent(dpy, win, ctx);
}
-static void get_window_pos(Window win, int *x, int *y)
+static void get_window_pos(int *x, int *y)
{
XWindowAttributes wattr;
XGetWindowAttributes(dpy, win, &wattr);
@@ -724,7 +902,7 @@ static void get_window_pos(Window win, int *x, int *y)
*y = wattr.y;
}
-static void get_window_size(Window win, int *w, int *h)
+static void get_window_size(int *w, int *h)
{
XWindowAttributes wattr;
XGetWindowAttributes(dpy, win, &wattr);
@@ -732,7 +910,7 @@ static void get_window_size(Window win, int *w, int *h)
*h = wattr.height;
}
-static void get_screen_size(Window win, int *scrw, int *scrh)
+static void get_screen_size(int *scrw, int *scrh)
{
XWindowAttributes wattr;
XGetWindowAttributes(dpy, root, &wattr);
@@ -789,8 +967,80 @@ static int sys_write(int fd, const void *buf, int count)
{
return write(fd, buf, count);
}
+
#else /* !MINIGLUT_USE_LIBC */
+#if defined(__GNUC__) && defined(MINIGLUT_GCC_NO_BUILTIN)
+static void mglut_sincosf(float angle, float *sptr, float *cptr)
+{
+ asm volatile(
+ "flds %2\n\t"
+ "fsincos\n\t"
+ "fstps %1\n\t"
+ "fstps %0\n\t"
+ : "=m"(*sptr), "=m"(*cptr)
+ : "m"(angle)
+ );
+}
+
+static float mglut_atan(float x)
+{
+ float res;
+ asm volatile(
+ "flds %1\n\t"
+ "fld1\n\t"
+ "fpatan\n\t"
+ "fstps %0\n\t"
+ : "=m"(res)
+ : "m"(x)
+ );
+ return res;
+}
+#endif
+
+#ifdef _MSC_VER
+static void mglut_sincosf(float angle, float *sptr, float *cptr)
+{
+ float s, c;
+ __asm {
+ fld angle
+ fsincos
+ fstp c
+ fstp s
+ }
+ *sptr = s;
+ *cptr = c;
+}
+
+static float mglut_atan(float x)
+{
+ float res;
+ __asm {
+ fld x
+ fld1
+ fpatan
+ fstp res
+ }
+ return res;
+}
+#endif
+
+#ifdef __WATCOMC__
+#pragma aux mglut_sincosf = \
+ "fsincos" \
+ "fstp dword ptr [edx]" \
+ "fstp dword ptr [eax]" \
+ parm[8087][eax][edx] \
+ modify[8087];
+
+#pragma aux mglut_atan = \
+ "fld1" \
+ "fpatan" \
+ parm[8087] \
+ value[8087] \
+ modify [8087];
+#endif
+
#ifdef __linux__
#ifdef __x86_64__