c++ - 为什么我的圆柱模型不能在 Z 轴上旋转?

标签 c++ opengl

我试图编写以下代码来绘制圆柱体。圆柱体是用 C++ 和 OpenGL 绘制的。学校给了我一个小工具,我可以用我自己的模型的 cpp 文件编译,然后可以用鼠标旋转模型。该工具不会影响我的模型的旋转,因为它适用于其他演示模型。但是,出于某种我不明白的原因,我无法在 Z 轴上旋转圆柱体以在水平 View 中查看它。因此,圆柱体只能在这些方向上旋转和观察:

enter image description here

为什么我不能旋转圆柱体以在这个方向看到它?下图是在 Photoshop 中手动旋转的,以说明模型无法旋转到的 View 方向:

enter image description here

我不明白为什么不能朝那个方向旋转,因为其他模型(其他人编写的)的演示可以在各个方向自由旋转。

这是我在 mymodel.cpp 中尝试编写的代码:

void drawCylinderObject() {
    float topRadius = 5;
    float bottomRadius = 5;
    float height = 10;
    int numOfPolygons = 50;
    float basisvec1[3] = {1, 0, 0};
    float basisvec2[3] = {0, 0, -1};
    float topPosition[3] = {0, height/2.0, 0};
    float bottomPosition[3] = {0, -height/2.0, 0};


    for(int i=0; i<numOfPolygons; i++) {
        float angle1 = (float)i/(float)numOfPolygons*2.0*M_PI;
        float angle2 = ((float)i+1.0)/(float)numOfPolygons*2.0*M_PI;
        vector<float> point1(3), point2(3), point3(3), point4(3);
        for(int j=0; j<3; j++) {
            point1[j] = topPosition[j] + topRadius * cos(angle1) * basisvec1[j] + topRadius * sin(angle1) * basisvec2[j];
        }


        for(int j=0; j<3; j++) {
            point2[j] = bottomPosition[j] + bottomRadius * cos(angle1) * basisvec1[j] + bottomRadius * sin(angle1) * basisvec2[j];

        }

        for(int j=0; j<3; j++) {
            point3[j] = bottomPosition[j] + bottomRadius * cos(angle2) * basisvec1[j] + bottomRadius * sin(angle2) * basisvec2[j];
        }

        for(int j=0; j<3; j++) {
            point4[j] = topPosition[j] + topRadius * cos(angle2) * basisvec1[j] + topRadius * sin(angle2) * basisvec2[j];
        }

        float crossvec1[3] = {point4[0]-point1[0], point4[1]-point1[1], point4[2]-point1[2]};
        float crossvec2[3] = {point2[0]-point1[0], point2[1]-point1[1], point2[2]-point1[2]};
        float normalVector1[3];

        crossProduct(crossvec2, crossvec1, normalVector1);

        glBegin(GL_POLYGON);

        glNormal3fv(normalVector1);

        glVertex3f(point1[0], point1[1], point1[2]);
        glVertex3f(point2[0], point2[1], point2[2]);
        glVertex3f(point3[0], point3[1], point3[2]);
        glVertex3f(point4[0], point4[1], point4[2]);

        glEnd();
    }
}

而我的覆盖函数是这样的,也在mymodel.cpp中:

void CRenderView::drawScene()
{
    //calls the above function
    drawCylinderObject();
}

我所做的基本上就是定义 2 个垂直的基本单位 vector ,然后将它们向外扩展一个幅度值。我通过这个 360 度循环绘制多边形以形成圆柱体。但是这种绘制方式不让我自由旋转模型有什么问题吗?

编辑:

以下是该工具绘制场景的部分代码。不知何故,该工具有大量的类。它的大部分类只是设置工具的 GUI,然后唯一绘制它的部分是 CRenderView.cpp 中的以下部分:

