Last active
January 30, 2025 08:32
-
-
Save stoned-ape/087f20bcdcf08d406015051209928f33 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // compile on linux: gcc x11_opengl.c -lm -lGL -lX11 | |
| // compile on mac: clang -framework OpenGL -I /opt/X11/include/ -L /opt/X11/lib/ -lGL -lX11 x11_opengl.c | |
| #include <X11/Xlib.h> | |
| #include <X11/Xutil.h> | |
| #if defined(__APPLE__) | |
| _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\""); | |
| #include <OpenGL/gl.h> | |
| #else | |
| #include <GL/gl.h> | |
| #endif | |
| #include <GL/glx.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <assert.h> | |
| #include <time.h> | |
| #include <sys/timeb.h> | |
| #include <math.h> | |
| #include <stdbool.h> | |
| #include <string.h> | |
| #define PRINT(val,type) printf("%s:\t"type"\n",#val,val); | |
| const float pi=3.141592653589793; | |
| double itime(){ | |
| struct timeb now; | |
| ftime(&now); | |
| return (double)(now.time%(60*60*24))+now.millitm/1e3; | |
| } | |
| void print_fps(){ | |
| static double timer; | |
| double delta=itime()-timer; | |
| timer+=delta; | |
| printf("\rfps = %f ",1/delta); | |
| fflush(stdout); | |
| } | |
| float map(float t,float t0,float t1,float s0,float s1){ | |
| return s0+(s1-s0)*(t-t0)/(t1-t0); | |
| } | |
| void color_wheel(float t,float ret[4]){ | |
| float theta=map(t,0.,1.,0.,2.*pi); | |
| float modulus=2.0f*pi*.75f; | |
| theta=fmodf(theta,modulus)+2.*pi*.87; | |
| float angles[2]={cosf(theta),sin(theta)}; | |
| angles[0]=map(angles[0],-1.,1.,0.,pi/2.); | |
| angles[1]=map(angles[1],-1.,1.,0.,pi/2.); | |
| ret[0]=cosf(angles[0])*sin(angles[1]); | |
| ret[1]=cosf(angles[1]); | |
| ret[2]=sin(angles[0])*sin(angles[1]); | |
| ret[3]=1; | |
| } | |
| void draw_square(){ | |
| glBegin(GL_TRIANGLE_STRIP); | |
| glVertex3f(-1,-1,0); | |
| glVertex3f(-1,+1,0); | |
| glVertex3f(+1,-1,0); | |
| glVertex3f(+1,+1,0); | |
| glEnd(); | |
| } | |
| float pos(bool p){return p?1.0f:-1.0f;} | |
| void draw_test_cube(){ | |
| glScalef(.75,.75,.75); | |
| for(int k=0;k<3;k++){ | |
| float rgb[3]={k==0,k==1,k==2}; | |
| for(int j=0;j<2;j++){ | |
| if(j==0) glColor3fv(rgb); | |
| else glColor3f(1-rgb[0],1-rgb[1],1-rgb[2]); | |
| glBegin(GL_TRIANGLE_STRIP); | |
| float vtx[3]; | |
| vtx[k]=.5*pos(j); | |
| for(int i=0;i<4;i++){ | |
| vtx[(k+1)%3]=+.5*pos(i/2); | |
| vtx[(k+2)%3]=+.5*pos(i%2); | |
| glVertex3fv(vtx); | |
| } | |
| glEnd(); | |
| } | |
| } | |
| } | |
| void draw_test_octa(){ | |
| for(int i=0;i<8;i++){ | |
| glColor3f(i&1,i&2,i&4); | |
| glBegin(GL_TRIANGLES); | |
| glVertex3f(.5*pos(i&1),0,0); | |
| glVertex3f(0,.5*pos(i&2),0); | |
| glVertex3f(0,0,.5*pos(i&4)); | |
| glEnd(); | |
| } | |
| } | |
| void draw_test_tetra(){ | |
| const float a=sqrtf(2)/4; | |
| float points[4][3]={ | |
| {+a,+.25,+0}, | |
| {-a,+.25,+0}, | |
| {+0,-.25,+a}, | |
| {+0,-.25,-a}, | |
| }; | |
| for(int i=0;i<4;i++){ | |
| glColor3f(points[i][0]+.5,points[i][2]+.5,points[i][2]+.5); | |
| glBegin(GL_TRIANGLES); | |
| for(int j=0;j<4;j++) if(i!=j){ | |
| glVertex3fv(points[j]); | |
| } | |
| glEnd(); | |
| } | |
| } | |
| void draw_test_ico() { | |
| float a=2*sinf(pi/5); | |
| float b=a*sinf(acosf(1/a)); | |
| float d=2*sinf(pi/10); | |
| float c=sqrtf(a*a-d*d)/2; | |
| float s=.5; | |
| float ud[2][4]={{0,s*(b+c),0,s},{0,s*(-b-c),0,s}}; | |
| float mid[2][5][4]; | |
| for(int i=0;i<2;i++){ | |
| for(int j=0;j<5;j++){ | |
| float theta=2*pi*j/5.0+pi/5.0*i; | |
| float p[4]={s*cosf(theta),-s*pos(i)*c,s*sinf(theta),s}; | |
| memcpy(mid[i][j],p,sizeof(p)); | |
| } | |
| } | |
| glBegin(GL_TRIANGLES); | |
| for(int i=0;i<2;i++){ | |
| for(int j=0;j<5;j++){ | |
| float col[4]; | |
| color_wheel(j/6.0+i*1/10.0,col); | |
| glColor3f(col[0],col[1],col[2]); | |
| glVertex3fv(mid[i][j]); | |
| glVertex3fv(mid[i][(j+1)%5]); | |
| glVertex3fv(ud[i]); | |
| } | |
| } | |
| for(int j=0;j<5;j++){ | |
| for(int i=0;i<2;i++){ | |
| float col[4]; | |
| color_wheel(j/6.0+1/20.0+1/40.0*i,col); | |
| glColor3f(col[0],col[1],col[2]); | |
| glVertex3fv(mid[i][j]); | |
| glVertex3fv(mid[i][(j+(i?4:1))%5]); | |
| glVertex3fv(mid[!i][j]); | |
| } | |
| } | |
| glEnd(); | |
| } | |
| float deg(float rad){return rad*180/pi;} | |
| void draw_pentagon(){ | |
| glBegin(GL_TRIANGLE_FAN); | |
| glVertex3f(0,0,0); | |
| for(int i=0;i<6;i++){ | |
| float theta=i*2*pi/5; | |
| glVertex3f(sinf(theta),0,cosf(theta)); | |
| } | |
| glEnd(); | |
| } | |
| void draw_test_dodec(){ | |
| const float s=.4; | |
| const float v=s/(2*sinf(pi/5)); | |
| const float m=v*cosf(pi/5); | |
| const float a=2*v*sinf(2*pi/5); | |
| const float phi=(1+sqrtf(5))/2; | |
| const float gamma=2*atanf(phi); | |
| const float h=s*sqrtf((25+11*sqrtf(5))/10); | |
| int face_idx=0; | |
| float col[4]; | |
| for(int j=0;j<2;j++){ | |
| glPushMatrix(); | |
| glRotatef(deg(j*pi/5),0,1,0); | |
| glScalef(1,pos(j),1); | |
| glTranslatef(0,h/2,0); | |
| glPushMatrix(); | |
| glScalef(v,v,v); | |
| color_wheel(((7*face_idx++)%12)/12.0+1/48.0,col); | |
| glColor3fv(col); | |
| draw_pentagon(); | |
| glPopMatrix(); | |
| for(int i=0;i<5;i++){ | |
| glPushMatrix(); | |
| glRotatef(deg(2*i*pi/5),0,1,0); | |
| glTranslatef(0,0,-m); | |
| glRotatef(deg(gamma),1,0,0); | |
| glTranslatef(0,0,m); | |
| glScalef(v,v,v); | |
| color_wheel(((7*face_idx++)%12)/12.0+1/48.0,col); | |
| glColor3fv(col); | |
| draw_pentagon(); | |
| glPopMatrix(); | |
| } | |
| glPopMatrix(); | |
| } | |
| } | |
| void draw_test_sphere(int res){ | |
| float inc=pi/res; | |
| float rho=.5; | |
| for(float phi=0;phi<pi;phi+=inc){ | |
| for(float theta=0;theta<2*pi;theta+=inc){ | |
| glBegin(GL_TRIANGLE_STRIP); | |
| glColor3f( | |
| .5+.5*cosf(theta+inc/2)*sinf(phi+inc/2), | |
| .5+.5* cosf(phi+inc/2), | |
| .5+.5*sinf(theta+inc/2)*sinf(phi+inc/2) | |
| ); | |
| for(int i=0;i<4;i++){ | |
| float t=theta+inc*(i&1); | |
| float p=phi+.5*inc*(i&2); | |
| glVertex3f( | |
| rho*cosf(t)*sinf(p), | |
| rho*cosf(p), | |
| rho*sinf(t)*sinf(p) | |
| ); | |
| } | |
| glEnd(); | |
| } | |
| } | |
| } | |
| int main(){ | |
| puts(__func__); | |
| Display *display=XOpenDisplay(NULL); | |
| assert(display); | |
| Window root=DefaultRootWindow(display); | |
| int att[]={GLX_RGBA,GLX_DEPTH_SIZE,24,GLX_DOUBLEBUFFER,None}; | |
| XVisualInfo *vi=glXChooseVisual(display, 0, att); | |
| assert(vi); | |
| XSetWindowAttributes swa; | |
| Colormap cmap=XCreateColormap(display,root,vi->visual,AllocNone); | |
| swa.colormap=cmap; | |
| swa.event_mask=ExposureMask|KeyPressMask; | |
| int width=600,height=600; | |
| Window win=XCreateWindow(display,root,0,0,width,height,0,vi->depth, | |
| InputOutput,vi->visual,CWColormap|CWEventMask,&swa); | |
| XMapWindow(display,win); | |
| XStoreName(display,win, ".______."); | |
| GLXContext glc=glXCreateContext(display,vi,NULL,GL_TRUE); | |
| glXMakeCurrent(display,win,glc); | |
| puts((const char *)glGetString(GL_VERSION)); | |
| glEnable(GL_DEPTH_TEST); | |
| bool running=true; | |
| while(running){ | |
| XEvent e={0}; | |
| while(XCheckWindowEvent(display,win,ExposureMask|KeyPressMask,&e)){ | |
| puts("event"); | |
| } | |
| int root_x,root_y,win_x,win_y; | |
| Window child; | |
| unsigned int mask; | |
| XQueryPointer(display,root,&root,&child,&root_x,&root_y,&win_x,&win_y,&mask); | |
| float theta=map(root_x,0,width,pi,-pi); | |
| float phi=map(root_y,0,height,pi/2,-pi/2); | |
| glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); | |
| for(int i=0;i<4;i++){ | |
| glViewport((i&1)*width/2,(i>1)*height/2,width/2,height/2); | |
| glPushMatrix(); | |
| glScalef(height/width,1,1); | |
| glRotatef(deg(phi),1,0,0); | |
| glRotatef(deg(theta),0,1,0); | |
| switch(i){ | |
| case 0:draw_test_octa();break; | |
| case 1:draw_test_cube();break; | |
| case 2:draw_test_ico();break; | |
| case 3:draw_test_dodec();break; | |
| } | |
| // draw_test_sphere(20); | |
| glPopMatrix(); | |
| } | |
| assert(glGetError()==GL_NO_ERROR); | |
| glXSwapBuffers(display, win); | |
| print_fps(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment