c++ - 曲面 segmentation 的理论与算法

标签 c++ opengl math geometry

我有以下问题:

下面是我在屏幕上绘制立方体的方法:

void drawCube()
{

    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
    glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT) ;

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;
    //glDisable(GL_LIGHTING) ;

    glBegin(GL_QUADS);                // Begin drawing the color cube with size 3cm x 3.5cm x 4cm
        // Top face (y = 1.0f)
        // Define vertices in counter-clockwise (CCW) order with normal pointing out
        glColor3f(0.0f, 1.0f, 0.0f);     // Green
        glVertex3f( 1.75f, 1.75f, -4.0f);
        glVertex3f(-1.75f, 1.75f, -4.0f);
        glVertex3f(-1.75f, 1.75f,  1.0f);
        glVertex3f( 1.75f, 1.75f,  1.0f);

        // Bottom face (y = -1.0f)
        glColor3f(1.0f, 0.5f, 0.0f);     // Orange
        glVertex3f( 1.75f, -1.75f,  1.0f);
        glVertex3f(-1.75f, -1.75f,  1.0f);
        glVertex3f(-1.75f, -1.75f, -4.0f);
        glVertex3f( 1.75f, -1.75f, -4.0f);

        // Front face  (z = 1.0f)
        glColor3f(1.0f, 0.0f, 0.0f);     // Red
        glVertex3f( 1.75f,  1.75f, 1.0f);
        glVertex3f(-1.75f,  1.75f, 1.0f);
        glVertex3f(-1.75f, -1.75f, 1.0f);
        glVertex3f( 1.75f, -1.75f, 1.0f);

        // Back face (z = -1.0f)
        glColor3f(1.0f, 1.0f, 0.0f);     // Yellow
        glVertex3f( 1.75f, -1.75f, -4.0f);
        glVertex3f(-1.75f, -1.75f, -4.0f);
        glVertex3f(-1.75f,  1.75f, -4.0f);
        glVertex3f( 1.75f,  1.75f, -4.0f);

        // Left face (x = -1.0f)
        glColor3f(0.0f, 0.0f, 1.0f);     // Blue
        glVertex3f(-1.75f,  1.75f,  1.0f);
        glVertex3f(-1.75f,  1.75f, -4.0f);
        glVertex3f(-1.75f, -1.75f, -4.0f);
        glVertex3f(-1.75f, -1.75f,  1.0f);

        // Right face (x = 1.0f)
        glColor3f(1.0f, 0.0f, 1.0f);     // Magenta
        glVertex3f(1.75f,  1.75f, -4.0f);
        glVertex3f(1.75f,  1.75f,  1.0f);
        glVertex3f(1.75f, -1.75f,  1.0f);
        glVertex3f(1.75f, -1.75f, -4.0f);
    glEnd();  // End of drawing color-cube


    glPopAttrib() ;
}

问题是如何在所有顶点之间分配“样本点”?

根据我的理解,我需要找到顶点之间的距离并将其分成(比如说)五个相等的部分。为了便于论证,假设两个顶点之间的间距为 1,因此 5 个点将放置在彼此相距 0.2 的距离上。此外,它们需要存储在某种内存结构( vector/数组)中,以便它们中的每一个都可以在稍后阶段访问并转换为屏幕坐标。

但是,我如何才能以完全通用的方式在 C++ 中执行此操作,以便基本上可以将其应用于任何距离度量?

Here is how the cube looks like

最佳答案

这是我的 drawBox 函数,如果您愿意,可以修改它以在每个面上绘制不同的颜色。

