Winapi 如何正确设置OpenGL场景以可视化单个对象

Winapi 如何正确设置OpenGL场景以可视化单个对象,winapi,opengl,wgl,Winapi,Opengl,Wgl,我需要为我的网格工具包编写一个简单的可视化工具。我正在使用的对象始终位于[-1,1]^3框(含)内,因此我需要确保用户完全可以看到该对象。我还想有一个可能性,旋转一个物体周围的相机,就像用户是“飞行”周围的物体 我就是这样做的: static void Reshape(int w, int h) { glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity()

我需要为我的网格工具包编写一个简单的可视化工具。我正在使用的对象始终位于[-1,1]^3框(含)内,因此我需要确保用户完全可以看到该对象。我还想有一个可能性,旋转一个物体周围的相机,就像用户是“飞行”周围的物体

我就是这样做的:

static void Reshape(int w, int h)
{
    glViewport(0,0,(GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    float maxDistance = sqrt(2);
    if (w <= h)
    {
        glOrtho(-maxDistance, maxDistance, -maxDistance * (GLfloat)h / (GLfloat)w,
            maxDistance * (GLfloat)h / (GLfloat)w, -6.0, 6.0);
    }
    else
    {
        glOrtho(-maxDistance * (GLfloat)w / (GLfloat)h, maxDistance * (GLfloat)w / (GLfloat)h,
            -maxDistance, maxDistance, -6.0, 6.0);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

static void PolarView(GLdouble distance, GLdouble twist, GLdouble elevation)
{
    double centerx, centery, centerz;
    double eyex, eyey, eyez;

    eyex = distance * cos(-twist) * cos(elevation);
    eyey = distance * sin(-twist) * cos(elevation);
    eyez = distance * sin(elevation);
    centerx = centery = centerz = 0;

    gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0, 0, 1);
}
我的像素格式描述符:

        PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        32, // Depth buffer size
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0,
        0,
        0
    };

我找到了一些解决方法:

  • 交换近平面和远平面的值
  • glDepthFunc
    设置为
    GL\u更大
    并将
    glClearDepth
    设置为
    0

    好的,如果出现偶数个错误,我的代码将正常工作。但第一个错误在哪里
    • 你读过吗

      你的代码有一点可疑,那就是近平面的负数。负Z值位于摄影机后面,这在渲染3D场景时通常是错误的。然而,这本身不应该引起您看到的问题,Z的范围[-6,6]应该为这种场景提供足够的精度

      您正在呼叫glEnable(GL_深度_测试)?您是否将
      GL\u DEPTH\u BUFFER\u位
      传递给
      glClear
      每一帧

      更新:您正在调用
      glPolygonMode(GL\u-FRONT,GL\u-LINE)
      。这意味着前向三角形仅以轮廓绘制,这意味着如果前向三角形A与另一个前向三角形B重叠,则您可以通过A看到B的边缘。对于凸体,这不会发生,因此您不会注意到问题

      如果希望三角形遮挡其后面的三角形,则需要使用模式
      GL\u fill
      填充它们。要获得线框图形,需要使用白色填充绘制模型,然后使用黑色轮廓再次绘制模型,如下所示:

      glDepthFunc(GL_LEQUAL); glPolygonMode(GL_FRONT, GL_FILL); /* draw the model in white */ glDepthFunc(GL_EQUAL); glPolygonMode(GL_FRONT, GL_LINE); /* draw the model again in black */ glDepthFunc(GL_LEQUAL); glPolygonMode(GL_前端,GL_填充); /*把模型画成白色*/ glDepthFunc(GL_等于); glPolygonMode(GL_前端,GL_线); /*再次以黑色绘制模型*/ 我们的想法是,在模型的第二个过程中,我们只想绘制轮廓,这些轮廓不会被第一个过程中绘制的更靠近摄影机的三角形(即Z较低的三角形)遮挡

      另一个想法:我认为你的相机可能指向错误的方向。这就解释了为什么使用glOrtho透视图绘制场景是错误的,而使用glFrustum透视图绘制场景是错误的。在格洛托的案例中,整个场景都在摄影机后面绘制;这就是为什么它的Z顺序画错了。将“近平面”设置为正数时,将剔除整个场景。

      “8.070如何自动计算显示整个模型的视图?(我知道边界球体和上方向向量)。”中的条目回答了我的问题。但是,我的设置略有不同,以下是我重写的PolarView和重塑功能:

      static void Reshape(int w, int h)
      {
          float diameter = sqrt(3);
          glViewport(0, 0, (GLsizei)w, (GLsizei)h);
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
          GLdouble zNear = 1;
          GLdouble zFar = zNear + diameter * 2;
          GLdouble left = -diameter;
          GLdouble right = diameter;
          GLdouble top = -diameter;
          GLdouble bottom = diameter;
          double aspect = (double)w / (double)h;
          if (aspect < 1)
          {
              bottom /= aspect;
              top /= aspect;
          }
          else
          {
              left *= aspect;
              right *= aspect;
          }
          glOrtho(left, right, bottom, top, zNear, zFar);
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
      }
      
      static void PolarView(GLdouble twist, GLdouble elevation)
      {
          float diameter = sqrt(3);
          double distance = diameter * 2;
          double centerx, centery, centerz;
          double eyex, eyey, eyez;
      
          eyex = distance * cos(twist) * cos(elevation);
          eyey = distance * sin(twist) * cos(elevation);
          eyez = distance * sin(elevation);
          centerx = centery = centerz = 0;
          gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0, 0, 1);
      }  
      
      静态空洞重塑(int w,int h)
      {
      浮子直径=sqrt(3);
      GLVIEW(0,0,(GLsizei)w,(GLsizei)h);
      glMatrixMode(GL_投影);
      glLoadIdentity();
      glznear=1;
      GLZfar=zNear+直径*2;
      GLdouble left=-直径;
      GLdouble right=直径;
      gl双顶部=-直径;
      GLD双底=直径;
      双方向=(双)w/(双)h;
      如果(方面<1)
      {
      底部/=侧面;
      顶端/=侧面;
      }
      其他的
      {
      左*=纵横比;
      右*=方面;
      }
      格洛托(左、右、下、上、zNear、zFar);
      glMatrixMode(GLU模型视图);
      glLoadIdentity();
      }
      静态空心PolarView(GLdouble twist,GLdouble elevation)
      {
      浮子直径=sqrt(3);
      双倍距离=直径*2;
      双centerx、centery、centerz;
      双目镜,双目镜,双目镜;
      eyex=距离*cos(扭转)*cos(仰角);
      eyey=距离*sin(扭转)*cos(仰角);
      eyez=距离*sin(高程);
      centerx=centery=centerz=0;
      gluLookAt(eyex,eyey,eyez,centerx,centery,centerz,0,0,1);
      }  
      
      您需要详细说明问题所在。这很难理解。甚至可能是一个屏幕截图?那个链接对我没有帮助。我在问题中添加了更多的代码。无论我如何绘制多边形(GL_线或GL_填充),问题仍然存在。有没有证据表明使用GL_线渲染不应该使用深度缓冲区?你能照我上面建议的那样拍摄模型的屏幕截图吗?上传了带有平面填充面的新渲染模型。你使用的是glOrtho,这使得区分(查看)哪些三角形近/远有点困难。如果生成网格时遇到问题,则必须按特定顺序生成三角形。看见
      static void Reshape(int w, int h)
      {
          float diameter = sqrt(3);
          glViewport(0, 0, (GLsizei)w, (GLsizei)h);
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
          GLdouble zNear = 1;
          GLdouble zFar = zNear + diameter * 2;
          GLdouble left = -diameter;
          GLdouble right = diameter;
          GLdouble top = -diameter;
          GLdouble bottom = diameter;
          double aspect = (double)w / (double)h;
          if (aspect < 1)
          {
              bottom /= aspect;
              top /= aspect;
          }
          else
          {
              left *= aspect;
              right *= aspect;
          }
          glOrtho(left, right, bottom, top, zNear, zFar);
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
      }
      
      static void PolarView(GLdouble twist, GLdouble elevation)
      {
          float diameter = sqrt(3);
          double distance = diameter * 2;
          double centerx, centery, centerz;
          double eyex, eyey, eyez;
      
          eyex = distance * cos(twist) * cos(elevation);
          eyey = distance * sin(twist) * cos(elevation);
          eyez = distance * sin(elevation);
          centerx = centery = centerz = 0;
          gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0, 0, 1);
      }