在 OpenGL 中将视图更改为对象

Changing the view to object in OpenGL

我正在尝试使用 OpenGL,这是我的第一个代码。如何更改屏幕上绘制的 2 个对象的不同视图?

是否可以手动执行此操作,而不是使用函数 gluPerspective()

我尝试了 glRotatef(60, 0.0, 0.0, 5.0) 但没有任何反应。因为我想看到金字塔的其他面以及旋转球体的不同视图。

我还想为我在屏幕上绘制的不同对象设置不同的颜色,我该怎么做?

为每个对象设置颜色的代码,即 glColor3f,我把它放在 glPushMatrix()glPopMatrix() 之间,而且我总是包含行 glLoadIdentity()在开始在屏幕上绘制对象之前。据我所知,这一行将重置以前对象的设置,并允许我为新对象设置新属性。

那为什么当我按下按钮 D 时,本该是白色的球体却是蓝色的?

这是我的完整代码:

#include <windows.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <math.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#define X .525731112119133606
#define Z .850650808352039932
#define Y 0.0
#define PI 3.1415926535898
#define CIRCLE_STEP 5000

using namespace std;

// Open an OpenGL window
GLFWwindow* window;
int keyboard = 0, itr;
bool big_Sphere = true, sphereWithNormalV = false, animation = false;
GLdouble angle = 0;

/****Step 1: define vertices in (x, y, z) form****/

// Coordinates to draw a Icosahedron
GLfloat icoVertices[12][3] = {
    {-X, Y, Z}, {X, Y, Z}, {-X, Y, -Z}, {X, Y, -Z},
   {Y, Z, X}, {Y, Z, -X}, {Y, -Z, X}, {Y, -Z, -X},
   {Z, X, Y}, {-Z, X, Y}, {Z, -X, Y}, {-Z, -X, Y}
};

// Coordinates to draw a Pyramid
GLfloat pyVertices[4][3] = {
    {0.0f, 1.0f, 0.0f},
    {1.0f, 0.0f, 0.0f},
    {-1.0f, 0.0f, 0.0f},
    {0.0f, 0.0f, -1.0f}
};

