decal.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:13k
源码类别:

GIS编程

开发平台:

Visual C++

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <GL/glut.h>
  5. /* Some <math.h> files do not define M_PI... */
  6. #ifndef M_PI
  7. #define M_PI 3.14159265358979323846
  8. #endif
  9. GLUquadricObj *quadric;
  10. GLfloat  black[] = {0, 0, 0, 1};
  11. GLfloat  white[] = {1, 1, 1, 1};
  12. int  winWidth, winHeight;
  13. GLfloat  *depthSave = NULL;
  14. GLubyte  *stencilSave = NULL;
  15. GLubyte  *colorSave = NULL;
  16. void resizeBuffers(void)
  17. {
  18.     colorSave = realloc(colorSave, winWidth * winHeight * 4 * sizeof(GLubyte));
  19.     depthSave = realloc(depthSave, winWidth * winHeight * 4 * sizeof(GLfloat));
  20.     stencilSave = (GLubyte *)depthSave;
  21. }
  22. void pushOrthoView(float left, float right, float bottom, float top,
  23.     float znear, float zfar)
  24. {
  25.     glPushMatrix();
  26.     glLoadIdentity();
  27.     glMatrixMode(GL_PROJECTION);
  28.     glPushMatrix();
  29.     glLoadIdentity();
  30.     glOrtho(left, right, bottom, top, znear, zfar);
  31. }
  32. void popView(void)
  33. {
  34.     glPopMatrix();
  35.     glMatrixMode(GL_MODELVIEW);
  36.     glPopMatrix();
  37. }
  38. void copyDepthToColor(GLenum whichColorBuffer)
  39. {
  40.     int x, y;
  41.     GLfloat max, min;
  42.     GLint previousColorBuffer;
  43.     glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
  44.         depthSave);
  45.     /* I'm sure this could be done much better with OpenGL */
  46.     max = 0;
  47.     min = 1;
  48.     for(y = 0; y < winHeight; y++)
  49. for(x = 0; x < winWidth; x++) {
  50.     if(depthSave[winWidth * y + x] < min)
  51. min = depthSave[winWidth * y + x];
  52.     if(depthSave[winWidth * y + x] > max && depthSave[winWidth * y + x] < .999)
  53. max = depthSave[winWidth * y + x];
  54. }
  55.     for(y = 0; y < winHeight; y++)
  56. for(x = 0; x < winWidth; x++) {
  57.     if(depthSave[winWidth * y + x] <= max)
  58. depthSave[winWidth * y + x] = 1 -  (depthSave[winWidth * y + x] - min) / (max - min);
  59.     else
  60. depthSave[winWidth * y + x] = 0;
  61. }
  62.     pushOrthoView(0, 1, 0, 1, 0, 1);
  63.     glRasterPos3f(0, 0, -.5);
  64.     glDisable(GL_DEPTH_TEST);
  65.     glDisable(GL_STENCIL_TEST);
  66.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  67.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  68.     glDrawBuffer(whichColorBuffer);
  69.     glDrawPixels(winWidth, winHeight, GL_LUMINANCE , GL_FLOAT, depthSave);
  70.     glDrawBuffer(previousColorBuffer);
  71.     glEnable(GL_DEPTH_TEST);
  72.     popView();
  73. }
  74. unsigned char colors[][3] =
  75. {
  76.     {255, 0, 0}, /* red */
  77.     {255, 218, 0}, /* yellow */
  78.     {72, 255, 0}, /* yellowish green */
  79.     {0, 255, 145}, /* bluish cyan */
  80.     {0, 145, 255}, /* cyanish blue */
  81.     {72, 0, 255}, /* purplish blue */
  82.     {255, 0, 218}, /* reddish purple */
  83. };
  84. void copyStencilToColor(GLenum whichColorBuffer)
  85. {
  86.     int x, y;
  87.     GLint previousColorBuffer;
  88.     glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
  89.         stencilSave);
  90.     /* I'm sure this could be done much better with OpenGL */
  91.     for(y = 0; y < winHeight; y++)
  92. for(x = 0; x < winWidth; x++) {
  93.     int stencilValue;
  94.     
  95.     stencilValue = stencilSave[winWidth * y + x];
  96.     colorSave[(winWidth * y + x) * 3 + 0] = colors[stencilValue % 7][0];
  97.     colorSave[(winWidth * y + x) * 3 + 1] = colors[stencilValue % 7][1];
  98.     colorSave[(winWidth * y + x) * 3 + 2] = colors[stencilValue % 7][2];
  99. }
  100.     pushOrthoView(0, 1, 0, 1, 0, 1);
  101.     glRasterPos3f(0, 0, -.5);
  102.     glDisable(GL_DEPTH_TEST);
  103.     glDisable(GL_STENCIL_TEST);
  104.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  105.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  106.     glDrawBuffer(whichColorBuffer);
  107.     glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
  108.     glDrawBuffer(previousColorBuffer);
  109.     glEnable(GL_DEPTH_TEST);
  110.     popView();
  111. }
  112. int useStencil = 0;
  113. int stage = 6;
  114. typedef enum {COLOR, DEPTH, STENCIL} DataChoice;
  115. DataChoice dataChoice = COLOR;
  116. void init(void)
  117. {
  118.     glEnable(GL_DEPTH_TEST);
  119.     glEnable(GL_CULL_FACE);
  120.     glCullFace(GL_BACK);
  121.     quadric = gluNewQuadric();
  122.     glMatrixMode(GL_PROJECTION);
  123.     glFrustum(-.33, .33, -.33, .33, .5, 40);
  124.     glMatrixMode(GL_MODELVIEW);
  125.     gluLookAt(-4, 10, 6, 0, 0, 0, 0, 1, 0);
  126.     glEnable(GL_LIGHTING);
  127.     glEnable(GL_LIGHT0);
  128.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  129.     glEnable(GL_NORMALIZE);
  130.     /*
  131.      * only need this to clear stencil and only need to clear stencil
  132.      * when you're looking at it; the algorithm works without it.
  133.      */
  134.     glClearStencil(5);
  135. }
  136. void setupLight(void)
  137. {
  138.     static GLfloat  lightpos[] = {0, 1, 0, 0};
  139.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  140. }
  141. void setupNormalDrawingState(void)
  142. {
  143.     glDisable(GL_STENCIL_TEST);
  144.     glEnable(GL_DEPTH_TEST);
  145.     glDepthMask(1);
  146. }
  147. void setupBasePolygonState(int maxDecal)
  148. {
  149.     glEnable(GL_DEPTH_TEST);
  150.     if(useStencil) {
  151. glEnable(GL_STENCIL_TEST);
  152. glStencilFunc(GL_ALWAYS, maxDecal + 1, 0xff);
  153. glStencilOp(GL_KEEP, GL_REPLACE, GL_ZERO);
  154.     }
  155. }
  156. void setupDecalState(int decalNum)
  157. {
  158.     if(useStencil) {
  159. glDisable(GL_DEPTH_TEST);
  160. glDepthMask(0);
  161. glEnable(GL_STENCIL_TEST);
  162. glStencilFunc(GL_GREATER, decalNum, 0xff);
  163. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  164.     }
  165. }
  166. void drawAirplane(void)
  167. {
  168.     GLfloat airplaneColor[4] = {.75, .75, .75, 1};
  169.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, airplaneColor);
  170.     glDisable(GL_CULL_FACE);
  171.     glPushMatrix();
  172.     glTranslatef(0, 0, -2.5);
  173.     gluCylinder(quadric, .5, .5, 5, 10, 10);
  174.     glPushMatrix();
  175.     glTranslatef(0, 0, 5);
  176.     gluCylinder(quadric, .5, 0, 1, 10, 10);
  177.     glPopMatrix();
  178.     glPushMatrix();
  179.     glTranslatef(0, 0, 3);
  180.     glScalef(3, .1, 1);
  181.     gluSphere(quadric, 1, 10, 10);
  182.     glPopMatrix();
  183.     glPushMatrix();
  184.     glTranslatef(0, 0, .5);
  185.     glScalef(2, .1, .5);
  186.     gluSphere(quadric, 1, 10, 10);
  187.     glPopMatrix();
  188.     glEnable(GL_CULL_FACE);
  189.     glBegin(GL_TRIANGLES);
  190.     glNormal3f(1, 0, 0);
  191.     glVertex3f(0, 1.5, 0);
  192.     glVertex3f(0, .5, 1);
  193.     glVertex3f(0, .5, 0);
  194.     glNormal3f(-1, 0, 0);
  195.     glVertex3f(0, 1.5, 0);
  196.     glVertex3f(0, .5, 0);
  197.     glVertex3f(0, .5, 1);
  198.     glEnd();
  199.     glDisable(GL_CULL_FACE);
  200.     glRotatef(180, 0, 1, 0);
  201.     gluDisk(quadric, 0, .5, 10, 10);
  202.     glPopMatrix();
  203.     glEnable(GL_CULL_FACE);
  204. }
  205. void drawGround(void)
  206. {
  207.     GLfloat groundColor[4] = {.647, .165, .165, 1};
  208.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, groundColor);
  209.     glBegin(GL_QUADS);
  210.     glNormal3i(0, 1, 0);
  211.     glVertex3f(10, 0, 10);
  212.     glVertex3f(10, 0, -10);
  213.     glVertex3f(-10, 0, -10);
  214.     glVertex3f(-10, 0, 10);
  215.     glEnd();
  216. }
  217. void drawAsphalt(void)
  218. {
  219.     GLfloat asphaltColor[4] = {.25, .25, .25, 1};
  220.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, asphaltColor);
  221.     glBegin(GL_QUADS);
  222.     glNormal3i(0, 1, 0);
  223.     glVertex3f(5, 0, 9.5);
  224.     glVertex3f(5, 0, -9.5);
  225.     glVertex3f(-5, 0, -9.5);
  226.     glVertex3f(-5, 0, 9.5);
  227.     glEnd();
  228. }
  229. int numStripes = 5;
  230. float stripeGap = .66;
  231. void drawStripes(void)
  232. {
  233.     GLfloat stripeColor[4] = {1, 1, 0, 1};
  234.     int i;
  235.     float stripeLength;
  236.     stripeLength = (16 - stripeGap * (numStripes - 1)) / numStripes;
  237.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, stripeColor);
  238.     glBegin(GL_QUADS);
  239.     glNormal3i(0, 1, 0);
  240.     glVertex3f(4.5, 0, 8.5);
  241.     glVertex3f(4.5, 0, -8.5);
  242.     glVertex3f(3.5, 0, -8.5);
  243.     glVertex3f(3.5, 0, 8.5);
  244.     glVertex3f(-3.5, 0, 8.5);
  245.     glVertex3f(-3.5, 0, -8.5);
  246.     glVertex3f(-4.5, 0, -8.5);
  247.     glVertex3f(-4.5, 0, 8.5);
  248.     for(i = 0; i < numStripes; i++) {
  249.         glVertex3f(.5, 0, 8 - i * (stripeLength + stripeGap));
  250.         glVertex3f(.5, 0, 8 - i * (stripeLength + stripeGap) - stripeLength);
  251.         glVertex3f(-.5, 0, 8 - i * (stripeLength + stripeGap) - stripeLength);
  252.         glVertex3f(-.5, 0, 8 - i * (stripeLength + stripeGap));
  253.     }
  254.     glEnd();
  255. }
  256. void redraw(void)
  257. {
  258.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  259.     
  260.     /* Only need this if you care to look at the stencil buffer */
  261.     if(dataChoice == STENCIL)
  262. glClear(GL_STENCIL_BUFFER_BIT);
  263.     glPushMatrix();
  264.     glScalef(.5, .5, .5);
  265.     if(stage == 1)
  266.        goto doneWithFrame;
  267.     setupLight();
  268.     setupNormalDrawingState();
  269.     glPushMatrix();
  270.     glTranslatef(0, 1, 4);
  271.     glRotatef(135, 0, 1, 0);
  272.     drawAirplane();
  273.     glPopMatrix();
  274.     if(stage == 2)
  275.        goto doneWithFrame;
  276.     setupBasePolygonState(3); /* 2 decals */
  277.     drawGround();
  278.     if(stage == 3)
  279.        goto doneWithFrame;
  280.     setupDecalState(1); /* decal # 1 = the runway asphalt */
  281.     drawAsphalt();
  282.     if(stage == 4)
  283.        goto doneWithFrame;
  284.     setupDecalState(2); /* decal # 2 = yellow paint on the runway */
  285.     drawStripes();
  286.     if(stage == 5)
  287.        goto doneWithFrame;
  288.     setupDecalState(3); /* decal # 3 = the plane's shadow */
  289.     glDisable(GL_LIGHTING);
  290.     glEnable(GL_BLEND);
  291.     glPushMatrix();
  292.     glColor4f(0, 0, 0, .5);
  293.     glTranslatef(0, 0, 4);
  294.     glRotatef(135, 0, 1, 0);
  295.     glScalef(1, 0, 1);
  296.     drawAirplane();
  297.     glPopMatrix();
  298.     glDisable(GL_BLEND);
  299.     glEnable(GL_LIGHTING);
  300. doneWithFrame:
  301.     setupNormalDrawingState();
  302.     glPopMatrix();
  303.     switch(dataChoice) {
  304.         case COLOR:
  305.     break; /* color already in back buffer */
  306. case STENCIL:
  307.     copyStencilToColor(GL_BACK);
  308.     break;
  309. case DEPTH:
  310.     copyDepthToColor(GL_BACK);
  311.     break;
  312.     }
  313.     glutSwapBuffers();
  314. }
  315. void reshape(int width, int height)
  316. {
  317.     glViewport(0, 0, width, height);
  318.     winWidth = width;
  319.     winHeight = height;
  320.     resizeBuffers();
  321.     glutPostRedisplay();
  322. }
  323. static int ox, oy;
  324. static int mode;
  325. /* ARGSUSED */
  326. void button(int b, int state, int x, int y)
  327. {
  328.     ox = x;
  329.     oy = y;
  330.     mode = b;
  331. }
  332. void motion(int x, int y)
  333. {
  334.     static float ang = 0;
  335.     static float height = 10;
  336.     float eyex, eyez;
  337.     if(mode == GLUT_LEFT_BUTTON)
  338.     {
  339.         ang += (x - ox) / 512.0 * M_PI;
  340.         height += (y - oy) / 512.0 * 10;
  341. eyex = cos(ang) * 7;
  342. eyez = sin(ang) * 7;
  343. glLoadIdentity();
  344. gluLookAt(eyex, height, eyez, 0, 0, 0, 0, 1, 0);
  345.         glutPostRedisplay();
  346. ox = x;
  347. oy = y;
  348.     }
  349. }
  350. void changeData(int data)
  351. {
  352.     char *s;
  353.     dataChoice = data;
  354.     glutPostRedisplay();
  355.     switch(data) {
  356.         case COLOR:
  357.     s = "color";
  358.     break;
  359.         case STENCIL:
  360.     s = "stencil";
  361.     break;
  362.         case DEPTH:
  363.     s = "depth";
  364.     break;
  365.     }
  366.     printf("Now displaying %s datan", s);
  367. }
  368. void changeStage(int data)
  369. {
  370.     char *s;
  371.     stage = data;
  372.     glutPostRedisplay();
  373.     switch(data) {
  374.         case 1:
  375.     s = "clearing";
  376.     break;
  377.         case 2:
  378.     s = "drawing airplane";
  379.     break;
  380.         case 3:
  381.     s = "drawing ground";
  382.     break;
  383.         case 4:
  384.     s = "drawing asphalt";
  385.     break;
  386.         case 5:
  387.     s = "drawing paint";
  388.     break;
  389.         case 6:
  390.     s = "drawing shadow";
  391.     break;
  392.     }
  393.     printf("Now displaying frame after %sn", s);
  394. }
  395. int mainMenu;
  396. void stencilDecalEnable(int enabled)
  397. {
  398.     glutSetMenu(mainMenu);
  399.     if(enabled){
  400. glutChangeToMenuEntry(1, "Turn off stencil decal", 0);
  401. printf("Stencil decaling turned onn");
  402. glutPostRedisplay();
  403.     } else {
  404. glutChangeToMenuEntry(1, "Turn on stencil decal", 1);
  405. printf("Stencil decaling turned offn");
  406. glutPostRedisplay();
  407.     }
  408.     useStencil = enabled;
  409. }
  410. /*
  411.  * Basically shortcuts for menu items
  412.  */
  413. /* ARGSUSED1 */
  414. void keyboard(unsigned char key, int x, int y)
  415. {
  416.     switch(key) {
  417.         case '1':
  418.         case '2':
  419.         case '3':
  420.         case '4':
  421.         case '5':
  422.         case '6':
  423.     changeStage(key - '0');
  424.     break;
  425. case 's': case 'S':
  426.     stencilDecalEnable(! useStencil);
  427.     break;
  428. case 'q': case 'Q': case '33':
  429.     exit(0);
  430.     break;
  431. default:
  432.     fprintf(stderr, "Push right mouse button for menun");
  433.     break;
  434.     }
  435. }
  436. int main(int argc, char **argv)
  437. {
  438.     int bufferMenu;
  439.     int finishMenu;
  440.     int stenSize;
  441.     glutInitWindowSize(winWidth = 512, winHeight = 512);
  442.     glutInit(&argc, argv);
  443.     glutInitDisplayString("samples stencil>=3 rgb double depth");
  444.     /* glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH|GLUT_ALPHA); */
  445.     (void)glutCreateWindow("decaling using stencil");
  446.     glutDisplayFunc(redraw);
  447.     glutKeyboardFunc(keyboard);
  448.     glutMotionFunc(motion);
  449.     glutMouseFunc(button);
  450.     glutReshapeFunc(reshape);
  451.     resizeBuffers();
  452.     glGetIntegerv(GL_STENCIL_BITS, &stenSize);
  453.     fprintf(stderr, "(%d bits of stencil available in this visual)n", stenSize);
  454.     fprintf(stderr, "Hit 'h' for help messagen");
  455.     finishMenu = glutCreateMenu(changeStage);
  456.     glutAddMenuEntry("Clearing screen", 1);
  457.     glutAddMenuEntry("Drawing airplane", 2);
  458.     glutAddMenuEntry("Drawing ground ", 3);
  459.     glutAddMenuEntry("Drawing asphalt", 4);
  460.     glutAddMenuEntry("Drawing paint", 5);
  461.     glutAddMenuEntry("Drawing shadow", 6);
  462.     bufferMenu = glutCreateMenu(changeData);
  463.     glutAddMenuEntry("Color data", COLOR);
  464.     glutAddMenuEntry("Stencil data", STENCIL);
  465.     glutAddMenuEntry("Depth data", DEPTH);
  466.     mainMenu = glutCreateMenu(stencilDecalEnable);
  467.     glutAddMenuEntry("Turn on stencil decal", 1);
  468.     glutAddSubMenu("Visible buffer", bufferMenu);
  469.     glutAddSubMenu("Finish frame after...", finishMenu);
  470.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  471.     init();
  472.     glutMainLoop();
  473.     return 0;
  474. }