void CRenderView::OnPaint() 
{
    // Device context for painting
    CPaintDC dc(this); 

    // Model is stored in Document
    CToolDoc *pDoc = (CToolDoc *)GetDocument();
    ASSERT_VALID(pDoc);

    // Useful in multidoc templates
    HWND hWnd = GetSafeHwnd();
    HDC hDC = ::GetDC(hWnd);
    wglMakeCurrent(hDC,m_hGLContext);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glClearColor(m_ClearColorRed,m_ClearColorGreen,m_ClearColorBlue,1.0f);

    glPushMatrix();

    // Position / translation / scale
    glTranslated(m_xTranslation,m_yTranslation,m_zTranslation);
    glRotatef(m_xRotation, 1.0, 0.0, 0.0);
    glRotatef(m_yRotation, 0.0, 1.0, 0.0);
    glScalef(m_xScaling,m_yScaling,m_zScaling);

    // Start rendering...
    drawScene();

    glPopMatrix();

    // Double buffer
    SwapBuffers(dc.m_ps.hdc);
}

protected:
    void drawScene();

void CRenderView::OnMouseMove(UINT nFlags, 
                                                            CPoint point) 
{
    if(m_LeftButtonDown)
    {
        m_yRotation -= (float)(m_LeftDownPos.x - point.x)/3.0f;
        m_xRotation -= (float)(m_LeftDownPos.y - point.y)/3.0f;
        m_LeftDownPos = point;
        InvalidateRect(NULL,FALSE);
    }
    CView::OnMouseMove(nFlags, point);
}

最佳答案

请问,为什么要通过重新计算顶点来旋转圆柱体?只需生成一个圆柱体模型一次,然后对模型 View 矩阵执行任何以下转换。另外我认为你会想要围绕 Z 旋转,而不是 Y。

更新

那个“工具”似乎是“MFC OpenGL CView”教程的一个稍微扩展的版本。 *呸*

我看到的最大问题是,CRenderView::OnPaint 函数是由不知道如何正确使用 OpenGL 的人编写的。

void CRenderView::OnPaint() 
{
    // Device context for painting
    CPaintDC dc(this); 

    // Model is stored in Document
    CToolDoc *pDoc = (CToolDoc *)GetDocument();
    ASSERT_VALID(pDoc);

    // Useful in multidoc templates
    HWND hWnd = GetSafeHwnd();
    HDC hDC = ::GetDC(hWnd);
    wglMakeCurrent(hDC,m_hGLContext);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
    glClearColor(m_ClearColorRed,m_ClearColorGreen,m_ClearColorBlue,1.0f);

glClearColor 必须 glClear 之前被调用,因为它设置将在 glClear 调用时应用的值。这样一来,它将在下一帧的 glClear 调用上工作,或者根本不工作。

    glPushMatrix();

这里推的是哪个矩阵?这缺少对 glMatrixMode 的调用。

从一些任意矩阵开始。顺便说一句,投影集在哪里(让我猜猜,在 OnSize 处理程序中,对吧?)。

    // Position / translation / scale
    glTranslated(m_xTranslation,m_yTranslation,m_zTranslation);
    glRotatef(m_xRotation, 1.0, 0.0, 0.0);
    glRotatef(m_yRotation, 0.0, 1.0, 0.0);

您确认要绕 Z 轴旋转。那你为什么不在这里做呢?这里只有关于 X 和 Y 的旋转。问题是:您在这里使用的是欧拉角,它具有一些令人讨厌的特性并且被 3D 图形人员反对。最好使用四元数来表示旋转(只是一个建议)。

    glScalef(m_xScaling,m_yScaling,m_zScaling);

    // Start rendering...
    drawScene();

    glPopMatrix();

    // Double buffer
    SwapBuffers(dc.m_ps.hdc);
}

关于c++ - 为什么我的圆柱模型不能在 Z 轴上旋转?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7702140/

相关文章:

c++ - 我的着色器停止工作

c++ - opengl纹理

opengl - 什么时候应该使用多个纹理单元?

c++ - 一个 .cpp 文件中的多个类

c++ - 更改外部类的 VTable

c++ - 在 Eclipse (OSX) 中设置 OpenGL

opengl - 如何将 cudaArray (Cuda) 复制到 GpuMat (OpenCV)?

java - 具有 O(m (log n + log m)) 时间复杂度的算法,用于在每行排序的 n*m 矩阵中查找第 k 个最小元素?

c++ - 为什么 Xbox Controller 没有响应?

c++ - 我有 12 个 CPU,1 个插槽,每个插槽 6 个内核,每个内核 2 个线程 - 这些信息如何对应于 MPI 和 OpenMP 的并行化?