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__