C   35

sdlr

Guest on 10th June 2022 01:28:11 PM

  1. /* Compile me with
  2.  * cc -o sdlr sdlr.c `sdl-config --cflags` -lGL -lGLU -lglut `sdl-config --libs`
  3. */
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <SDL/SDL.h>
  8. #include <GL/gl.h>
  9. #include <GL/glu.h>
  10. #include <GL/glut.h>
  11.  
  12. #include <unistd.h>
  13. #include <math.h>
  14.  
  15. #include <png.h>
  16.  
  17. struct quat {
  18.         GLfloat q0,q1,q2,q3;
  19. };
  20.  
  21. typedef struct quat quat_t;
  22.  
  23.  
  24.  
  25. /*********** globals for main code ************/
  26.  
  27. const GLfloat nearclip=0.1;
  28.  
  29. SDL_Surface *screen,*bitmap;    /* Screen data handles */
  30.  
  31. SDL_Rect screenrect;            /* Screen geometry */
  32. int screenx,screeny;
  33.  
  34. Uint16 timetop,timebot;
  35.  
  36. GLfloat sphererad=0.0; /* Radius of trackball sphere */
  37.  
  38. int glinit=0; /* Set to 1 once GL has been set up */
  39. unsigned int frameno=0;
  40.  
  41. /* Things which are global but shouldn't be */
  42. volatile int frameflag=0;       /* Set to 1 after frame timer expires */
  43. #define FRAMETIMEMS     20      /* 40ms <=> 25 fps */
  44.  
  45. #define NBLURS 15       /* no of motion-blur frames */
  46. /* Quaternion for global orientation */
  47. quat_t orquat;
  48.  
  49. GLfloat dist=5;
  50. GLfloat geomx=0,geomy=0;
  51.  
  52. /************** Globals for mouse state **************/
  53.  
  54. /* SDL button values for mouse wheel motion */
  55. #define WHEELUP 4
  56. #define WHEELDOWN 5
  57.  
  58. int mousex=0,mousey=0;          /* Mouse status */
  59. int leftbutdown=0;
  60. int rightbutdown=0;
  61. int midbutdown=0;
  62. int bx=0,by=0;
  63.  
  64. /*********** Quaternion stuff ****************/
  65.  
  66. /* Turn a quaternion into a matrix */
  67.  
  68. void quatmatrix(quat_t q,GLfloat *m )
  69. {
  70.         GLfloat w,x,y,z;
  71.  
  72.         w = q.q0; x = q.q1; y=q.q2; z=q.q3;
  73.  
  74.         m[ 0] = 1 - 2*y*y - 2*z*z;
  75.         m[ 1] = 2*x*y + 2*w*z;
  76.         m[ 2] = 2*x*z - 2*w*y;
  77.         m[ 3] = 0;
  78.  
  79.         m[ 4] = 2*x*y - 2*w*z;
  80.         m[ 5] = 1 - 2*x*x - 2*z*z;
  81.         m[ 6] = 2*y*z + 2*w*x;
  82.         m[ 7] = 0;
  83.  
  84.         m[ 8] = 2*x*z + 2*w*y;
  85.         m[ 9] = 2*y*z - 2*w*x;
  86.         m[10] = 1 - 2*x*x - 2*y*y;
  87.         m[11] = 0;
  88.  
  89.         m[12] = 0;
  90.         m[13] = 0;
  91.         m[14] = 0;
  92.         m[15] = 1;
  93.  
  94.         return;
  95.  
  96. }
  97.  
  98. /* Construct the quaternion corresponding to a right-handed rotation of
  99.  * theta radians about the given vector.
  100.  */
  101.  
  102. quat_t quatrotation(GLfloat theta, GLfloat x, GLfloat y, GLfloat z)
  103. {
  104.         GLfloat st,ct;
  105.         quat_t q;
  106.  
  107.         st = sin(0.5*theta);
  108.         ct = cos(0.5*theta);
  109.  
  110.         q.q0 = ct;
  111.         q.q1 = x*st;  
  112.         q.q2 = y*st;  
  113.         q.q3 = z*st;  
  114.         return q;
  115. }
  116. /*
  117.  * Return the quaternion product of two quaternions.
  118.  *
  119.  * ( a0, a ) ( b0, b) =  ( a0*b0 - a.b , a0*a + b0*b + a x b )
  120.  *
  121.  */
  122.  
  123. quat_t quatmultiply(quat_t a, quat_t b)
  124. {
  125.         quat_t q;
  126.  
  127.         q.q0 = a.q0 * b.q0
  128.                 - a.q1*b.q1
  129.                 - a.q2*b.q2
  130.                 - a.q3*b.q3;
  131.        
  132.         q.q1 =    a.q0 * b.q1
  133.                 + b.q0 * a.q1
  134.                 + a.q2 * b.q3 - a.q3 * b.q2;
  135.  
  136.         q.q2 =    a.q0 * b.q2
  137.                 + b.q0 * a.q2
  138.                 + a.q3 * b.q1 - a.q1 * b.q3;
  139.  
  140.         q.q3 =    a.q0 * b.q3
  141.                 + b.q0 * a.q3
  142.                 + a.q1 * b.q2 - a.q2 * b.q1;
  143.         return q;
  144. }
  145.  
  146.  
  147. /******************** SDL utility boilerplate *************/
  148.  
  149. /* Called to resize the screen to given dimensions.
  150.  * Returns 0 on success, nonzero on failure.
  151.  */
  152.  
  153. int vidresize(int w, int h) {
  154.         SDL_Surface *newscreen=NULL;
  155.  
  156.         if (NULL==(newscreen=SDL_SetVideoMode(
  157.                 w,h,32,
  158.                 SDL_OPENGL|SDL_RESIZABLE))) {
  159.                 fprintf(stderr, "SDL_SetVideoMode() failed\n");
  160.                 return -1;
  161.         } else {
  162.                 screen=newscreen;
  163.                 screenx = w;
  164.                 screeny = h;
  165.  
  166.                 screenrect.x=screenrect.y=0;
  167.                 screenrect.w=w;
  168.                 screenrect.h=h;
  169.  
  170.                 if (glinit) {
  171.                         glViewport(0,0,screenx,screeny);
  172.                 }
  173.  
  174.                 if (screenx>screeny) {
  175.                         sphererad=0.5*screeny;
  176.                 } else {
  177.                         sphererad=0.5*screenx;
  178.                 }
  179.         }
  180.         return 0;
  181. }
  182.  
  183. /********************* Main code *********************/
  184.  
  185.  
  186. /* Called to initialise GL (as opposed to SDL's GL interface).
  187.  * Must only be called once the SDL video subsystem has been set up.
  188.  */
  189.  
  190. void init_gl()
  191. {
  192.         GLfloat ambientlight[] = { 0.5,0.5,0.5};
  193.         GLfloat diffuselight[] = { 0.5,0.5,0.5};
  194.  
  195.         glViewport(0,0,screenx,screeny);
  196.  
  197.         glShadeModel(GL_SMOOTH);
  198.  
  199.         glClearColor(0.0,0.5,0.7,0.0);
  200.         glClearDepth(1.0);
  201.  
  202.         glLightfv(GL_LIGHT1,GL_AMBIENT,ambientlight);
  203.         glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuselight);
  204.         glEnable(GL_LIGHT1);
  205.         glEnable(GL_LIGHTING);
  206.  
  207.         glDepthFunc(GL_LESS);
  208.         glDepthMask(GL_TRUE);
  209.         glEnable(GL_DEPTH_TEST);
  210.  
  211.         glCullFace(GL_BACK);
  212.         glEnable(GL_CULL_FACE);
  213.  
  214.         glEnable(GL_BLEND);
  215.         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  216.  
  217.  
  218.         glEnable(GL_POLYGON_OFFSET_FILL);
  219.  
  220.         glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
  221.         glEnable(GL_COLOR_MATERIAL);
  222.  
  223.         glPolygonOffset(1.0,1.0);
  224.         glEnable(GL_POLYGON_OFFSET_FILL);
  225.  
  226.         glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
  227.         glEnable(GL_LINE_SMOOTH);
  228.  
  229.         glLineWidth(3.0);
  230.  
  231.         glinit=1;
  232. }
  233.  
  234.  
  235. void draw_gl()
  236. {
  237.  
  238.         GLfloat m[16];
  239.  
  240.         /* Set for perspective projection */
  241.  
  242.         glMatrixMode(GL_PROJECTION);
  243.         glLoadIdentity();
  244.         gluPerspective(60.0,(float)screenx/(float)screeny,nearclip,1024.0 );
  245.         glMatrixMode(GL_MODELVIEW);
  246.  
  247.         glDepthMask(GL_TRUE);
  248.         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  249.  
  250.         /* Position and orient geometry */
  251.         glLoadIdentity();
  252.         glTranslatef(geomx,geomy,-dist);
  253.         quatmatrix(orquat,m);
  254.         glMultMatrixf(m);
  255.  
  256.         glEnable(GL_LIGHTING);
  257.         glColor4f(0.5,0.5,0.5,1.0);
  258.         glutSolidCube(1.0);
  259.         glColor4f(0.0,0.0,1.0,1.0);
  260.         glutWireCube(1.0);
  261.  
  262.         /* Set modelview and projection matrices to unity */
  263.  
  264.         glMatrixMode(GL_PROJECTION);
  265.         glLoadIdentity();
  266.         glMatrixMode(GL_MODELVIEW);
  267.         glLoadIdentity();
  268.  
  269.         /* Be green. */
  270.  
  271.         glColor3f(0,1,0);
  272.  
  273.         /* Turn off lighting since we don't want it to affect the HUD */
  274.  
  275.         glDisable(GL_LIGHTING);
  276.  
  277.         /* turn off depth test so that th HUD is unaffected by the 3d stuff */
  278.  
  279.         glDisable(GL_DEPTH_TEST);
  280.  
  281.         /* Draw a 2d square. */
  282.         glBegin(GL_LINE_STRIP);
  283.                 glVertex2f(-0.5, 0.5);
  284.                 glVertex2f( 0.5, 0.5);
  285.                 glVertex2f( 0.5,-0.5);
  286.                 glVertex2f(-0.5,-0.5);
  287.                 glVertex2f(-0.5, 0.5);
  288.         glEnd();
  289.  
  290.         /* Turn lighting back on */
  291.         glEnable(GL_LIGHTING);
  292.  
  293.         /* Turn depth test back on */
  294.         glEnable(GL_DEPTH_TEST);
  295.  
  296.  
  297.         return ;
  298. }
  299.  
  300.  
  301. /* Process mouse motion from x0,y0 to x1,y1 */
  302.  
  303. void mouserotatemotion(int x0,int y0, int x1,int y1) {
  304.  
  305.         GLfloat mx,my,m,s;
  306.         GLfloat theta;
  307.         quat_t rotquat;
  308.  
  309.         s = sphererad;
  310.         my = (GLfloat)(x1-x0);
  311.         mx = (GLfloat)(y1-y0);
  312.         m=sqrt(mx*mx+my*my);
  313.  
  314.         if ((m>0) && (m<s)) {
  315.                 theta = m/s;
  316.  
  317.                 mx /= m;
  318.                 my /= m;
  319.  
  320.                 rotquat = quatrotation(theta,mx,my,0.0);
  321.                 orquat = quatmultiply(rotquat,orquat);
  322.         }
  323.  
  324. }
  325.  
  326. void mousezoommotion(int dz)
  327. {
  328.         const GLfloat zoomscale=0.02;
  329.         dist+=zoomscale*dz;
  330.         return;
  331. }
  332.  
  333. void mousetransmotion(int dx,int dy)
  334. {
  335.         const GLfloat transscale=0.02;
  336.         geomx+=transscale*dx;
  337.         geomy-=transscale*dy; /* GL uses left-handed coordinates */
  338.         return;
  339. }
  340.  
  341.  
  342. /* Clear up and quit. */
  343. void quit_all() {
  344.  
  345.         SDL_ShowCursor(SDL_ENABLE);
  346.         exit(0);
  347. }
  348.  
  349.  
  350.  
  351. int main(int argc, char *argv[])
  352. {
  353.         SDL_Event event;
  354.         screenx=500;
  355.         screeny=500;
  356.  
  357.         /* Initialize SDL */
  358.  
  359.         if ( 0 > SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)) {
  360.                 fprintf(stderr,"main: SDL_Init() failed\n");
  361.                 return -1;
  362.         }
  363.  
  364.         SDL_EnableUNICODE(1);
  365.  
  366.         /* Set GL options: >=15-bit colour, 16-bit Z, double-buffered. */
  367.  
  368.         SDL_GL_SetAttribute(SDL_GL_RED_SIZE,5);
  369.         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,5);
  370.         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,5);
  371.         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16);
  372.         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
  373.  
  374.         /* Make us a window at 32bpp */
  375.  
  376.  
  377.         vidresize(screenx,screeny);
  378.  
  379.         SDL_WM_SetCaption("GL/SDL",NULL);
  380.  
  381.         /* Initialize GL */
  382.  
  383.         init_gl();
  384.         orquat = quatrotation(0.0,0.0,0.0,1.0);
  385.  
  386.         /* Main loop */
  387.  
  388.         while(1) {
  389.                 timetop=SDL_GetTicks();
  390.  
  391.                 /* Render frame to screen */
  392.                 draw_gl();
  393.                 SDL_GL_SwapBuffers();
  394.  
  395.  
  396.  
  397.                 /* Poll for events */
  398.                 if (SDL_WaitEvent(&event)) {
  399.                         unsigned char asciival;
  400.                         switch(event.type) {
  401.                                
  402.                                 case SDL_KEYUP:
  403.                                 case SDL_QUIT:
  404.                                         SDL_ShowCursor(SDL_ENABLE);
  405.                                         return 0;
  406.                                         break;
  407.                                 case SDL_MOUSEBUTTONDOWN:
  408.                                         switch(event.button.button) {
  409.                                                 case SDL_BUTTON_LEFT:
  410.                                                 leftbutdown=1;
  411.                                                 bx=event.button.x;
  412.                                                 by=event.button.y;
  413.                                                 SDL_ShowCursor(SDL_DISABLE);
  414.                                                 break;
  415.                                                 case SDL_BUTTON_RIGHT:
  416.                                                 rightbutdown=1;
  417.                                                 bx=event.button.x;
  418.                                                 by=event.button.y;
  419.                                                 SDL_ShowCursor(SDL_DISABLE);
  420.                                                 break;
  421.                                                 case SDL_BUTTON_MIDDLE:
  422.                                                 midbutdown=1;
  423.                                                 bx=event.button.x;
  424.                                                 by=event.button.y;
  425.                                                 SDL_ShowCursor(SDL_DISABLE);
  426.                                                 break;
  427.                                                 case WHEELDOWN:
  428.                                                 dist+=1.0;
  429.                                                 break;
  430.                                                 case WHEELUP:
  431.                                                 dist-=1.0;
  432.                                                 break;
  433.                                                 default:
  434.                                                 break;
  435.                                         }
  436.                                         break;
  437.                                 case SDL_MOUSEBUTTONUP:
  438.                                         switch(event.button.button) {
  439.                                                 case SDL_BUTTON_LEFT:
  440.                                                  leftbutdown=0;
  441.                                                  if (!leftbutdown &&
  442.                                                         !midbutdown) {
  443.                                                   SDL_ShowCursor(SDL_ENABLE);
  444.                                                  }
  445.                                                 break;
  446.                                                 case SDL_BUTTON_RIGHT:
  447.                                                  rightbutdown=0;
  448.                                                  if (!leftbutdown &&
  449.                                                         !midbutdown) {
  450.                                                   SDL_ShowCursor(SDL_ENABLE);
  451.                                                  }
  452.                                                 break;
  453.                                                 case SDL_BUTTON_MIDDLE:
  454.                                                  midbutdown=0;
  455.                                                  if (!leftbutdown &&
  456.                                                         !rightbutdown) {
  457.                                                   SDL_ShowCursor(SDL_ENABLE);
  458.                                                  }
  459.                                                 break;
  460.                                                 default:
  461.                                                 break;
  462.                                         }
  463.                                         break;
  464.                                 case SDL_MOUSEMOTION:
  465.                                         mousex = event.motion.x;
  466.                                         mousey = event.motion.y;
  467.                                         if ((0!=event.motion.xrel) ||
  468.                                                 (0!=event.motion.yrel)) {
  469.                                                 if (leftbutdown) {
  470.                                                 mouserotatemotion(bx,by,
  471.                                                         mousex,mousey);
  472.                                                         SDL_WarpMouse(bx,by);
  473.                                                         mousex=bx; mousey=by;
  474.                                                 } else if (rightbutdown) {
  475.                                                 mousezoommotion(
  476.                                                         event.motion.y-by);
  477.                                                         SDL_WarpMouse(bx,by);
  478.                                                         mousex=bx; mousey=by;
  479.                                                 } else if (midbutdown) {
  480.                                                 mousetransmotion(
  481.                                                         event.motion.x-bx,
  482.                                                         event.motion.y-by);
  483.                                                         SDL_WarpMouse(bx,by);
  484.                                                         mousex=bx; mousey=by;
  485.                                                 }
  486.                                         }
  487.                                         break;
  488.  
  489.                                 case SDL_VIDEORESIZE:
  490.                                         vidresize(      event.resize.w,
  491.                                                         event.resize.h);
  492.                                         break;
  493.                         } /* switch(event.type) */
  494.                 } /* if (WaitEvent()) */
  495.  
  496.                 timebot=SDL_GetTicks();
  497.  
  498.                 frameno++;
  499.         }
  500.         return 0;
  501. }

Raw Paste


Login or Register to edit or fork this paste. It's free.