home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl1 / demos / shadow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  15.0 KB  |  541 lines

  1. /*
  2.  * Copyright 1994, 1996, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /*
  19.  *    shadow.c -   OpenGL example drawing a shadowed cube
  20.  *
  21.  *    Escape Key        - exit the program
  22.  *
  23.  *    r Key            - toggle cube rotation
  24.  *    f Key            - toggle filled/outlined
  25.  *    s Key            - toggle parallel/perspective shadow/light
  26.  *    l Key            - toggle lighting
  27.  *
  28.  *    Left/Right Arrow Key      - move light
  29.  *      Up/Down Arrow Key      - move light
  30.  *
  31.  *    Left Mousebutton, down    - start moving the eye
  32.  *    Left Mousebutton, up      - stop moving the eye
  33.  *    Mouse pointer location    - position eye
  34.  */
  35.  
  36. #include <Xm/Xm.h>
  37. #include <Xm/AtomMgr.h>        /* for WMProtocol */
  38. #include <Xm/Protocols.h>
  39.  
  40. #include <X11/keysym.h>
  41.  
  42. #include <GL/GLwMDrawA.h>        /* for Mixed Model OpenGL */
  43. #include <GL/gl.h>
  44. #include <GL/glu.h>
  45. #include <GL/glx.h>
  46.  
  47. /*  Function Prototypes  */
  48.  
  49. void    initCB  (Widget w, XtPointer client_data, GLwDrawingAreaCallbackStruct *call_data);
  50. void    exposeCB(Widget w, XtPointer dummy0, XtPointer dummy1);
  51. void    resizeCB(Widget w, XtPointer dummy0, GLwDrawingAreaCallbackStruct *call_data);
  52. void    inputCB (Widget w, Display *display, GLwDrawingAreaCallbackStruct *call_data);
  53.  
  54. GLvoid  drawScene( GLvoid );
  55.  
  56. /* Global Variables */
  57.  
  58. static XtAppContext app_context;
  59. static GLXContext glx_context;
  60. static Display *display;
  61. static Window   window;
  62. static XtWorkProcId wpid;
  63.  
  64. static GLboolean    b1_pressed = GL_FALSE;
  65.  
  66. GLint       xStart, yStart;
  67. GLfloat      rotationX, rotationY;
  68.  
  69. static int useLighting = 1;
  70. static int doFilled = 1;
  71. static int doRotation = 1;
  72. static int shadowType = 1;
  73.  
  74. #define GREY    0
  75. #define RED    1
  76. #define GREEN    2
  77. #define BLUE    3
  78. #define CYAN    4
  79. #define MAGENTA    5
  80. #define YELLOW    6
  81. #define BLACK    7
  82.  
  83. static float materialColor[8][4] = {
  84.     { 0.8, 0.8, 0.8, 1.0 },
  85.     { 0.8, 0.0, 0.0, 1.0 },
  86.     { 0.0, 0.8, 0.0, 1.0 },
  87.     { 0.0, 0.0, 0.8, 1.0 },
  88.     { 0.0, 0.8, 0.8, 1.0 },
  89.     { 0.8, 0.0, 0.8, 1.0 },
  90.     { 0.8, 0.8, 0.0, 1.0 },
  91.     { 0.0, 0.0, 0.0, 0.4 },
  92. };
  93.  
  94. static float shadowPos[4] = { 0.0, 1.2, 0.0, 1.0 };
  95. static float lightAmb[4]  = { 0.2, 0.2, 0.2, 1.0 };
  96. static float lightDiff[4] = { 0.8, 0.8, 0.8, 1.0 };
  97. static float lightSpec[4] = { 0.4, 0.4, 0.4, 1.0 };
  98.  
  99. static float groundPlane[4] = { 0.0, 1.0, 0.0, 0.0 };
  100.  
  101. static unsigned char shadowPattern[128] = {
  102.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  103.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  104.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  105.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  106.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  107.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  108.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  109.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  110.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  111.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  112.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  113.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  114.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  115.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  116.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
  117.     0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xd
  118. };
  119.  
  120. static float cube_vertexes[6][4][3] = {
  121.     { { -0.3,  0.3, -0.3 },
  122.       { -0.3,  0.0, -0.3 },
  123.       { -0.3,  0.0,  0.3 },
  124.       { -0.3,  0.3,  0.3 } },
  125.  
  126.     { {  0.3,  0.3, -0.3 },
  127.       {  0.3,  0.3,  0.3 },
  128.       {  0.3,  0.0,  0.3 },
  129.       {  0.3,  0.0, -0.3 } },
  130.  
  131.     { {  0.3,  0.0, -0.3 },
  132.       { -0.3,  0.0, -0.3 },
  133.       { -0.3,  0.3, -0.3 },
  134.       {  0.3,  0.3, -0.3 } },
  135.  
  136.     { {  0.3,  0.0,  0.3 },
  137.       {  0.3,  0.3,  0.3 },
  138.       { -0.3,  0.3,  0.3 },
  139.       { -0.3,  0.0,  0.3 } },
  140.  
  141.     { { -0.3,  0.0,  0.3 },
  142.       { -0.3,  0.0, -0.3 },
  143.       {  0.3,  0.0, -0.3 },
  144.       {  0.3,  0.0,  0.3 } },
  145.  
  146.     { {  0.3,  0.3, -0.3 },
  147.       { -0.3,  0.3, -0.3 },
  148.       { -0.3,  0.3,  0.3 },
  149.       {  0.3,  0.3,  0.3 } }
  150. };
  151.  
  152. static float cube_normals[6][3] = {
  153.     { -1.0,  0.0,  0.0 },
  154.     {  1.0,  0.0,  0.0 },
  155.     {  0.0,  0.0, -1.0 },
  156.     {  0.0,  0.0,  1.0 },
  157.     {  0.0, -1.0,  0.0 },
  158.     {  0.0,  1.0,  0.0 }
  159. };
  160.  
  161. void
  162. main(int argc, char *argv[])
  163. {
  164.     Atom WM_DELETE_WINDOW;
  165.     Widget glw, toplevel;
  166.  
  167.     static String fallback_resources[] =
  168.     {
  169.         "*title:    shadow: controlled by 'r' 's' 'f' 'l' and arrow keys", 
  170.         "*geometry: +100+100", 
  171.         "*glwidget*width:  600",
  172.         "*glwidget*height: 384",
  173.         "*glwidget*rgba:        TRUE",
  174.         "*glwidget*doublebuffer:  TRUE",
  175.         
  176.         "*sgiMode: true",           /* try to enable IRIX 5.2+ look & feel */
  177.         "*useSchemes: all",         /* and SGI schemes */
  178.         
  179.         NULL
  180.     };
  181.     
  182.     toplevel = XtVaAppInitialize(
  183.         &app_context,          /* Application context */
  184.         "OGLTemplates",          /* Application class */
  185.         NULL, 0,              /* command line option list */
  186.         &argc, argv,          /* command line args */
  187.         fallback_resources,
  188.         NULL);              /* end of argument list */
  189.  
  190.     glw = XtCreateManagedWidget("glwidget", glwMDrawingAreaWidgetClass, toplevel, NULL, 0);
  191.     
  192.     XtAddCallback(glw, GLwNginitCallback, (XtCallbackProc)initCB, NULL);
  193.     XtAddCallback(glw, GLwNexposeCallback, (XtCallbackProc)exposeCB, NULL);
  194.     XtAddCallback(glw, GLwNresizeCallback, (XtCallbackProc)resizeCB, NULL);
  195.     XtAddCallback(glw, GLwNinputCallback,  (XtCallbackProc)inputCB, (XtPointer)XtDisplay(toplevel));
  196.  
  197.     WM_DELETE_WINDOW = XmInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False);
  198.     XmAddWMProtocolCallback(toplevel, WM_DELETE_WINDOW, (XtCallbackProc)inputCB, (XtPointer)XtDisplay(toplevel));
  199.  
  200.  
  201.     XtRealizeWidget(toplevel);    /* instantiate it now */
  202.     XtAppMainLoop(app_context);    /* loop for events */
  203. }
  204.  
  205. /*           
  206.  *      initCB
  207.  *
  208.  *  The initCB subroutine initializes graphics modes and
  209.  *  transformation matrices.
  210.  */ 
  211.  
  212. void
  213. initCB(Widget w, XtPointer d0, GLwDrawingAreaCallbackStruct *call_data)
  214. {
  215.     GLfloat aspect;
  216.     Arg args[1];
  217.     XVisualInfo *vi;
  218.     
  219.     window  = XtWindow(w);
  220.     display = XtDisplay(w);
  221.  
  222.     XtSetArg(args[0], GLwNvisualInfo, &vi);
  223.     XtGetValues(w, args, 1);
  224.     
  225.     glx_context = glXCreateContext(XtDisplay(w), vi, 0, GL_TRUE);
  226.     GLwDrawingAreaMakeCurrent(w, glx_context);
  227.  
  228.     glClearColor( 0.0, 0.0, 0.0, 1.0 );
  229.     
  230.     glMatrixMode( GL_PROJECTION );
  231.         aspect = (GLfloat) call_data->width / call_data->height;
  232.         gluPerspective( 50.0, aspect, 1.0, 70.0 );
  233.     glMatrixMode( GL_MODELVIEW );
  234.     
  235.     glTranslatef(0.0, 0.0, -4.0);
  236.     glRotatef(45.0, 1.0, 0.0, 0.0);
  237.  
  238.     glEnable(GL_LIGHTING);
  239.     glEnable(GL_LIGHT0);
  240.     glLightfv(GL_LIGHT0, GL_POSITION, shadowPos);
  241.     glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
  242.     glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff);
  243.     glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpec);
  244.  
  245.     glPolygonStipple((const GLubyte *)shadowPattern);
  246.     glPointSize(4.0);
  247.     
  248.     wpid = XtAppAddWorkProc(app_context, (XtWorkProc)drawScene, NULL);
  249. }
  250.  
  251.  
  252. /*  exposeCB() and resizeCB() are called when the window
  253.  *  is uncovered, moved, or resized.
  254.  */
  255.  
  256. void
  257. exposeCB(Widget w, XtPointer d0, XtPointer d1)
  258. {
  259.     GLwDrawingAreaMakeCurrent(w, glx_context);
  260.     drawScene();
  261. }
  262.  
  263. void
  264. resizeCB(Widget w, XtPointer d0, GLwDrawingAreaCallbackStruct *call_data)
  265. {
  266.     GLfloat     aspect;
  267.     
  268.     glViewport(0,  0, (GLuint) call_data->width, (GLuint) call_data->height);
  269.     
  270.     aspect = (GLfloat)  call_data->width /  call_data->height;
  271.     
  272.     glMatrixMode( GL_PROJECTION );
  273.         glLoadIdentity();
  274.         gluPerspective( 50.0, aspect, 1.0, 70.0 );
  275.     glMatrixMode( GL_MODELVIEW );
  276. }
  277.  
  278. void
  279. inputCB(Widget w, Display *display, GLwDrawingAreaCallbackStruct *call_data)
  280. {
  281.     char            buf[2];
  282.     KeySym          keysym;
  283.     int             rc;
  284.     
  285.     GLboolean     do_exit = GL_FALSE;
  286.     
  287.     switch(call_data->reason)
  288.     {
  289.         case 6666:    do_exit = GL_TRUE; break;
  290.         case GLwCR_INPUT:
  291.       switch(call_data->event->type)
  292.       {
  293.           case KeyPress:
  294.             XLookupString((XKeyEvent *) call_data->event, buf, 2, &keysym, NULL);
  295.             switch (keysym)
  296.             {
  297.               case XK_Escape:
  298.                 do_exit = GL_TRUE;
  299.                 break;
  300.               case XK_L: case XK_l:
  301.                 useLighting = !useLighting;
  302.                 useLighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING);
  303.                 break;
  304.               case XK_F: case XK_f:
  305.                 doFilled = !doFilled;
  306.                 break;
  307.               case XK_R: case XK_r:
  308.                 doRotation = !doRotation;
  309.                 if (doRotation)
  310.               wpid = XtAppAddWorkProc(app_context, (XtWorkProc)drawScene, NULL);
  311.                 else
  312.                 {
  313.               XtRemoveWorkProc(wpid);
  314.               wpid = NULL;
  315.                 }
  316.                 break;
  317.               case XK_S: case XK_s:
  318.                 shadowType = !shadowType;
  319.                 if (shadowType) shadowPos[3] = 1.0;
  320.                 else        shadowPos[3] = 0.0;
  321.                 break;
  322.               case XK_Left:
  323.                 shadowPos[0]-=.1;
  324.                 break;
  325.               case XK_Right:
  326.                 shadowPos[0]+=.1;
  327.                 break;
  328.               case XK_Up:
  329.                 shadowPos[1]+=.1;
  330.                 break;
  331.               case XK_Down:
  332.                 shadowPos[1]-=.1;
  333.                 break;
  334.             }
  335.         break;
  336.         
  337.           case ButtonPress:
  338.         if (((XButtonEvent *)call_data->event)->button == 1)
  339.         {
  340.             b1_pressed = GL_TRUE;
  341.             xStart = ((XButtonEvent *)call_data->event)->x_root;
  342.             yStart = ((XButtonEvent *)call_data->event)->y_root;
  343.         }
  344.         break;
  345.         
  346.           case ButtonRelease:
  347.         if (((XButtonEvent *)call_data->event)->button == 1)
  348.             b1_pressed = GL_FALSE;
  349.         break;
  350.         
  351.           case MotionNotify:
  352.         {
  353.             GLint     xPos, yPos;
  354.             GLint     xOffset, yOffset;
  355.             
  356.             if (! b1_pressed) break;
  357.             
  358.             xPos = ((XMotionEvent *)call_data->event)->x_root;
  359.             yPos = ((XMotionEvent *)call_data->event)->y_root;
  360.             
  361.             /* Using the stored and current mouse positions, compute how far
  362.              * the mouse moved */
  363.             xOffset = xPos - xStart;
  364.             yOffset = yPos - yStart;
  365.             
  366.             /* Adjust the eye position based on the mouse position */
  367.             rotationY += xOffset;
  368.             rotationX += yOffset;
  369.             
  370.             /* Update the stored mouse position for later use */
  371.             xStart = xPos;
  372.             yStart = yPos;
  373.         }
  374.         break;
  375.       }
  376.       break;
  377.         
  378.         default:
  379.       printf("inputCB: reason: %d event->type: %d\n", call_data->reason, call_data->event->type);
  380.       break;  
  381.     }
  382.         
  383.     if (do_exit)
  384.     {
  385.         XtCloseDisplay(display);
  386.         exit(0);
  387.     }
  388.             
  389.     if (!doRotation && (XPending(display) == 0))    drawScene();
  390. }
  391.  
  392. static void
  393. drawCube()
  394. {
  395.     int i;
  396.  
  397.     glBegin(GL_QUADS);
  398.     for (i = 0; i < 6; ++i)
  399.     {
  400.         glNormal3fv(&cube_normals[i][0]);
  401.         glVertex3fv(&cube_vertexes[i][0][0]);
  402.         glVertex3fv(&cube_vertexes[i][1][0]);
  403.         glVertex3fv(&cube_vertexes[i][2][0]);
  404.         glVertex3fv(&cube_vertexes[i][3][0]);
  405.     }
  406.     glEnd();
  407. }
  408.  
  409. static void
  410. myShadowMatrix(float ground[4], float light[4])
  411. {
  412.     int i, j;
  413.     float  dot;
  414.     float  shadowMat[4][4];
  415.  
  416.     dot = ground[0] * light[0] +
  417.           ground[1] * light[1] +
  418.           ground[2] * light[2] +
  419.           ground[3] * light[3];
  420.  
  421.         // fp exceptions may occur whenever the light comes
  422.         // (nearly) directly in an 90 degree angle (compared to the)
  423.         // ground normal. In reality there's no shadow when the sun
  424.         // (or any light) goes down...
  425.  
  426.         // lighting should be turned off, as the shadow itself is not
  427.         // lighted at all (this will avoid fp exceptions)
  428.     
  429.     shadowMat[0][0] = dot - light[0] * ground[0];
  430.     shadowMat[1][0] = 0.0 - light[0] * ground[1];
  431.     shadowMat[2][0] = 0.0 - light[0] * ground[2];
  432.     shadowMat[3][0] = 0.0 - light[0] * ground[3];
  433.     
  434.     shadowMat[0][1] = 0.0 - light[1] * ground[0];
  435.     shadowMat[1][1] = dot - light[1] * ground[1];
  436.     shadowMat[2][1] = 0.0 - light[1] * ground[2];
  437.     shadowMat[3][1] = 0.0 - light[1] * ground[3];
  438.     
  439.     shadowMat[0][2] = 0.0 - light[2] * ground[0];
  440.     shadowMat[1][2] = 0.0 - light[2] * ground[1];
  441.     shadowMat[2][2] = dot - light[2] * ground[2];
  442.     shadowMat[3][2] = 0.0 - light[2] * ground[3];
  443.     
  444.     shadowMat[0][3] = 0.0 - light[3] * ground[0];
  445.     shadowMat[1][3] = 0.0 - light[3] * ground[1];
  446.     shadowMat[2][3] = 0.0 - light[3] * ground[2];
  447.     shadowMat[3][3] = dot - light[3] * ground[3];
  448.  
  449.     glMultMatrixf((const GLfloat*)shadowMat);
  450.     
  451. /*  for (i=0; i<4; i++)
  452.         printf("%5.3f %5.3f %5.3f %5.3f\n", shadowMat[i][0], shadowMat[i][1], shadowMat[i][2], shadowMat[i][3]); 
  453.     printf("\n\n");
  454. */
  455. }
  456.  
  457. GLvoid
  458. drawScene( GLvoid )
  459. {
  460.     static GLfloat rotCube;
  461.     static GLfloat cubeXform[4][4];
  462.     
  463.     glClear( GL_COLOR_BUFFER_BIT );
  464.     
  465.     glDisable(GL_CULL_FACE);
  466.     glPolygonMode(GL_FRONT, GL_FILL);
  467.     glPolygonMode(GL_BACK, GL_LINE);
  468.     
  469.     glPushMatrix();
  470.         glRotatef(rotationX, 1.0, 0.0, 0.0);
  471.         glRotatef(rotationY, 0.0, 1.0, 0.0);
  472.         
  473.         glLightfv(GL_LIGHT0, GL_POSITION, shadowPos);
  474.     
  475.         if (useLighting)
  476.         {
  477.       glNormal3fv(groundPlane);
  478.       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &materialColor[BLUE][0]);
  479.         }
  480.         else    glColor4fv(&materialColor[BLUE][0]);
  481.  
  482.         glBegin(GL_QUADS);
  483.       glVertex3f( 2.0, 0.0,-2.0);
  484.       glVertex3f(-2.0, 0.0,-2.0);
  485.       glVertex3f(-2.0, 0.0, 2.0);
  486.       glVertex3f( 2.0, 0.0, 2.0);
  487.         glEnd();
  488.         
  489.         glDisable(GL_LIGHTING);    // shadow itself is not lighted
  490.         
  491.         if (doRotation)        // of cube
  492.         { 
  493.       glPushMatrix();
  494.           glLoadIdentity();
  495.           rotCube += 5; if (rotCube >= 360.0) rotCube = 0.0;
  496.           glRotatef(rotCube, 0, 1, 0);
  497.           glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)cubeXform);
  498.       glPopMatrix();
  499.         }
  500.         
  501.         if (doFilled)
  502.         {
  503.       glEnable(GL_POLYGON_STIPPLE);
  504.       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  505.         }
  506.         else  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  507.         
  508.         glPushMatrix();
  509.       myShadowMatrix(groundPlane, shadowPos);
  510.       glMultMatrixf((const GLfloat *) cubeXform);
  511.         
  512.       glColor3f(0.0, 0.0, 0.0);
  513.       drawCube();        // draw ground shadow
  514.         glPopMatrix();
  515.         
  516.         if (shadowPos[3] != 0.0)
  517.         {
  518.       glColor3f(1.0, 1.0, 1.0);    // draw pointlight
  519.       glBegin(GL_POINTS);
  520.           glVertex3fv(shadowPos);
  521.       glEnd();
  522.         }
  523.         
  524.         glEnable(GL_CULL_FACE);
  525.         glDisable(GL_POLYGON_STIPPLE);
  526.         if (useLighting) glEnable(GL_LIGHTING);
  527.         
  528.         glPushMatrix();
  529.       glMultMatrixf((const GLfloat *) cubeXform);
  530.  
  531.       if (useLighting)      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &materialColor[RED][0]);
  532.       else          glColor4fv(&materialColor[RED][0]);
  533.  
  534.       drawCube();        // draw cube
  535.         glPopMatrix();
  536.     
  537.     glPopMatrix();
  538.     
  539.     glXSwapBuffers(display, window);    // or GLwDrawingAreaSwapBuffers(glwidget)
  540. }
  541.