plvDraw.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:31k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. #include <tcl.h>
  2. #ifdef WIN32
  3. # include "winGLdecs.h"
  4. #endif
  5. #include <GL/gl.h>
  6. #include <GL/glu.h>
  7. #include <algo.h>
  8. #include <vector.h>
  9. #include "plvDraw.h"
  10. #include "plvScene.h"
  11. #include "plvGlobals.h"
  12. #ifdef no_overlay_support
  13. #include "plvDrawCmds.h" // overlay planes work around
  14. #endif
  15. #include "accpersp.h"
  16. #include "togl.h"
  17. #include "RigidScan.h"
  18. #include "DisplayMesh.h"
  19. #include "DrawObj.h"
  20. #include "plvClipBoxCmds.h"
  21. #include "BailDetector.h"
  22. #include "plvAnalyze.h"
  23. #include "defines.h"
  24. #include "TclCmdUtils.h"
  25. static void drawCenterOfRotation();
  26. static bool drawMeshes (bool bDrawAnnotations = true);
  27. static bool drawShadowedMeshes();
  28. static bool setupViewing (bool bFirstPass);
  29. static void setupLighting();
  30. static void setupShading();
  31. static void initRenderParams();
  32. static const int NUM_POWERS = 100;
  33. static const int NUM_POWER_ARGS = 5000;
  34. static float *thePowers;
  35. static int hiliteColor = -1;
  36. DrawObjects draw_other_things;
  37. bool
  38. initDrawing()
  39. {
  40.   float camera[3] = { 0, 0, 5 };
  41.   float object[3] = { 0, 0, 0 };
  42.   float up[3] = { 0, 1, 0 };
  43.   tbView->setup (camera, object, up, 10);
  44.   tbView->setOrthographic (false);
  45.   theScene->centerCamera();
  46.   initRenderParams();
  47.   thePowers = new float[NUM_POWERS*NUM_POWER_ARGS];
  48.   for (int i = 0; i < NUM_POWERS; i++) {
  49.     for (int j = 0; j < NUM_POWER_ARGS; j++) {
  50.       thePowers[j + i*NUM_POWER_ARGS] = 
  51. pow(float(j)/(NUM_POWER_ARGS-1), i);
  52.     }
  53.   }
  54.   return true;
  55. }
  56. bool
  57. initDrawingPostCreation()
  58. {
  59.   if (toglCurrent != NULL) {
  60.     initSelection (toglCurrent);
  61.     hiliteColor = Togl_AllocColorOverlay (toglCurrent, 0, 1, 1);
  62.     Togl_ShowOverlay (toglCurrent);
  63.   }
  64.   glLightModelfv (GL_LIGHT_MODEL_AMBIENT, theRenderParams->lightAmbient);
  65.   return true;
  66. }
  67. static void
  68. initRenderParams()
  69. {
  70.     theRenderParams = new RenderParams;
  71.     theRenderParams->polyMode = GL_FILL;
  72.     theRenderParams->hiddenLine = false;
  73.     theRenderParams->shadeModel = perVertex;
  74.     theRenderParams->cull = false;
  75.     theRenderParams->useTstrips = false;
  76.     theRenderParams->boundSelection = true;
  77.     theRenderParams->light = true;
  78.     theRenderParams->colorMode = grayColor;
  79.     theRenderParams->useEmissive = false;
  80.     theRenderParams->twoSidedLighting = false;
  81.     
  82.     // taken care of by two sided lighting
  83.     // kberg - 6/5/01
  84.     //theRenderParams->backFaceEmissive = false;
  85.     theRenderParams->backfaceMode = lit;
  86.     theRenderParams->confScale = 1;
  87.     theRenderParams->pointSize = 1.0;
  88.     theRenderParams->lineWidth = 1.0;
  89.     theRenderParams->blend = 0;
  90.     
  91.     theRenderParams->shininess = 20;
  92.     theRenderParams->specular[0] = 128;
  93.     theRenderParams->specular[1] = 128;
  94.     theRenderParams->specular[2] = 128;
  95.     theRenderParams->specular[3] = 255;
  96.     theRenderParams->diffuse[0] = 178; // .7 * 255
  97.     theRenderParams->diffuse[1] = 178;
  98.     theRenderParams->diffuse[2] = 178;
  99.     theRenderParams->diffuse[3] = 255;
  100.     /* added by kberg 6/5/01
  101.        paramters used when two sided lighting is turne don
  102.     */
  103.     theRenderParams->backDiffuse[0] = 25;
  104.     theRenderParams->backDiffuse[1] = 25;
  105.     theRenderParams->backDiffuse[2] = 25;
  106.     theRenderParams->backDiffuse[3] = 255;
  107.     
  108.     theRenderParams->backSpecular[0] = 18;
  109.     theRenderParams->backSpecular[1] = 18;
  110.     theRenderParams->backSpecular[2] = 18;
  111.     theRenderParams->backSpecular[3] = 255;
  112.     
  113.     theRenderParams->backShininess = 20;
  114.     theRenderParams->background[0] = 0;
  115.     theRenderParams->background[1] = 0;
  116.     theRenderParams->background[2] = 0;
  117.     theRenderParams->background[3] = 255;
  118.     theRenderParams->lightPosition[0] = 0.0;
  119.     theRenderParams->lightPosition[1] = 0.0;
  120.     theRenderParams->lightPosition[2] = 1.0;
  121.     theRenderParams->lightAmbient[0] = 0.0;
  122.     theRenderParams->lightAmbient[1] = 0.0;
  123.     theRenderParams->lightAmbient[2] = 0.0;
  124.     theRenderParams->lightAmbient[3] = 1.0;
  125.     theRenderParams->lightDiffuse[0] = 1.0;
  126.     theRenderParams->lightDiffuse[1] = 1.0;
  127.     theRenderParams->lightDiffuse[2] = 1.0;
  128.     theRenderParams->lightDiffuse[3] = 1.0;
  129.     theRenderParams->lightSpecular[0] = 1.0;
  130.     theRenderParams->lightSpecular[1] = 1.0;
  131.     theRenderParams->lightSpecular[2] = 1.0;
  132.     theRenderParams->lightSpecular[3] = 1.0;
  133.     theRenderParams->shadows = false;
  134.     theRenderParams->antiAlias = false;
  135.     theRenderParams->numAntiAliasSamps = 8;
  136.     theRenderParams->jitterX = 0;
  137.     theRenderParams->jitterY = 0;
  138.     theRenderParams->jitterArray = (jitter_point *)j8;
  139.     theRenderParams->dofJitterX = 0;
  140.     theRenderParams->dofJitterY = 0;
  141.     theRenderParams->dofCenter = 0.5; // ratio between near and far
  142.     theRenderParams->shadowLength = 0.05;
  143.     theRenderParams->fromLightPOV = false;
  144.     theRenderParams->flipnorm = false;
  145.     theRenderParams->clearBeforeRender = true;
  146.     theRenderParams->accelerateWithBbox = true;
  147.     theRenderParams->bRenderManipsPoints = true;
  148.     theRenderParams->bRenderManipsTinyPoints = false;
  149.     theRenderParams->bRenderManipsUnlit = false;
  150.     theRenderParams->bRenderManipsLores = false;
  151.     theRenderParams->bRenderManipsSkipDlist = true;
  152.     theRenderParams->iFastManipsThreshold = 0;
  153.     
  154. #ifdef no_overlay_support
  155.     // RGBA being read back in
  156.     theRenderParams->savedImage = new char[4 * theWidth * theHeight];
  157.     
  158.     theRenderParams->savedImageWidth = theWidth;
  159.     theRenderParams->savedImageHeight = theHeight;
  160. #endif
  161. }
  162. static bool
  163. setupViewing (bool bFirstPass)
  164. {
  165.   struct RenderParams* gRP = theRenderParams; // for convenience
  166.   // Viewport
  167.   int width = theWidth;
  168.   int height = theHeight;
  169.   if (theResCap > 0) {
  170.     width = min (theResCap, width);
  171.     height = min (theResCap, height);
  172.   }
  173.   glViewport((theWidth - width) / 2, (theHeight - height) / 2, width, height);
  174.   
  175.   // Prepare projection
  176.   tbView->applyProjection();
  177.   // if antialiasing, have to jitter projection matrix
  178.   if (gRP->antiAlias) {
  179.     if (!tbView->getOrthographic()) {
  180.       // perspective
  181.       // rebuild projection matrix with jitter code
  182.       float left, right, top, bottom, znear, zfar;
  183.       tbView->getFrustum (left, right, top, bottom, znear, zfar);
  184.       // zFocus = lerp (dofCenter, znear, zfar)
  185.       float zFocus = gRP->dofCenter * zfar + (1 - gRP->dofCenter) * znear;
  186.       // this doesn't actually work; I think to get true depth of field
  187.       // you have to call accFrustum a bunch of times as depth of what you 
  188.       // draw changes?  I can get this to draw things blurry as the scene
  189.       // approaches the camera, but a) not as they recede from the camera,
  190.       // and b) it draws the whole scene with the same blurriness, regardless
  191.       // of how far individual objects are from camera.
  192.       
  193.       accFrustum (left, right, top, bottom, znear, zfar,
  194.   gRP->jitterX, gRP->jitterY,
  195.   gRP->jitterX * gRP->dofJitterX,
  196.   gRP->jitterY * gRP->dofJitterY,
  197.   zFocus);
  198.     } else {
  199.       // orthographic
  200.       // have to modify projection matrix with jitter code
  201.       float heightAngle, aspectRatio, nearDistance, farDistance;
  202.       tbView->getProjection(heightAngle, 
  203.     aspectRatio,
  204.     nearDistance, 
  205.     farDistance);
  206.       float cameraHeight = tbView->getOrthoHeight();
  207.       glTranslatef(gRP->jitterX * cameraHeight * aspectRatio / theWidth,
  208.    gRP->jitterY * cameraHeight / theHeight,
  209.    0.0);
  210.     }
  211.   }
  212.     
  213.   // Prepare viewing orientation/trans
  214.   if (bFirstPass)    tbView->applyXform();   // apply spin()
  215.   else               tbView->reapplyXform(); // no spin
  216.   return true;
  217. }
  218. static void
  219. setupLighting()
  220. {
  221.   if (theRenderParams->light) {
  222.     // Enable lighting
  223.     glEnable (GL_LIGHTING);
  224.     glEnable (GL_LIGHT0);
  225.     
  226.     glMatrixMode (GL_MODELVIEW);
  227.     glPushMatrix();
  228.     glLoadIdentity();
  229.     // if rendering with "flipped" normals, actually flip light dir
  230.     if (theRenderParams->flipnorm)
  231.       glRotatef (180, 0, 1, 0);
  232.     
  233.     glLightfv (GL_LIGHT0, GL_POSITION, theRenderParams->lightPosition);
  234.     glLightfv (GL_LIGHT0, GL_AMBIENT, theRenderParams->lightAmbient);
  235.     glLightfv (GL_LIGHT0, GL_DIFFUSE, theRenderParams->lightDiffuse);
  236.     glLightfv (GL_LIGHT0, GL_SPECULAR, theRenderParams->lightSpecular);
  237.     glPopMatrix();
  238.   } else {
  239.     glDisable (GL_LIGHTING);
  240.   }
  241. }
  242. static void
  243. setupShading()
  244. {
  245.   if (theRenderParams->shadeModel == perVertex)
  246.     glShadeModel(GL_SMOOTH);
  247.   else
  248.     glShadeModel(GL_FLAT);
  249.   //this is for the old pseudo-hidden line draw mode --
  250.   //draw front faces outline and back faces solid black
  251.   //glPolygonMode(GL_FRONT, theRenderParams->polyMode);
  252.   // depending on whether normals are flipped, specify the orientation
  253.   // of the faces - removed from if (...->cull) by kberg 7/5/01 so that
  254.   // flipping normals did not cause nothing to be drawn when 2 sided lighting
  255.   // was selected
  256.   glFrontFace (theRenderParams->flipnorm ? GL_CW : GL_CCW);
  257.   // don't cull back faces if two sided lighting is enabled
  258.   if (theRenderParams->cull && !theRenderParams->twoSidedLighting) {
  259.     glEnable (GL_CULL_FACE);
  260.   } else {
  261.     glDisable (GL_CULL_FACE);
  262.   }
  263.   //two sided lighting will take care of this
  264.   //glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, theRenderParams->backFaceEmissive);
  265.   glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, theRenderParams->twoSidedLighting);
  266. }
  267. bool
  268. setupSceneDrawing()
  269. {
  270.   theScene->computeBBox (Scene::flush);
  271.   // Prepare buffer
  272.   glDepthFunc(GL_LESS);
  273.   glEnable(GL_DEPTH_TEST);
  274.   // Lighting
  275.   setupLighting();
  276.   setupShading();
  277.   // Viewing
  278.   setupViewing (true);
  279.   
  280.   // clear buffer
  281.   if (theRenderParams->clearBeforeRender) {
  282.     glClearColor(theRenderParams->background[0] / 255.,
  283.  theRenderParams->background[1] / 255.,
  284.  theRenderParams->background[2] / 255.,
  285.  theRenderParams->background[3] / 255.);
  286.   }
  287.   // bbox-clipping for this render pass?
  288.   theRenderParams->accelerateWithBbox = GetTclGlobalBool ("noclip");
  289.   if (theRenderParams->accelerateWithBbox) {
  290.     // if the whole scene is onscreen, bbox clipping for individual
  291.     // meshes is a waste of time.
  292.     ScreenBox* filter = new ScreenBox (NULL,
  293.      0, Togl_Width(toglCurrent) - 1,
  294.      0, Togl_Height(toglCurrent) - 1);
  295.     if (filter->acceptFully (theScene->worldBbox())) {
  296.       //cout << "Whole scene onscreen; no need to clip test" << endl;
  297.       theRenderParams->accelerateWithBbox = false;
  298.     }
  299.     delete filter;
  300.   }
  301.   return true;
  302. }
  303. bool
  304. drawScene()
  305. {
  306.   if (!setupSceneDrawing())
  307.     return false;
  308.   if (theRenderParams->antiAlias) {
  309.     glClear(GL_ACCUM_BUFFER_BIT);
  310.     for (int i = 0; i < theRenderParams->numAntiAliasSamps; i++) {
  311.       printf("rRender pass %d of %d...", i+1,
  312.      theRenderParams->numAntiAliasSamps);
  313.       fflush(stdout);
  314.       
  315.       theRenderParams->jitterX = theRenderParams->jitterArray[i].x;
  316.       theRenderParams->jitterY = theRenderParams->jitterArray[i].y;
  317.       
  318.       // Viewing
  319.       setupViewing (i == 0);
  320.       drawShadowedMeshes();
  321.       
  322.       glAccum(GL_ACCUM, 1.0/theRenderParams->numAntiAliasSamps);
  323.       if (GetTclGlobalBool ("aaswap"))
  324. Togl_SwapBuffers (toglCurrent);
  325.     }
  326.     glAccum(GL_RETURN, 1.0);
  327.     printf("Antialiased render (%d passes) complete.n", i);
  328.   } else {
  329.     drawShadowedMeshes();
  330.   }
  331.   if (!(   GetTclGlobalBool ("highQualSingle")
  332. && GetTclGlobalBool ("highQualHideBbox"))) {
  333.     if (theScene->wantMeshBBox()) {
  334.       drawBoundingBox (theScene->worldBbox());
  335.     }
  336.     
  337.     // bugnote, do this last b/c it hoses render modes
  338.     drawCenterOfRotation();
  339.   }
  340.  
  341. #ifdef no_overlay_support
  342.   // only allocate new memory if the window has been resized
  343.   if (theRenderParams->savedImageWidth != theWidth || 
  344.       theRenderParams->savedImageHeight != theHeight) {
  345.     delete [] theRenderParams->savedImage;
  346.     
  347.     theRenderParams->savedImageWidth = theWidth;
  348.     theRenderParams->savedImageHeight = theHeight;
  349.   
  350.     theRenderParams->savedImage = new char[theWidth*theHeight*4];
  351.   }
  352.   glReadBuffer(GL_BACK);
  353.   glReadPixels(0,0,theWidth, theHeight, GL_RGBA, GL_UNSIGNED_BYTE, 
  354.        theRenderParams->savedImage);
  355.   drawOverlay(toglCurrent);
  356. #endif
  357.   return true;
  358. }
  359. static void 
  360. initTextureParmsForShadowMap(void)
  361. {
  362. #ifdef GL_SGIX_shadow
  363.   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  364.   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  365.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  366.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  367.   
  368.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  369.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  370.   
  371.   glTexParameterf(GL_TEXTURE_2D, GL_SHADOW_AMBIENT_SGIX, 0.3);
  372.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_OPERATOR_SGIX,
  373.   GL_TEXTURE_LEQUAL_R_SGIX);
  374.   // Enable texgen to get texture-coods (x, y, z, w) at every point.These
  375.   // texture co-ordinates are then transformed by the texture matrix.
  376.   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  377.   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  378.   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  379.   glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  380.   GLfloat p[4];
  381.   p[0] = 1.0;
  382.   p[1] = p[2] = p[3] = 0.0;
  383.   glTexGenfv(GL_S, GL_OBJECT_PLANE, p);
  384.   p[0] = 0.0;
  385.   p[1] = 1.0;
  386.   p[2] = p[3] = 0.0;
  387.   glTexGenfv(GL_T, GL_OBJECT_PLANE, p);
  388.   p[0] = p[1] = 0.0;
  389.   p[2] = 1.0, p[3] = 0.0;
  390.   glTexGenfv(GL_R, GL_OBJECT_PLANE, p);
  391.   p[0] = p[1] = p[2] = 0.0;
  392.   p[3] = 1.0;
  393.   glTexGenfv(GL_Q, GL_OBJECT_PLANE, p);
  394.   glEnable(GL_TEXTURE_GEN_S);
  395.   glEnable(GL_TEXTURE_GEN_T);
  396.   glEnable(GL_TEXTURE_GEN_R);
  397.   glEnable(GL_TEXTURE_GEN_Q);
  398. #endif
  399. }
  400. static float lightview_mat[16] = {0};
  401. static float lightview_proj_mat[16] = {0};
  402. static bool
  403. drawMeshesFromLightView (void)
  404. {
  405.   // may need to render to back buffer to get info about where to position 
  406.   // "light-cam" and have relevant area onscreen
  407.   bool bReadFromFront = true;
  408.   if (theRenderParams->fromLightPOV
  409.       || !GetTclGlobalBool ("shadowFastPass")) {
  410.     drawMeshes();
  411.     bReadFromFront = false;
  412.   }
  413.   int vp[4];
  414.   glGetIntegerv(GL_VIEWPORT, vp);
  415.   int curWidth = vp[2], curHeight = vp[3];
  416.   // first, calculate desired light angle:
  417.   Pnt3 current (0, 0, 1);
  418.   Pnt3 wanted (theRenderParams->lightPosition);
  419.   // if we're antialiasing, also jitter light for soft shadows
  420.   if (theRenderParams->antiAlias) {
  421.     Pnt3 jitter (theRenderParams->jitterX, theRenderParams->jitterY, 0);
  422.     jitter *= theRenderParams->shadowLength;
  423.     wanted += jitter;
  424.   }
  425.   // and rotation center:
  426.   // first get camera parms
  427.   float sceneCenter[3]; tbView->getRotationCenter (sceneCenter);
  428.   float cameraCenter[3]; tbView->getCameraCenter (cameraCenter);
  429.   float viewRot[4][4], viewTrans[3];
  430.   tbView->getXform(viewRot,viewTrans);
  431.   // try to get rotation center from center of screen instead of scene bbox
  432.   Pnt3 objectCenter;
  433.   if (!findZBufferNeighborExt (curWidth / 2, curHeight / 2, objectCenter,
  434.        toglCurrent, tbView, 100,
  435.        NULL, false, bReadFromFront)) {
  436.     objectCenter = sceneCenter;
  437.   }
  438.   if (GetTclGlobalBool ("shadowHackCenter", "false"))
  439.     objectCenter = sceneCenter;
  440.   // get corners, sides while we're at it
  441.   vector<Pnt3> cornerPos;
  442.   for (int i = 0; i < 8; i++) {
  443.     int x = (i & 1) ? 0 : curWidth - 1;
  444.     int y = (i & 2) ? 0 : curHeight - 1;
  445.     if (i >= 4) {
  446.       if (x) {
  447. x /= 2;
  448.       } else {
  449. if (y)
  450.   x = curWidth - 1;
  451. y = curHeight / 2;
  452.       }
  453.     }
  454.     Pnt3 corner;
  455.     if (findZBufferNeighborExt (x, y, corner, toglCurrent, tbView, 100,
  456. NULL, false, bReadFromFront)) {
  457.       //cerr << "accept screen corner " << x << ", " << y 
  458.       //   << ": " << corner << endl;
  459.       cornerPos.push_back (corner);
  460.     }
  461.   }
  462.   // and toss in any corners of the scene bbox that fall onscreen
  463.   ScreenBox screen (NULL, 0, curWidth-1, 0, curHeight-1);
  464.   const Bbox& bb = theScene->worldBbox();
  465.   for (i = 0; i < 8; i++) {
  466.     if (screen.accept (bb.corner(i))) {
  467.       cornerPos.push_back (bb.corner (i));
  468.       //cerr << "accept bb corner " << i << endl;
  469.     }
  470.   }
  471.   
  472.   // now start setting matrices the way we need them
  473.   glMatrixMode (GL_MODELVIEW);
  474.   glPushMatrix();
  475.   glLoadIdentity();
  476.   // rotate to light direction
  477.   Pnt3 axis = cross (current, wanted);
  478.   if (axis.norm2() > 0.0) {
  479.     float angle = dot (current, wanted);
  480.     angle = -180 / M_PI * acos (angle);
  481.     if (!GetTclGlobalBool ("shadowHackRotate", false))
  482.       glRotatef (angle, axis[0], axis[1], axis[2]);
  483.   }
  484.   // apply viewing xform (rotation only) so we're looking at correct face
  485.   glMultMatrixf (&viewRot[0][0]);
  486.   // translate back to object coords
  487.   glTranslatef (-objectCenter[0], -objectCenter[1], -objectCenter[2]);
  488.   // set up orthographic projection (since directional light)
  489.   glMatrixMode (GL_PROJECTION);
  490.   float oldProj[16];
  491.   glGetFloatv (GL_PROJECTION_MATRIX, oldProj);
  492.   float dummy, aspect, znear, zfar;
  493.   tbView->getProjection(dummy, aspect, znear, zfar);
  494.   float orthoHeight = tbView->getOrthoHeight();
  495.   float halfScene = theScene->sceneRadius(); // conservative
  496.   glLoadIdentity();
  497.   glOrtho(-orthoHeight/2*aspect, orthoHeight/2*aspect,
  498.   -orthoHeight/2, orthoHeight/2,
  499.         -halfScene, +halfScene);
  500.   glGetFloatv (GL_PROJECTION_MATRIX, lightview_proj_mat);
  501.   glMatrixMode (GL_MODELVIEW);
  502.   // zoom scene (part rendered from camera view) so that it fits onscreen
  503.   // and try to get it to fill screen, since shadow resolution is
  504.   // screen-space dependent
  505.   float shadScale = atof (GetTclGlobal ("shadowZoom", "1.0"));
  506.   // and now we want to move the scene so the old viewport bbox is still
  507.   // centered and fills the new viewport.
  508.   Projector proj;
  509.   int x1 = 1e6, x2 = -1e6, y1 = 1e6, y2 = -1e6;
  510.   for (i = 0; i < cornerPos.size(); i++) {
  511.     cornerPos[i] = proj (cornerPos[i]);
  512.     x1 = MIN (x1, cornerPos[i][0]);
  513.     x2 = MAX (x2, cornerPos[i][0]);
  514.     y1 = MIN (y1, cornerPos[i][1]);
  515.     y2 = MAX (y2, cornerPos[i][1]);
  516.   }
  517.   int dx = x2 - x1; int dy = y2 - y1;
  518.   int tx = (curWidth - (x1 + x2)) / 2;
  519.   int ty = (curHeight - (y1 + y2)) / 2;
  520.   float scale = MIN ((float)curWidth / dx, (float)curHeight / dy);
  521.   scale *= .9; // slightly conservative
  522.   scale *= shadScale;
  523.   cerr << "Using " << scale 
  524.        << " as shadow scale factor; set shadowZoom to change" << endl;
  525.   
  526.   // apply scale, translate on right
  527.   glGetFloatv (GL_MODELVIEW_MATRIX, lightview_mat);
  528.   glLoadIdentity(); 
  529.   glScalef (scale, scale, 1.0); // z=1 b/c ortho, so doesn't matter, and
  530. // we don't want to hose clipping planes
  531.   if (!GetTclGlobalBool ("shadowHackTranslate", false)) {
  532.     glTranslatef (tx * scale, ty * scale, 0);
  533.   }
  534.   glMultMatrixf (lightview_mat);
  535.   // save for retexturing
  536.   glGetFloatv (GL_MODELVIEW_MATRIX, lightview_mat);
  537.   bool ret = drawMeshes (false);
  538.   glMatrixMode (GL_PROJECTION);
  539.   glLoadIdentity();
  540.   glMultMatrixf (oldProj);
  541.   glMatrixMode (GL_MODELVIEW);
  542.   glPopMatrix();
  543.   return ret;
  544. }
  545. static void dumpGLerror (void)
  546. {
  547.   while (int a = glGetError()) {
  548.     cerr << "GL error: " << a << endl << flush;
  549.   }
  550. }
  551. static bool
  552. generateShadowMap (void)
  553. {
  554. #ifdef GL_SGIX_shadow
  555.   int x, y;
  556.   GLfloat log2 = log(2.0);
  557.   x = 1 << ((int) (log((float) theWidth) / log2));
  558.   y = 1 << ((int) (log((float) theHeight) / log2));
  559.   glViewport(0, 0, x, y);
  560.   initTextureParmsForShadowMap();
  561.   glEnable (GL_POLYGON_OFFSET_FILL);
  562.   char* of1 = GetTclGlobal ("shadowOffset1", "3");
  563.   char* of2 = GetTclGlobal ("shadowOffset2", "0");
  564.   glPolygonOffset (atof (of1), atof (of2));
  565.   bool ret = drawMeshesFromLightView();
  566.   glDisable (GL_POLYGON_OFFSET_FILL);
  567.   if (ret) {
  568.     // Read in frame-buffer into a depth texture map
  569.     // do NOT remove the glError calls (either one) or it hoses the pipe!
  570.     // really the problem is some context switching/synchronization error
  571.     // look at /usr/adm/crash/diag/gfx/IR/*.rslt for fun
  572.     // but really make sure not to run gr_osview while running this.'
  573.     // calling glGetError() causes it to occur much less frequently,
  574.     // but doesn't stop it entirely.
  575.     dumpGLerror();
  576.     //cerr << "extracting texture:" << endl;
  577.     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_SGIX,
  578.      0, 0, x, y, 0);
  579.     dumpGLerror();
  580.   }
  581.   glViewport(0, 0, theWidth, theHeight);
  582.   return ret;
  583. #endif
  584. }
  585. bool
  586. drawShadowedMeshes (void)
  587. {
  588. #ifdef GL_SGIX_shadow
  589.   if (theRenderParams->fromLightPOV) {
  590.     return drawMeshesFromLightView();
  591.   } else if (theRenderParams->shadows) {
  592.     // algorithm from Siggraph 99 course notes, OpenGL advanced
  593.     // techniques, section 11.4.3: shadow maps
  594.     // also Tom McReynolds' shadowmap.c sample
  595.     if (!generateShadowMap())
  596.       return false;
  597.     
  598.     // Now render the normal scene using projective textures to get the depth
  599.     // value from the light's point of view into the r-cood of the texture.
  600.     glEnable(GL_TEXTURE_2D);
  601.     glMatrixMode (GL_TEXTURE);
  602.     glLoadIdentity();
  603.     glTranslatef (0.5, 0.5, 0.4994); // magic numbers?
  604.     glScalef (0.5, 0.5, 0.5);
  605.     glMultMatrixf (lightview_proj_mat);
  606.     glMultMatrixf (lightview_mat);
  607.     glMatrixMode (GL_MODELVIEW);
  608.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_TRUE);
  609.     bool ret = drawMeshes();
  610.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_SGIX, GL_FALSE);
  611.     glDisable (GL_TEXTURE_2D);
  612.     return ret;
  613.   } else {
  614.     return drawMeshes();
  615.   }
  616. #else
  617.     return drawMeshes();
  618. #endif
  619. }
  620. bool
  621. drawSceneIndexColored (int scale = 1)
  622. {
  623.   PushRenderParams();
  624.   theRenderParams->polyMode = GL_FILL;
  625.   theRenderParams->hiddenLine = false;
  626.   theRenderParams->shadeModel = fakePerFace;
  627.   theRenderParams->colorMode = noColor;
  628.   theRenderParams->light = false;
  629.   theRenderParams->useEmissive = false;
  630.   theRenderParams->antiAlias = false;
  631.   theRenderParams->boundSelection = false;
  632.   theRenderParams->blend = false;
  633.   theRenderParams->diffuse[0] = 0;
  634.   theRenderParams->diffuse[1] = 0;
  635.   theRenderParams->diffuse[2] = 0;
  636.   theRenderParams->diffuse[3] = 255;
  637.   theRenderParams->background[0] = 0;
  638.   theRenderParams->background[1] = 0;
  639.   theRenderParams->background[2] = 0;
  640.   theRenderParams->background[3] = 255;
  641.   setupSceneDrawing();
  642.   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  643.   for (int i = 0; i < theScene->meshSets.size(); i++) {
  644.     // encode mesh index as 3 floats, suitable for representation in
  645.     // quantized 15-bit (or better) frame buffer.  Allows 32767 meshes.
  646.     int is = (i + 1) * scale;
  647.     uchar r = is % 32;
  648.     uchar g = (is / 32) % 32;
  649.     uchar b = is / 1024;
  650.     theRenderParams->diffuse[0] = r * 8;
  651.     theRenderParams->diffuse[1] = g * 8;
  652.     theRenderParams->diffuse[2] = b * 8;
  653.     // sanity check to make sure packing/unpacking works right
  654.     int i2 = b * 1024 + g * 32 + r;
  655.     i2 /= scale;
  656.     assert (i2 == i + 1);
  657.     theScene->meshSets[i]->drawSelf (false);
  658.   }
  659.   PopRenderParams();
  660.   return true;
  661. }
  662. bool
  663. drawSceneThicknessColored (void)
  664. {
  665.   // draw once normally...
  666.   if (!setupSceneDrawing())
  667.     return false;
  668.   PushRenderParams();
  669.   theRenderParams->boundSelection = false;
  670.   drawMeshes();
  671.   // save the near z-buffer
  672.   vector<Pnt3> nearPts, farPts;
  673.   Selection screen;
  674.   screen.type = Selection::rect;
  675.   screen.pts.push_back (Selection::Pt (0, 0));
  676.   screen.pts.push_back (Selection::Pt (0, theHeight));
  677.   screen.pts.push_back (Selection::Pt (theWidth, theHeight));
  678.   screen.pts.push_back (Selection::Pt (theWidth, 0));
  679.   if (!ReadZBufferArea (nearPts, screen, true, false)) {
  680.     PopRenderParams();
  681.     return false;
  682.   }
  683.   // then clear everything, and draw again with reversed depth test
  684.   glClearDepth (0);
  685.   setupSceneDrawing();
  686.   glClearDepth (1);
  687.   glDepthFunc (GL_GREATER);
  688.   drawMeshes();
  689.   // save the far z-buffer
  690.   if (!ReadZBufferArea (farPts, screen, true, false, true)) {
  691.     PopRenderParams();
  692.     return false;
  693.   }
  694.   // create a nice visualization of this
  695.   vector<unsigned int> depth;
  696.   depth.reserve (theWidth * theHeight);
  697.   for (int y = 0; y < theHeight; y++) {
  698.     int yofs = y * theWidth;
  699.     for (int x = 0; x < theWidth; x++) {
  700.       float nz = nearPts [yofs + x] [2];
  701.       float fz = farPts [yofs + x] [2];
  702.       if (nz != 0 && fz != 0) {
  703. depth.push_back (((255 - (int)MIN (255, (nz-fz) * 10)) << 16)
  704.  + 65535 + (255<<24));
  705. //printf ("%f %f %xn", nz, fz, depth.back());
  706.       } else {
  707. depth.push_back (0);
  708.       }
  709.     }
  710.   }
  711.   // and blit it to screen.
  712.   glMatrixMode (GL_PROJECTION);
  713.   glLoadIdentity();
  714.   glMatrixMode (GL_MODELVIEW);
  715.   glLoadIdentity();
  716.   glDisable (GL_DEPTH_TEST);
  717.   glRasterPos2f (-1, -1);
  718.   glDrawPixels (theWidth, theHeight, GL_RGBA, GL_UNSIGNED_BYTE, depth.begin());
  719.   while (int err = glGetError()) {
  720.     cerr << "Error: " << err << endl;
  721.   }
  722.   PopRenderParams();
  723.   return true;
  724. }
  725. bool
  726. drawScanHilites (void)
  727. {
  728.   char* which = GetTclGlobal ("showScanHilites", "");
  729.   if (!strcmp (which, "never"))
  730.     return false;
  731.   bool bInvis = (0 == strcmp (which, "always"));
  732.   int nToHilite = g_hilitedScans.size();
  733.   if (nToHilite) {
  734.     setupViewing (false);
  735. #ifndef no_overlay_support
  736.     glIndexi (hiliteColor);
  737. #else
  738.     glColor3f(0,1,1);
  739. #endif
  740.     for (int i = 0; i < nToHilite; i++) {
  741.    
  742.       if (bInvis || g_hilitedScans[i]->getVisible()) {
  743. glMatrixMode (GL_MODELVIEW);
  744. glPushMatrix();
  745. g_hilitedScans[i]->getMeshData()->gl_xform();
  746. drawBoundingBox (g_hilitedScans[i]->getMeshData()->localBbox(),
  747.  false);
  748. glPopMatrix();
  749.       }
  750.     }
  751.   }
  752.   return true;
  753. }
  754. static void
  755. drawCenterOfRotation()
  756. {
  757.   if (g_tclInterp != NULL) {
  758.     if (GetTclGlobalBool ("rotCenterVisible")) {
  759.       //show center of rotation
  760.       float redcolor[3] = { .5, 0, 0 };
  761.       Pnt3 center;
  762.       glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, redcolor);
  763.       if (theActiveScan == NULL) {
  764. tbView->getRotationCenter (center);
  765.       } else {
  766. center = theActiveScan->getMeshData()->worldCenter();
  767.       }
  768.       glTranslatef(center[0],center[1], center[2]);
  769.       if (GetTclGlobalBool ("rotCenterOnTop"))
  770. glDisable (GL_DEPTH_TEST);
  771.       GLUquadric* quad;
  772.       quad = gluNewQuadric();
  773.       gluSphere (quad, theScene->sceneRadius() / 100, 10, 10);
  774.       gluDeleteQuadric (quad);
  775.     }
  776.   }
  777. }
  778. static bool
  779. drawMeshes (bool bDrawAnnotations)
  780. {
  781.   int k;
  782.   int nMeshes = theScene->meshSets.size();
  783.   BailDetector bail;
  784.   // clear before rendering
  785.   if (theRenderParams->clearBeforeRender)
  786.     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  787.   // ensure that bounding box is up-to-date
  788.   theScene->computeBBox (Scene::flush);
  789.   if (GetTclGlobalBool ("renderOnlyActiveMesh")) {
  790.     theSelectedScan->drawSelf();
  791.   } else {
  792.     // two passes, draw opaque meshes then transparent ones
  793.     for (k = 0; k < nMeshes; k++) {
  794.       
  795.       if (!theScene->meshSets[k]->transparent()) {
  796. theScene->meshSets[k]->drawSelf();
  797. //int g = 255 * ++i / nMeshes;
  798. //sprintf (cmd, "redrawStatus #%02x%02x00", 255 - g, g);
  799. //Tcl_Eval (g_tclInterp, cmd);
  800. if (bail())
  801.   break;
  802.       }
  803.     }
  804.     
  805.     for (k = 0; k < nMeshes; k++) {
  806.       
  807.       if (theScene->meshSets[k]->transparent()) {
  808. theScene->meshSets[k]->drawSelf();
  809. //int g = 255 * ++i / nMeshes;
  810. //sprintf (cmd, "redrawStatus #%02x%02x00", 255 - g, g);
  811. //Tcl_Eval (g_tclInterp, cmd);
  812. if (bail())
  813.   break;
  814.       }
  815.     }
  816.   }
  817.   if (bDrawAnnotations) {
  818.     draw_other_things();
  819.   }
  820.   
  821.   return true;
  822. }
  823. static void
  824. glvtx(const Pnt3 &p)
  825. {
  826.   glVertex3fv(&p[0]);
  827. }
  828. void
  829. drawBoundingBox (const Bbox& box, bool bUseDefaultColor)
  830. {
  831.   vector<Pnt3> bbox_edges(24);
  832.   // don't draw the bounding box if the max is less than the min
  833.   if (box.max()[0] < box.min()[0] && 
  834.       box.max()[1] < box.min()[1] &&
  835.       box.max()[2] < box.min()[2])
  836.     return;
  837.   if (bUseDefaultColor)
  838.     glColor3f (1, 0, 0);
  839.   glPushAttrib (GL_LIGHTING_BIT);
  840.   glDisable (GL_LIGHTING);
  841.   box.edgeList(bbox_edges);
  842.   glBegin(GL_LINES);
  843.   for_each(bbox_edges.begin(), bbox_edges.end(), glvtx);
  844.   glEnd();
  845.   glPopAttrib();
  846. }
  847. static vector<RenderParams> renderParamsStack;
  848. void
  849. PushRenderParams (void)
  850. {
  851.   renderParamsStack.push_back (*theRenderParams);
  852. }
  853. void
  854. PopRenderParams (void)
  855. {
  856.   assert (renderParamsStack.size() > 0);
  857.   *theRenderParams = renderParamsStack.back();
  858.   renderParamsStack.pop_back();
  859. }
  860. #if 0  // texture code inactive
  861. #ifdef WIN32
  862. #undef PARALLEL //revisit this someday?  I just did it to get
  863.                 //this to compile... -- magi
  864. #else
  865. #include <ulocks.h>
  866. #include <task.h>
  867. #include <unistd.h>
  868. #define PARALLEL
  869. #endif
  870. #include "Xform.h"
  871. void texLightDiff(MeshSet *meshSet);
  872. void texLightAll(MeshSet *meshSet);
  873. void
  874. texLightDiff(MeshSet *meshSet)
  875. {
  876.    int nx, ny, nz;
  877.    int color;
  878. #ifdef PARALLEL
  879.    int myid = m_get_myid();
  880.    int processes = m_get_numprocs();
  881. #else
  882.    int myid = 0;
  883.    int processes = 1;
  884. #endif
  885.    int start = (meshSet->texXdim * meshSet->texYdim)/processes * myid;
  886.    int stop = (meshSet->texXdim * meshSet->texYdim)/processes * (myid+1);
  887.    float lx = theRenderParams->lightPosition[0];
  888.    float ly = theRenderParams->lightPosition[1];
  889.    float lz = theRenderParams->lightPosition[2];
  890.    Xform<float> rotxf;
  891.    float q[4], t[3];
  892.    tbView->getXform(q,t);
  893.    rotxf.rotQ(q[0], q[1], q[2], q[3]);
  894.    rotxf = rotxf * meshSet->getXform();
  895.    Pnt3 light(lx,ly,lz), newLight;
  896.    rotxf.apply(light, newLight);
  897.    lx = newLight[0]*theRenderParams->diffuse[0]*2;
  898.    ly = newLight[1]*theRenderParams->diffuse[0]*2;
  899.    lz = newLight[2]*theRenderParams->diffuse[0]*2;
  900.    uchar *buf = meshSet->texture + start*3;
  901.    uchar *newBuf = meshSet->newTexture + start;
  902.    float diff;
  903.    for (int i=start; i < stop; i++) {
  904.       nx = int(*buf++ - 128);
  905.       ny = int(*buf++ - 128);
  906.       nz = int(*buf++ - 128);
  907.       diff = nx*lx + ny*ly + nz*lz;
  908.       if (diff > 0) {
  909.  color = uchar(diff);
  910.  if (color < 0)
  911.     *newBuf++ = 0;
  912.  else if (color > 255)
  913.     *newBuf++=  255;
  914.  else
  915.     *newBuf++ = color;
  916.       } 
  917.       else {
  918.  *newBuf++ = 0;
  919.       }
  920.    }
  921. }
  922.     
  923. void
  924. texLightAll(MeshSet *meshSet)
  925. {
  926.   int nx, ny, nz;
  927.   int color;
  928. #ifdef PARALLEL
  929.   int myid = m_get_myid();
  930.   int processes = m_get_numprocs();
  931. #else
  932.   int myid = 0;
  933.   int processes = 1;
  934. #endif
  935.   Xform<float> rotxf;
  936.   float q[4], t[3];
  937.   tbView->getXform(q,t);
  938.   rotxf.rotQ(q[0], q[1], q[2], q[3]);
  939.   rotxf = rotxf * meshSet->getXform();
  940.   int start = (meshSet->texXdim * meshSet->texYdim)/processes * myid;
  941.   int stop = (meshSet->texXdim * meshSet->texYdim)/processes * (myid+1);
  942.   float lx = theRenderParams->lightPosition[0];
  943.   float ly = theRenderParams->lightPosition[1];
  944.   float lz = theRenderParams->lightPosition[2];
  945.   Pnt3 light(lx,ly,lz), newLight;
  946.   rotxf.apply(light, newLight);
  947.   lx = newLight[0];
  948.   ly = newLight[1];
  949.   lz = newLight[2];
  950.   Pnt3 viewer(0,0,1), newViewer;
  951.   rotxf.apply(viewer, newViewer);
  952.   float hx = lx + newViewer[0];
  953.   float hy = ly + newViewer[1];
  954.   float hz = lz + newViewer[2];
  955.   float hnorm = (NUM_POWER_ARGS-1)/sqrt(hx*hx + hy*hy + hz*hz)/127;
  956.   hx *= hnorm;
  957.   hy *= hnorm;
  958.   hz *= hnorm;
  959.   uchar *buf = meshSet->texture + start*3;
  960.   uchar *newBuf = meshSet->newTexture + start;
  961.   float diff, spec, hn, diffFactor, specFactor;
  962.   float *powerPtr;
  963.   specFactor = theRenderParams->specular[0] * 350;
  964.   diffFactor = 2 * theRenderParams->diffuse[0];
  965.   if (theRenderParams->shininess < NUM_POWERS) {
  966.     powerPtr = thePowers + 
  967.       int(theRenderParams->shininess) * NUM_POWER_ARGS;
  968.   }
  969.   else {
  970.     powerPtr = thePowers + (NUM_POWER_ARGS-1)*NUM_POWERS;
  971.   }
  972.   lx *= diffFactor;
  973.   ly *= diffFactor;
  974.   lz *= diffFactor;
  975.    
  976.   for (int i=start; i < stop; i++) {
  977.     nx = int(*buf++ - 128);
  978.     ny = int(*buf++ - 128);
  979.     nz = int(*buf++ - 128);
  980.     diff = nx*lx + ny*ly + nz*lz;
  981.     if (diff > 0) {
  982.       hn = nx*hx + ny*hy + nz*hz;
  983.       if (hn > 0) {
  984. //spec = pow(hn, theRenderParams->shininess) * 
  985. //   specFactor;
  986. if (hn >= NUM_POWER_ARGS)
  987.   spec = specFactor;
  988. else {
  989.   spec = *(powerPtr + int(hn)) * specFactor;
  990. }
  991.       } else {
  992. spec = 0;
  993.       }
  994.       color = uchar(diff + spec);
  995.       if      (color < 0) *newBuf++ = 0;
  996.       else if (color > 255) *newBuf++ = 255;
  997.       else                 *newBuf++ = color;
  998.     } else {
  999.       *newBuf++ = 0;
  1000.     }
  1001.   }
  1002. }
  1003. #endif // texture code