static GLuint icoIndices[20][3] = {
   {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
   {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
   {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
   {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };

static GLuint pyIndices[4][3] = {
   {0,1,2}, {0,1,3}, {0,2,3}, {1,2,3}
};
/************************/

void normalize3f(float v[3]) {
   GLfloat d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
   if (d == 0.0) {
      fprintf(stderr, "zero length vector");
      return;
   }
   v[0] /= d; v[1] /= d; v[2] /= d;
}

void sphereNormalV(GLfloat p1[3], GLfloat p2[3], GLfloat p3[3])
{
    glBegin(GL_LINES);
    glVertex3f(p1[0] *1.5,p1[1] *1.5, p1[2] *1.5);
    glVertex3fv(p1);
    glEnd();

    glBegin(GL_LINES);
    glVertex3f(p2[0] *1.1,p2[1] *1.1, p2[2] *1.1);
    glVertex3fv(p2);
    glEnd();

    glBegin(GL_LINES);
    glVertex3f(p3[0] *1.1,p3[1] *1.1, p3[2] *1.1);
    glVertex3fv(p3);
    glEnd();
}

void drawtriangle(float *v1, float *v2, float *v3)
{
    glBegin(GL_LINE_LOOP);
    //glNormal3fv(v1);
    glVertex3fv(v1);
    //glNormal3fv(v2);
    glVertex3fv(v2);
    //glNormal3fv(v3);
    glVertex3fv(v3);
    glEnd();
}

void subdivide(GLfloat *v1, GLfloat *v2, GLfloat *v3, long depth)
{
   GLfloat v12[3], v23[3], v31[3];
   GLint i;

    if (depth == 0){
        drawtriangle(v1, v2, v3);
        if (sphereWithNormalV == true){
            sphereNormalV(v1, v2, v3);
        }
        return;
    }
   for (i = 0; i < 3; i++) {
      v12[i] = v1[i]+v2[i];
      v23[i] = v2[i]+v3[i];
      v31[i] = v3[i]+v1[i];
   }

   normalize3f(v12);
   normalize3f(v23);
   normalize3f(v31);
   subdivide(v1, v12, v31, depth-1);
   subdivide(v2, v23, v12, depth-1);
   subdivide(v3, v31, v23, depth-1);
   subdivide(v12, v23, v31, depth-1);
}

void drawSphere(GLfloat x, GLfloat y, GLfloat z){
    glLoadIdentity();
    glPushMatrix();
    if (big_Sphere == true){
        glScaled(0.4, 0.55, 0.4);
    }else{
        glScaled(0.13, 0.18, 0.13);
    }

    if (animation){
        glTranslatef(x, y, z);
    }

    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < 20; i++) {
       subdivide(&icoVertices[icoIndices[i][0]][0], &icoVertices[icoIndices[i][1]][0], &icoVertices[icoIndices[i][2]][0], 3);
    }
    glEnd();
    glPopMatrix();
}

void drawPyramid(){//(GLfloat x, GLfloat y, GLfloat z){
    glLoadIdentity();
    glPushMatrix();
    glScaled(0.13, 0.18, 0.13);
    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < 4; i++){
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3fv(pyVertices[pyIndices[i][0]]);
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3fv(pyVertices[pyIndices[i][1]]);
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3fv(pyVertices[pyIndices[i][2]]);
    }
    glEnd();
    glPopMatrix();
}

int getKeyPressed(){
    if (glfwGetKey(window, GLFW_KEY_A)){
        keyboard = GLFW_KEY_A;
    }

    if (glfwGetKey(window, GLFW_KEY_B)){
        keyboard = GLFW_KEY_B;
    }

    if (glfwGetKey(window, GLFW_KEY_C)){
        keyboard = GLFW_KEY_A;
    }

    if (glfwGetKey(window, GLFW_KEY_D)){
        keyboard = GLFW_KEY_D;
    }

    if (glfwGetKey(window, GLFW_KEY_E)){
        keyboard = GLFW_KEY_E;
    }

    return keyboard;
}

void controlSphere(bool _big_Sphere, bool _sphereNormalV, bool _animation){
    big_Sphere = _big_Sphere;
    sphereWithNormalV = _sphereNormalV;
    animation = _animation;
}

void gluPerspective(double fovy,double aspect, double zNear, double zFar)
{
 // Start in projection mode.
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 double xmin, xmax, ymin, ymax;
 ymax = zNear * tan(fovy * PI / 360.0);
 ymin = -ymax;
 xmin = ymin * aspect;
 xmax = ymax * aspect;
 glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}

int main( void ) {
    if (!glfwInit()){
        fprintf(stderr, "Failed to initialize GLFW.\n");
        return -1;
    }

    // Create a windowed mode window and its OpenGL context
    window = glfwCreateWindow(1100, 800, "Hello World", NULL, NULL);
    if (window == NULL) {
            fprintf(stderr, "glfw failed to create window.\n");
            //glfwTerminate();
            return -1;
            }
    // Make the window's context current
    glfwMakeContextCurrent(window);

    glewInit();
    if (glewInit() != GLEW_OK){
        fprintf(stderr, "Failed to initialize GLEW: %s.\n", glewGetErrorString(glewInit()));
        return -1;
    }
    // 4x anti aliasing
    glfwWindowHint(GLFW_SAMPLES, 4);

    /**Step 3: Main loop for OpenGL draw the shape**
    /* Main loop */
    int i = 0;
    GLfloat pos_X, pos_Y;
    glRotatef(60, 0.0f, 0.3f, 0.4f);

    do{

        //glMatrixMode(GL_MODELVIEW);
        glClear(GL_COLOR_BUFFER_BIT);

        switch(getKeyPressed()){
            case 65:
                controlSphere(true, false, false);
                drawSphere(0, 0, 0);
                break;
            case 66:
                controlSphere(true, true, false);
                drawSphere(0, 0, 0);
                break;
            case 67:
//                drawPyramid();
                break;
            case 68:
                // drawing a Sphere moving in a circular path
                controlSphere(false, false, true);
                angle = 2*PI*i/CIRCLE_STEP;
                pos_X = cos(angle) * 4.5;
                pos_Y = sin(angle) * 4.5;
                drawSphere(pos_X, pos_Y, 0);
                i += 1;
                angle += 1;
                if (angle >= 360){
                    angle = 0;
                }

                // drawing a Pyramid rotate around its y axis
                drawPyramid();
                break;
            default:
                controlSphere(true, false, false);
                drawSphere(0, 0, 0);
                break;
        }

        Sleep(1);
        // Swap front and back rendering buffers
        glfwSwapBuffers(window);

        //Poll for and process events
        glfwPollEvents();
    } // check if the ESC key was pressed or the window was closed
    while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
    /***********************************************/


    // Close window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();
    // Exit program
    exit( EXIT_SUCCESS );
}

您正在寻找允许分割屏幕的多视口。在您的情况下,两个不同的视口两个不同的相机(每个相机一个)就足够了。

检查此 post

Is there anyway to do this manually, in stead of using function gluPerspective()?

这个问题我不是很懂。但是如果你想设置具有不同变换、缩放、旋转 and/or 平移的多个对象(具有相同的参数),你需要将其推入堆栈,然后绘制所需的对象。可以在这里找到一个很好的起点:http://www.songho.ca/opengl/gl_transform.html

Also I want to set different colours to different objects that I draw on the screen, how can I do that?

您的球体是蓝色的,因为对 glColor3f() 的最后一次调用是在 drawPyramid()

您可以通过在绘制函数的开头调用 glColor3f (1.0f, 1.0f, 1.0f); 来更改球的颜色:

void drawSphere (GLfloat x, GLfloat y, GLfloat z)
{
   glColor3f (1.0f, 1.0f, 1.0f);
   ...
}

从旧管道(您刚刚实现的)到新管道 (GLSL) 学习 OpenGL 的一个非常好的网站是 http://www.lighthouse3d.com/tutorials/