void DrawBox(GLfloat fWidth,GLfloat fHeight,GLfloat fDepth,GLint wslices,GLint dslices,GLint stacks)
{
     // Calculate number of primitives on each side of box
     // because we can use different tessalation configurations 
     // we must calculate separate group of box sides 

    int iTopButtonQuads = wslices * dslices * 2; // Calculate number of quads in top and button sides
    int iLeftRightQuads = dslices * stacks * 2; // Calculate number of quads in left and right sides
    int iFrontBackQuads = wslices * stacks * 2; // Calculate number of quads in front and back sides

    // If we consider to use quads as primitive then each primitive will
    // have 4 points, and each point has color, coord and normal attribute.
    // So we create separate array to contain each attibute values.

    float* pfVertices = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];
    float* pfColors = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];
    float* pfNormals = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];

    int iVertexIndex = 0;

    GLfloat Xstep = fWidth / wslices;
    GLfloat Ystep = fHeight / stacks;
    GLfloat Zstep = fDepth / dslices;

    GLfloat firstX = fWidth / 2.0f;
    GLfloat firstY = fHeight / 2.0f;
    GLfloat firstZ = fDepth / 2.0f;

    GLfloat currX = 0.0f;
    GLfloat currY = 0.0f;
    GLfloat currZ = 0.0f;

    GLfloat x_status = 0.0f;
    GLfloat y_status = 0.0f;
    GLfloat z_status = 0.0f;

    // the bottom and the top of the box
    for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
    {
        for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
        {
            int iCurrentIndex = iVertexIndex * 3 * 4;

            float pfNormal[3] = { 0.0f, -1.0f, 0.0f };

            memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

            float pfColor[3] = { 1.0f, 0.0f, 0.0f };

            memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

            float pfVertex0[3] = {currX,-firstY,currZ};
            float pfVertex1[3] = {currX + Xstep,-firstY,currZ};
            float pfVertex2[3] = {currX + Xstep,-firstY,currZ + Zstep};
            float pfVertex3[3] = {currX,-firstY,currZ + Zstep};

            memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

            iVertexIndex++;
        }

        for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
        {
            int iCurrentIndex = iVertexIndex * 3 * 4;

            float pfNormal[3] = { 0.0f, 1.0f, 0.0f };

            memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

            float pfColor[3] = { 0.0f, 1.0f, 0.0f };

            memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

            float pfVertex0[3] = {currX + Xstep,firstY,currZ + Zstep};
            float pfVertex1[3] = {currX + Xstep,firstY,currZ};
            float pfVertex2[3] = {currX,firstY,currZ};
            float pfVertex3[3] = {currX,firstY,currZ + Zstep};

            memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

            iVertexIndex++;
        }
    }

    // the front and the back of the box
    for (currY = -firstY, y_status = 0.0f; currY < firstY - Ystep / 2.0f ; currY += Ystep, y_status += Ystep)
    {
        for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
        {
            int iCurrentIndex = iVertexIndex * 3 * 4;

            float pfNormal[3] = { 0.0f, 0.0f, 1.0f };

            memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

            float pfColor[3] = { 0.0f, 0.0f, 1.0f };

            memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

            float pfVertex0[3] = {currX,currY,firstZ};
            float pfVertex1[3] = {currX + Xstep,currY,firstZ};
            float pfVertex2[3] = {currX + Xstep,currY + Ystep,firstZ};
            float pfVertex3[3] = {currX,currY + Ystep,firstZ};

            memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

            iVertexIndex++;
        }

        for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
        {
            int iCurrentIndex = iVertexIndex * 3 * 4;

            float pfNormal[3] = { 0.0f, 0.0f, -1.0f };

            memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

            float pfColor[3] = { 0.0f, 1.0f, 1.0f };

            memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

            float pfVertex0[3] = {currX + Xstep,currY + Ystep,-firstZ};
            float pfVertex1[3] = {currX + Xstep,currY,-firstZ};
            float pfVertex2[3] = {currX,currY,-firstZ};
            float pfVertex3[3] = {currX,currY + Ystep,-firstZ};

            memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

            iVertexIndex++;
        }
    }

    // Right side and the left side of the box
    for (currY = -firstY, y_status = 0.0f; currY < firstY - Ystep / 2.0f; currY += Ystep, y_status += Ystep)
    {
        for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
        {
            int iCurrentIndex = iVertexIndex * 3 * 4;

            float pfNormal[3] = { 1.0f, 0.0f, 0.0f };

            memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

            float pfColor[3] = { 1.0f, 0.0f, 1.0f };

            memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

            float pfVertex0[3] = {firstX,currY,currZ};
            float pfVertex1[3] = {firstX,currY + Ystep,currZ};
            float pfVertex2[3] = {firstX,currY + Ystep,currZ + Zstep};
            float pfVertex3[3] = {firstX,currY,currZ + Zstep};

            memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

            iVertexIndex++;
        }

        for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
        {
            int iCurrentIndex = iVertexIndex * 3 * 4;

            float pfNormal[3] = { -1.0f, 0.0f, 0.0f };

            memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
            memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

            float pfColor[3] = { 1.0f, 1.0f, 0.0f };

            memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
            memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

            float pfVertex0[3] = {-firstX,currY,currZ};
            float pfVertex1[3] = {-firstX,currY,currZ + Zstep};
            float pfVertex2[3] = {-firstX,currY + Ystep,currZ + Zstep};
            float pfVertex3[3] = {-firstX,currY + Ystep,currZ};

            memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
            memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

            iVertexIndex++;
        }
    }

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glColorPointer(3, GL_FLOAT, 0, (void*)pfColors);
    glNormalPointer(GL_FLOAT, 0, (void*)pfNormals);
    glVertexPointer(3, GL_FLOAT, 0, (void*)pfVertices);

    glDrawArrays(GL_QUADS, 0, (iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

    delete [] pfVertices;
    delete [] pfNormals;
    delete [] pfColors;
}

结果是这样的

enter image description here

这是使用创建数组的示例,用于收集一些形状统计信息

    // Example 
    // Find min-max of shapes coordinates

    // Get coord of first vertex
    float fMinX = pfVertices[0];
    float fMinY = pfVertices[1];
    float fMinZ = pfVertices[2];

    float fMaxX = pfVertices[0];
    float fMaxY = pfVertices[1];
    float fMaxZ = pfVertices[2];

    for (int iVertexIndex = 0; iVertexIndex < (iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 4; iVertexIndex++)
    {
        int iCurrentIndex = iVertexIndex * 3; // (x y z) per vertex

        if (pfVertices[iCurrentIndex] < fMinX)
            fMinX = pfVertices[iCurrentIndex];

        if (pfVertices[iCurrentIndex + 1] < fMinY)
            fMinY = pfVertices[iCurrentIndex + 1];

        if (pfVertices[iCurrentIndex + 2] < fMinZ)
            fMinZ = pfVertices[iCurrentIndex + 2];

        if (pfVertices[iCurrentIndex] > fMaxX)
            fMaxX = pfVertices[iCurrentIndex];

        if (pfVertices[iCurrentIndex + 1] > fMaxY)
            fMaxY = pfVertices[iCurrentIndex + 1];

        if (pfVertices[iCurrentIndex + 2] > fMaxZ)
            fMaxZ = pfVertices[iCurrentIndex + 2];
    }

    // Create an axes aligned bounding box 
    // by simply drawing inflated min-maxes, that we collect
    // example of using indexed primitives

    glDisable(GL_CULL_FACE);

    GLfloat vertices[] = {
        fMinX - 2.0, fMaxY + 2.0, fMaxZ + 2.0,
        fMaxX + 2.0, fMaxY + 2.0, fMaxZ + 2.0,
        fMaxX + 2.0, fMinY - 2.0, fMaxZ + 2.0,
        fMinX - 2.0, fMinY - 2.0, fMaxZ + 2.0,
        fMinX - 2.0, fMaxY + 2.0, fMinZ - 2.0,
        fMaxX + 2.0, fMaxY + 2.0, fMinZ - 2.0,
        fMaxX + 2.0, fMinY - 2.0, fMinZ - 2.0,
        fMinX - 2.0, fMinY - 2.0, fMinZ - 2.0
    };

    GLint indices[] = {
        0, 1, 2, 3,
        4, 5, 1, 0,
        3, 2, 6, 7,
        5, 4, 7, 6,
        1, 5, 6, 2,
        4, 0, 3, 7 
    };

    glColor3f(1.0f, 1.0f, 1.0f);

    glEnableClientState(GL_VERTEX_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, (void*)vertices);

    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (void*)indices);

    glDisableClientState(GL_VERTEX_ARRAY);

    glEnable(GL_CULL_FACE);

关于c++ - 曲面 segmentation 的理论与算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33124211/

相关文章:

java - 尽管链接和验证成功,为什么着色器程序无法编译?

java - 用户输入问题的代码双方程错误

c++ - 预定义派生类

c++ - 将直接值传递给 CreateIoCompletionPort() 的 CompletionKey 参数

c++ - 重载 operator->() 以更改被调用函数的返回值

OpenGL 4 采用

opengl - 为什么人们不将四面体用于天空盒?

c++ - 简单的计算给出了错误的结果

algorithm - 多重嵌套循环索引

c++ - constexpr 和数组