如何选择要转换的特定视口,同时在OpenGL

时间:2016-10-10 00:31:38

标签: c++ opengl visual-studio-2015

所以这是我本应该做的一项任务,我目前关注的指导方针是:

用户可以通过单击选择“活动”视口(您应该更改颜色) 选择视口时的边框)。任何转换(轮换,翻译等)都应该是 仅在活动视口上执行。

用户应该能够使用WASD键和/或箭头在所选视口中导航场景 键(用于正投影)。鼠标控制(如在FPS游戏中)和WASD键和/或箭头 用于透视投影。只应在活动视口中允许导航。该 其他视口应保持静止。

我已经有了能够以fps方式转换透视视图的代码,并为前视图硬编码了一些相机转换,但我似乎无法弄清楚如何制作一个可以区分视口,如果我可以,我将能够只是插入代码转换为。我目前正在使用mouseclickcallback函数来检测鼠标的位置,但主要的问题是它在我的displaycallbackfunction之后运行,这是创建和运行视口的地方,这意味着我必须找到一种方法来实现它,所以我可以从显示功能转换而不是检测它的鼠标。

我的一些代码是:

void DisplayCallbackFunction(void)
{
/* clear the screen */
glViewport(0, 0, windowWidth, windowHeight);
glClearColor(0.2f, 0.2f, 0.2f, 0.8f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

//create viewport
setViewport(1);

//Perspective
//glFrustum(-1.0f,1.0f, -1.0f, 1.0f, 1.0f, 100);
gluPerspective(45.0f,1.0f, 0.1f, 100.0f);

//Orthographic
//glOrtho(-1.0f, 1.0f, -1.0, 1.0, 1.0f, 100.0f);
//gluOrtho2D(1.0f, 1.0f, 1.0f, 1.0f);


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/*
if (x < windowWidth / 2 && y < windowHeight / 2) {

    viewport = 3;
    std::cout << "Viewport =" << viewport << std::endl;
}
if (x > windowWidth / 2 && y < windowHeight / 2) {
    viewport = 4;
    std::cout << "Viewport =" << viewport << std::endl;
}
if (x > windowWidth / 2 && y > windowHeight / 2) {
    viewport = 2;
    std::cout << "Viewport =" << viewport << std::endl;
}
if (x < windowWidth / 2 && y > windowHeight / 2) {
    viewport = 1;
    std::cout << "Viewport =" << viewport << std::endl;
}
break;*/

    gluLookAt(
        cameraPosition.x, cameraPosition.y, cameraPosition.z,// camera position
        cameraPosition.x + forwardVector.x,
        cameraPosition.y + forwardVector.y,
        cameraPosition.z + forwardVector.z,// what the camera is looking at 
        0.0f, 1.0f, 0.0f);//what the camera thinks is up


/* This is where we draw things */
//glColor3f(0.5f, 0.8f, 0.1f); //RGB  or 4f-> RGBA
//drawObjects();


//cube code is here




//second viewport
setViewport(2);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();


gluLookAt(
    rz, rz2, 6.0f,// camera position
    rz, rz2, 0.0f,// what the camera is looking at 
    0.0f, 1.0f, 0.0f);//what the camera thinks is up



//other cube

//third viewport
setViewport(3);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
    -6.0f, 0.0f, 0.0f,// camera position
    0.0f, 0.0f, 0.0f,// what the camera is looking at 
    0.0f, 1.0f, 0.0f);//what the camera thinks is up
//3rd cube

//fourth viewport
setViewport(4);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
    0.0f, 6.0f, 0.0f,// camera position
    0.0f, 0.0f, 0.0f,// what the camera is looking at 
    0.0f, 0.0f, 1.0f);//what the camera thinks is up

//fourth cube

//HUD or Overlay viewport

glViewport(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS);
glVertex3f(-0.02, -1.0, 0.0);// bottom left
glVertex3f(0.02, -1.0, 0.0); //bottom right
glVertex3f(0.02, 1.0, 0.0); // top right
glVertex3f(-0.02, 1.0, 0.0); // top left
glBegin(GL_QUADS);
glVertex3f(-1.0, -0.02, 0.0);// bottom left
glVertex3f(1.0, -0.02, 0.0); //bottom right
glVertex3f(1.0, 0.02, 0.0); // top right
glVertex3f(-1.0, 0.02, 0.0); // top left
glBegin(GL_QUADS);
glVertex3f(0.0, 0.0, 0.0);// bottom left
glVertex3f(0.02, 0.0, 0.0); //bottom right
glVertex3f(0.02, 1.0, 0.0); // top right
glVertex3f(0.0, 1.0, 0.0); // top left
glEnd();

