2

我需要为我的网格工具包编写一个简单的可视化工具。我正在使用的对象始终位于 [-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);
}

在初始设置期间调用 Reshape 函数,并且在每次调整可视化控件的大小后,在每次重绘时调用 PolarView 函数,其中某些角度和距离大于 3 的平方根(真的很重要吗?)。该代码适用于立方体或球体等凸面对象,但圆环对象存在一些问题(有些面是通过其他人看到的),所以我相信这是关于深度测试的东西。我的设置有什么问题?截图: 我在互联网上进行了一些搜索,发现如果我的近平面和远平面参数有问题,就会出现这样的问题。在我的情况下,这些的正确值是什么?我的绘图过程如下:
坏环面
坏环面填充

glEnable(GL_DEPTH_TEST);
glClearDepth(1);
glPolygonMode(GL_FRONT, GL_LINE); // Changing of GL_LINE to GL_FILL doesn't fixing my problem, it just changing the appearance of the model.
glClearColor(BackColor.R / 255.0f, BackColor.G / 255.0f, BackColor.B / 255.0f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
PolarView(sqrt(3), _phi, _theta);
// .. only draws 

我的像素格式描述符:

        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
    };

我找到了一些解决此问题的方法:

  • 为我的近平面和远平面交换值
  • 设置glDepthFuncGL_GREATERglClearDepth确定0
    ,如果有偶数个错误,我的代码将正常工作。但是第一个错误在哪里?
4

2 回答 2

2

你读过OpenGL 常见问题 12吗?

您的代码看起来可疑的一件事是负面的近平面。负 Z 值位于相机后面,这通常是渲染 3D 场景时的错误。但是,这本身不应该导致您看到的问题,并且 Z 的范围 [-6,6] 应该为这种场景提供足够的精度。

你在打电话glEnable(GL_DEPTH_TEST)吗?你是否传递GL_DEPTH_BUFFER_BITglClear每一帧?

更新:你打电话给glPolygonMode(GL_FRONT, GL_LINE). 这意味着正面三角形仅绘制轮廓,这意味着如果正面三角形 A 与另一个正面三角形 B 重叠,您可以通过 A 看到 B 的边缘。对于凸体,这不会发生,所以你不会注意到这个问题。

如果你想让三角形遮挡它们后面的三角形,那么你需要使用 mode 填充它们GL_FILL。为了得到一个线框图形,你需要用白色填充绘制模型,然后用黑色轮廓再次绘制模型,如下所示:

glDepthFunc(GL_LEQUAL);
glPolygonMode(GL_FRONT, GL_FILL);
/* 用白色绘制模型 */
glDepthFunc(GL_EQUAL);
glPolygonMode(GL_FRONT, GL_LINE);
/* 再次用黑色绘制模型 */

这个想法是,在模型的第二次遍历中,我们只想绘制未被第一次遍历中更靠近相机(即 Z 值较低)绘制的某个三角形遮挡的轮廓。

另一个想法:我认为你的相机可能指向错误的方向。这可以解释为什么使用 glOrtho 透视图会错误地绘制场景,而不是使用 glFrustum 透视图。在 glOrtho 案例中,整个场景都在摄像机后面绘制;这就是为什么它以错误的方式用 Z 顺序绘制。当您将近平面设置为正数时,整个场景都会被剔除。

于 2009-02-22T15:58:23.573 回答
0

“8.070 如何自动计算显示整个模型的视图?(我知道边界球和向上向量。)” OpenGL FAQ 8中的条目回答了我的问题。但是,我的设置略有不同,这是我重写的 PolarView 和 Reshape 函数:

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);
}  
于 2009-02-23T10:41:39.053 回答