예제 #1
0
static void
drawModel(void)
{
  switch(currentModel) {
  case MOD_DINO:
    drawDinosaur();
    break;
  case MOD_SPHERE:
    glMaterialfv(GL_FRONT, GL_DIFFUSE, blueMaterial);
    glutSolidSphere(6.0, 15, 15);
    break;
  case MOD_CUBE:
    glMaterialfv(GL_FRONT, GL_DIFFUSE, redMaterial);
    glutSolidCube(6.0);
    break;
  case MOD_ICO:
    glMaterialfv(GL_FRONT, GL_DIFFUSE, purpleMaterial);
    glPushMatrix();
      glEnable(GL_NORMALIZE);
      glScalef(7.0, 7.0, 7.0);
      glutSolidIcosahedron();
      glDisable(GL_NORMALIZE);
    glPopMatrix();
    break;
  }
}
예제 #2
0
void
logs(void) {
    static GLUquadricObj *quadric;

    if (!quadric) {
	quadric = gluNewQuadric();
	glNewList(100, GL_COMPILE);
	gluQuadricOrientation(quadric, GLU_OUTSIDE);
	glTranslatef(0.f, 0.f, -2.f);
	gluCylinder(quadric, .5, .5, 4., 5, 1);
	glTranslatef(0.f, 0.f, 4.f);
	gluDisk(quadric, 0., .5, 10, 1);
	glTranslatef(0.f, 0.f, -4.f);
	gluQuadricOrientation(quadric, GLU_INSIDE);
	gluDisk(quadric, 0., .5, 10, 1);
	glEndList();
    }
    glPushMatrix();
    glTranslatef(0.f, -.5f, 0.f);
    glColor3f(.55f, .14f, .14f);
    glPushMatrix();
    glRotatef(55., 0., 1., 0.);
    glCallList(100);
    glPopMatrix();
    glPushMatrix();
    glRotatef(-55., 0., 1., 0.);
    glCallList(100);
    glPopMatrix();
    if (marshmallow) {
	glPushMatrix();
	glColor4f(1.f, 1.f, 1.f, 1.f);
	glTranslatef(0.f, 1.7f, 0.f);
	glRotatef(45.f, 0.f, 0.f, 1.f);
	glRotatef(90.f, 0.f, 1.f, 0.f);
	glScalef(1., 1., .25f);
	glCallList(100);
	glPopMatrix();

	glPushMatrix();
	glColor4f(.1f, .1f, .1f, 1.f);
	glTranslatef(1.5f, 3.4f, 0.f);
	glRotatef(45.f, 0.f, 0.f, 1.f);
	glRotatef(90.f, 0.f, 1.f, 0.f);
	glScalef(.2f, .2f, 1.f);
	glCallList(100);
	glPopMatrix();

	if (marshmallow == 2) {
	    extern void drawDinosaur(void);
	    glDisable(GL_COLOR_MATERIAL);
	    glPushMatrix();
	    glTranslatef(10.f, 0.f, 0.f);
	    glRotatef(180.f, 0.f, 1.f, 0.f);
	    glScalef(.5f, .5f, .5f);
	    drawDinosaur();
	    glPopMatrix();
	}
    }
    glPopMatrix();
}
예제 #3
0
void
redraw(void)
{
    if (useStencil) {
        /* Clear; default stencil clears to zero. */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    } else {
        /* Not using stencil; just clear color and depth. */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }

    glPushMatrix();
    /* Perform scene rotations based on user mouse input. */
    glRotatef(angle2, 1.0, 0.0, 0.0);
    glRotatef(angle, 0.0, 1.0, 0.0);

    /* Translate the dinosaur to be at (0,0,0). */
    glTranslatef(-8, -8, -bodyWidth / 2);

    glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
    glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);

    if (useStencil) {

        /* We can eliminate the visual "artifact" of seeing the "flipped"
        dinosaur underneath the floor by using stencil.  The idea is
         draw the floor without color or depth update but so that
         a stencil value of one is where the floor will be.  Later when
         rendering the dinosaur reflection, we will only update pixels
         with a stencil value of 1 to make sure the reflection only
         lives on the floor, not below the floor. */

        /* Don't update color or depth. */
        glDisable(GL_DEPTH_TEST);
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

        /* Draw 1 into the stencil buffer. */
        glEnable(GL_STENCIL_TEST);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
        glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

        /* Now render floor; floor pixels just get their stencil set to 1. */
        drawFloor();

        /* Re-enable update of color and depth. */
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glEnable(GL_DEPTH_TEST);

        /* Now, only render where stencil is set to 1. */
        glStencilFunc(GL_EQUAL, 1, 0xffffffff);  /* draw if ==1 */
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    }

    glPushMatrix();

    /* The critical reflection step: Reflect dinosaur through the floor
       (the Y=0 plane) to make a relection. */
    glScalef(1.0, -1.0, 1.0);

    /* Position lights now in reflected space. */
    glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
    glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);

    /* XXX Ugh, unfortunately the back face culling reverses when we reflect
    the dinosaur.  Easy solution is just disable back face culling for
     rendering the reflection.  Also, the normals for lighting get screwed
     up by the scale; enabled normalize to ensure normals are still
     properly normalized despite the scaling.  We could have fixed the
     dinosaur rendering code, but this is more expedient. */
    glEnable(GL_NORMALIZE);
    glCullFace(GL_FRONT);

    /* Draw the reflected dinosaur. */
    drawDinosaur();

    /* Disable noramlize again and re-enable back face culling. */
    glDisable(GL_NORMALIZE);
    glCullFace(GL_BACK);

    glPopMatrix();

    /* Restore light positions on returned from reflected space. */
    glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
    glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);


    if (useStencil) {
        /* Don't want to be using stenciling for drawing the actual dinosaur
        (not its reflection) and the floor. */
        glDisable(GL_STENCIL_TEST);
    }

    /* Back face culling will get used to only draw either the top or the
       bottom floor.  This let's us get a floor with two distinct
       appearances.  The top floor surface is reflective and kind of red.
       The bottom floor surface is not reflective and blue. */

    /* Draw "top" of floor.  Use blending to blend in reflection. */
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glColor4f(0.7, 0.0, 0.0, 0.3);
    drawFloor();
    glDisable(GL_BLEND);

    /* Draw "bottom" of floor in blue. */
    glFrontFace(GL_CW);  /* Switch face orientation. */
    glColor4f(0.1, 0.1, 0.7, 1.0);
    drawFloor();
    glFrontFace(GL_CCW);

    /* Draw "actual" dinosaur, not its reflection. */
    drawDinosaur();

    glPopMatrix();

    glutSwapBuffers();
}
예제 #4
0
static void
redraw(void)
{
  int start = 0, end = 0;

  if (reportSpeed) {
    start = glutGet(GLUT_ELAPSED_TIME);
  }

  /* Clear; default stencil clears to zero. */
  if ((stencilReflection && renderReflection) || (stencilShadow && renderShadow)) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  } else {
    /* Avoid clearing stencil when not using it. */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  }

  /* Reposition the light source. */
  lightPosition[0] = 12*cos(lightAngle);
  lightPosition[1] = lightHeight;
  lightPosition[2] = 12*sin(lightAngle);
  if (directionalLight) {
    lightPosition[3] = 0.0;
  } else {
    lightPosition[3] = 1.0;
  }

  shadowMatrix(floorShadow, floorPlane, lightPosition);

  glPushMatrix();
    /* Perform scene rotations based on user mouse input. */
    glRotatef(angle2, 1.0, 0.0, 0.0);
    glRotatef(angle, 0.0, 1.0, 0.0);
     
    /* Tell GL new light source position. */
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

    if (renderReflection) {
      if (stencilReflection) {
        /* We can eliminate the visual "artifact" of seeing the "flipped"
  	   dinosaur underneath the floor by using stencil.  The idea is
	   draw the floor without color or depth update but so that 
	   a stencil value of one is where the floor will be.  Later when
	   rendering the dinosaur reflection, we will only update pixels
	   with a stencil value of 1 to make sure the reflection only
	   lives on the floor, not below the floor. */

        /* Don't update color or depth. */
        glDisable(GL_DEPTH_TEST);
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

        /* Draw 1 into the stencil buffer. */
        glEnable(GL_STENCIL_TEST);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
        glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

        /* Now render floor; floor pixels just get their stencil set to 1. */
        drawFloor();

        /* Re-enable update of color and depth. */ 
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glEnable(GL_DEPTH_TEST);

        /* Now, only render where stencil is set to 1. */
        glStencilFunc(GL_EQUAL, 1, 0xffffffff);  /* draw if ==1 */
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
      }

      glPushMatrix();

        /* The critical reflection step: Reflect dinosaur through the floor
           (the Y=0 plane) to make a relection. */
        glScalef(1.0, -1.0, 1.0);

	/* Reflect the light position. */
        glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

        /* To avoid our normals getting reversed and hence botched lighting
	   on the reflection, turn on normalize.  */
        glEnable(GL_NORMALIZE);
        glCullFace(GL_FRONT);

        /* Draw the reflected dinosaur. */
        drawDinosaur();

        /* Disable noramlize again and re-enable back face culling. */
        glDisable(GL_NORMALIZE);
        glCullFace(GL_BACK);

      glPopMatrix();

      /* Switch back to the unreflected light position. */
      glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

      if (stencilReflection) {
        glDisable(GL_STENCIL_TEST);
      }
    }

    /* Back face culling will get used to only draw either the top or the
       bottom floor.  This let's us get a floor with two distinct
       appearances.  The top floor surface is reflective and kind of red.
       The bottom floor surface is not reflective and blue. */

    /* Draw "bottom" of floor in blue. */
    glFrontFace(GL_CW);  /* Switch face orientation. */
    glColor4f(0.1, 0.1, 0.7, 1.0);
    drawFloor();
    glFrontFace(GL_CCW);

    if (renderShadow) {
      if (stencilShadow) {
	/* Draw the floor with stencil value 3.  This helps us only 
	   draw the shadow once per floor pixel (and only on the
	   floor pixels). */
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_ALWAYS, 3, 0xffffffff);
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
      }
    }

    /* Draw "top" of floor.  Use blending to blend in reflection. */
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glColor4f(0.7, 0.0, 0.0, 0.3);
    glColor4f(1.0, 1.0, 1.0, 0.3);
    drawFloor();
    glDisable(GL_BLEND);

    if (renderDinosaur) {
      /* Draw "actual" dinosaur, not its reflection. */
      drawDinosaur();
    }

    if (renderShadow) {

      /* Render the projected shadow. */

      if (stencilShadow) {

        /* Now, only render where stencil is set above 2 (ie, 3 where
	   the top floor is).  Update stencil with 2 where the shadow
	   gets drawn so we don't redraw (and accidently reblend) the
	   shadow). */
        glStencilFunc(GL_LESS, 2, 0xffffffff);  /* draw if ==1 */
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
      }

      /* To eliminate depth buffer artifacts, we use polygon offset
	 to raise the depth of the projected shadow slightly so
	 that it does not depth buffer alias with the floor. */
      if (offsetShadow) {
	switch (polygonOffsetVersion) {
	case EXTENSION:
#ifdef GL_EXT_polygon_offset
	  glEnable(GL_POLYGON_OFFSET_EXT);
	  break;
#endif
#ifdef GL_VERSION_1_1
	case ONE_DOT_ONE:
          glEnable(GL_POLYGON_OFFSET_FILL);
	  break;
#endif
	case MISSING:
	  /* Oh well. */
	  break;
	}
      }

      /* Render 50% black shadow color on top of whatever the
         floor appareance is. */
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glDisable(GL_LIGHTING);  /* Force the 50% black. */
      glColor4f(0.0, 0.0, 0.0, 0.5);

      glPushMatrix();
	/* Project the shadow. */
        glMultMatrixf((GLfloat *) floorShadow);
        drawDinosaur();
      glPopMatrix();

      glDisable(GL_BLEND);
      glEnable(GL_LIGHTING);

      if (offsetShadow) {
	switch (polygonOffsetVersion) {
#ifdef GL_EXT_polygon_offset
	case EXTENSION:
	  glDisable(GL_POLYGON_OFFSET_EXT);
	  break;
#endif
#ifdef GL_VERSION_1_1
	case ONE_DOT_ONE:
          glDisable(GL_POLYGON_OFFSET_FILL);
	  break;
#endif
	case MISSING:
	  /* Oh well. */
	  break;
	}
      }
      if (stencilShadow) {
        glDisable(GL_STENCIL_TEST);
      }
    }

    glPushMatrix();
    glDisable(GL_LIGHTING);
    glColor3f(1.0, 1.0, 0.0);
    if (directionalLight) {
      /* Draw an arrowhead. */
      glDisable(GL_CULL_FACE);
      glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
      glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0);
      glRotatef(atan(lightHeight/12) * 180.0 / M_PI, 0, 0, 1);
      glBegin(GL_TRIANGLE_FAN);
	glVertex3f(0, 0, 0);
	glVertex3f(2, 1, 1);
	glVertex3f(2, -1, 1);
	glVertex3f(2, -1, -1);
	glVertex3f(2, 1, -1);
	glVertex3f(2, 1, 1);
      glEnd();
      /* Draw a white line from light direction. */
      glColor3f(1.0, 1.0, 1.0);
      glBegin(GL_LINES);
	glVertex3f(0, 0, 0);
	glVertex3f(5, 0, 0);
      glEnd();
      glEnable(GL_CULL_FACE);
    } else {
      /* Draw a yellow ball at the light source. */
      glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
      glutSolidSphere(1.0, 5, 5);
    }
    glEnable(GL_LIGHTING);
    glPopMatrix();

  glPopMatrix();

  if (reportSpeed) {
    glFinish();
    end = glutGet(GLUT_ELAPSED_TIME);
    printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start);
    fflush(stdout);
  }

  glutSwapBuffers();
}