/* Swap Buffers to Make it show up on screen */
glutSwapBuffers();
}
void KeyboardCallbackFunction(unsigned char key, int x, int y)
{
std::cout << "Key Down:" << (int)key << std::endl;



switch (key)
{
case 32: // the space bar
    break;
case 27: // the escape key
//case 'q': // the 'q' key
    exit(0);
    break;
case 'W':
case 'w':
    cameraPosition += (forwardVector * movementScalar);
    break;
case 'S':
case 's':
    cameraPosition -= (forwardVector * movementScalar);
    break;
case 'A':
case 'a':
    rightVector = glm::cross(forwardVector, glm::vec3(0.0f, 1.0f, 0.0f));
    rightVector = glm::normalize(rightVector);
    cameraPosition -= (rightVector * movementScalar);
        break;
case 'D':
case 'd':
    rightVector = glm::cross(forwardVector, glm::vec3(0.0f, 1.0f, 0.0f));
    rightVector = glm::normalize(rightVector);
    cameraPosition += (rightVector * movementScalar);
    break;





}
}




void SpecialInput(int key, int x, int y)
{
switch (key)
{


case GLUT_KEY_LEFT:

    rz += 1.0;
    break;

case GLUT_KEY_RIGHT:
    rz -= 1.0f;
    break;
case GLUT_KEY_UP:
    rz2 -= 1.0f;
    break;

case GLUT_KEY_DOWN:
    rz2 += 1.0f;
    break;
}

glutPostRedisplay();
}

void MouseClickCallbackFunction(int button, int state, int x, int y)
{
// Handle mouse clicks
switch (button) {

    if (state == GLUT_DOWN) {
case GLUT_RIGHT_BUTTON:
    std::cout << "Mouse X: " << x << "Mouse Y: " << y << std::endl;

    break;
case GLUT_LEFT_BUTTON:
    std::cout << "Mouse X: " << x << "Mouse Y: " << y << std::endl;
    if (x < windowWidth / 2 && y < windowHeight / 2) {

        viewport = 3;
        std::cout << "Viewport =" << viewport<<std::endl;
    }
    if (x > windowWidth / 2 && y < windowHeight / 2) {
        viewport = 4;
        std::cout << "Viewport ="<< viewport << std::endl;
    }
    if (x > windowWidth / 2 && y > windowHeight / 2) {
        viewport = 2;
        std::cout << "Viewport ="<< viewport << std::endl;
    }
    if (x < windowWidth / 2 && y > windowHeight / 2) {
        viewport = 1;
        std::cout << "Viewport ="<< viewport << std::endl;
    }
    break;
    }




}
}

所以我可能已经搞砸了,因为这应该是午夜时分,老师并没有告诉我们足够的信息来正确地完成这个。如果有人能告诉我如何通过左键单击选择要转换的特定视口,我将不胜感激,然后通过箭头键转换相机。

2 个答案:

答案 0 :(得分:0)

实际上你知道你需要做的一切。 OpenGL不会为您保存状态。相反,您负责记住状态并将其传输到您呈现的每个视口的OpenGL。所以定义:

struct ViewportState {
    int vp[2], vs[2]; // position annd size of the viewport on screen
    vec3 pos; // camera position in the world
    vec3 rot; // euler angles of camera rotation
};

ViewportState viewports[number_of_viewports];
int active_viewport = 0;

编写一个函数来计算视口的视图矩阵:

mat4 ViewMatrix(const ViewportState &vp)
{
    // build a view matrix m based on vp.pos and vp.rot
    return m;
}

现在在渲染过程中使用这些:

void DisplayViewport(int i)
{
    const ViewportState &vp = viewports[i];
    glViewport(vp.vp[0], vp.vp[1], vp.vs[0], vp.vs[1]);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    if(i == active_vieport)
    {
        // draw a highlighted border around viewport
    }

    // load ViewMatrix(vp)
    // draw the actual 3d content of the viewport
}

void DisplayCallbackFunction(void)
{
    // ...
    for(int i = 0; i < nviewports; ++i)
        DisplayViewport(i);
    //...
}

键盘和鼠标将修改活动视口:

void KeyboardCallbackFunction(unsigned char key, int x, int y)
{
    // ...
    case 'w':
        viewports[active_viewport].pos -= (ViewMatrix(viewports[active_viewport]) * vec4(0,0,movementScalar,1)).xyz;
        break;

    case 'a':
        viewports[active_viewport].pos -= (ViewMatrix(viewports[active_viewport]) * vec4(movementScalar,0,0,1)).xyz;
        break;
    // ...
}

要激活其他视口:

void MouseClickCallbackFunction(int button, int state, int x, int y)
{
    // iterate over viewports, find the one within x/y coordinates and set active_viewport accordingly
}

答案 1 :(得分:0)

您有2个选择。

  1. 将视口场景渲染到由纹理支持的帧缓冲区。然后将纹理渲染到屏幕上
  2. 使用矩阵将场景从视口空间转换为屏幕空间。为防止自己画出框,请使用剪刀测试将其夹到视口