You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*#define MINIGLUT_GCC_NO_BUILTIN*/
+
#ifdef MINIGLUT_USE_LIBC
+#define _GNU_SOURCE
#include <stdlib.h>
+#include <math.h>
+#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 <X11/Xlib.h>
};
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);
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;
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;
}
/* 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<stacks; i++) {
+ v = i * dv;
+ for(j=0; j<slices; j++) {
+ u = j * du;
+ for(k=0; k<4; k++) {
+ gray = k ^ (k >> 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<stacks; i++) {
+ v = i * dv;
+ for(j=0; j<slices; j++) {
+ u = j * du;
+ for(k=0; k<4; k++) {
+ gray = k ^ (k >> 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<rings; i++) {
+ u = i * du;
+ for(j=0; j<sides; j++) {
+ v = j * dv;
+ for(k=0; k<4; k++) {
+ gray = k ^ (k >> 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)
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);
*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);
*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);
{
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__