当前位置: 首页 > 知识库问答 >
问题:

OpenGL:新窗口显示当前打开窗口的内容

姜明贤
2023-03-14

我尝试使用OpenGL绘制贝塞尔曲面。我的程序读取一个输入文件,其中包含用于绘图的采样点数量、用于表面着色的控制点和调色板。它必须输出一个带有曲面图的新窗口,我可以在其中操纵曲面和控制点的属性。

从Bernstein多项式生成的点被三角化,并通过从三角形的最小和最大高度映射它来按调色板分配颜色。

不幸的是,它打开了一个窗口,其中当前窗口的一部分在操作系统中打开,而没有为surface创建新界面。

这是代码:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <cmath>


using namespace std;


struct vertex
{
    float x;
    float y;
    float z;
};


struct RGB
{
    float r;
    float g;
    float b;
};


int main_window;


bool TM = true;
vertex surfaceTranslate;
float surfaceRotate = 0;
vertex camera;
vertex up;
int currentPointX = 0, currentPointY = 0;
vertex toY;

int SampleR, SampleC;
int M, N;
int K;
vector < vector <vertex> > points;
vector <RGB> palette;
vector < vector <vertex> > control;
float minH, maxH;


int fact (int n)
{
    if (!n || n == 1)
    {
        return 1;
    }
    return n * fact (n - 1);
}

int C (int n, int i)
{
    return fact (n) / (fact (i) * fact (n - i));
}


void initialDisplay(void)
{
    glClearColor (1.0, 1.0, 1.0, 1.0);
    glDisable (GL_LIGHTING);
    glEnable (GL_RESCALE_NORMAL);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity();
    gluPerspective (60, 1, 1, 1000000);
    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity();
}


void updateControl()
{
    control.clear();
    for (int i = 0; i < SampleR; ++i)
    {
        vector <vertex> temp;
        for (int j = 0; j < SampleC; ++j)
        {
            float u = (float)(i) / (SampleR - 1);
            float v = (float)(j) / (SampleC - 1);
            vertex p;
            p.x = p.y = p.z = 0;
            for (int k = 0; k < M; ++k)
            {
                for (int m = 0; m < N; ++m)
                {
                    float B_u = float (C (M - 1, k)) * pow (u, k) * pow (1 - u, M - 1 - k);
                    float B_v = float (C (N - 1, m)) * pow (v, m) * pow (1 - v, N - 1 - m);
                    p.x += B_u * B_v * points[k][m].x;
                    p.y += B_u * B_v * points[k][m].y;
                    p.z += B_u * B_v * points[k][m].z;
                }
            }
            temp.push_back (p);
        }
        control.push_back (temp);
    }
    maxH = 1 << ((sizeof(float) * 8) - 1);
    minH = -maxH;
    for (int i = 0; i < SampleR - 1; ++i)
    {
        for (int j = 0; j < SampleC - 1; ++j)
        {
            float h = (control[i][j].y + control[i + 1][j].y + control[i][j + 1].y) / 3;
            if (h > maxH)
            {
                maxH = h;
            }
            if (h < minH)
            {
                minH = h;
            }
            h = (control[i][j + 1].y + control[i + 1][j].y + control[i + 1][j + 1].y) / 3;
            if (h > maxH)
            {
                maxH = h;
            }
            if (h < minH)
            {
                minH = h;
            }
        }
    }
    for (int i = 0; i < SampleR; ++i)
    {
        for (int j = 0; j < SampleC; ++j)
        {
            toY.x += control[i][j].x;
            toY.z += control[i][j].z;
        }
        toY.x /= SampleR * SampleC;
        toY.z /= SampleR * SampleC;
    }
}


void display(void)
{
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt (camera.x, camera.y, camera.z, 0, 0, 0, up.x, up.y, up.z);
    glTranslatef (surfaceTranslate.x, surfaceTranslate.y, surfaceTranslate.z);
    glTranslatef (toY.x, toY.y, toY.z);
    glRotatef (surfaceRotate, 0, 1, 0);
    glTranslatef (- toY.x, -toY.y, -toY.z);
    if (!TM)
    {
        glPointSize (10);
        glBegin (GL_POINTS);
        for (int i = 0; i < M; ++i)
        {
            for (int j = 0; j < N; ++j)
            {
                if (i == currentPointX && j == currentPointY)
                {
                    glColor3f (1.0, 0.0, 0.0);
                }
                else
                {
                    glColor3f (0.0, 0.0, 1.0);
                }
                glVertex3f (points[i][j].x, points[i][j].y, points[i][j].z);
            }
        }
        glEnd();
    }
    glBegin (GL_TRIANGLES);
    for (int i = 0; i < SampleR - 1; ++i)
    {
        for (int j = 0; j < SampleC - 1; ++j)
        {
            glVertex3f (control[i][j].x, control[i][j].y, control[i][j].z);
            glVertex3f (control[i + 1][j].x, control[i + 1][j].y, control[i + 1][j].z);
            glVertex3f (control[i][j + 1].x, control[i][j + 1].y, control[i][j + 1].z);
            float h = (control[i][j].y + control[i + 1][j].y + control[i][j + 1].y) / 3;
            int r = (palette[K - 1].r - palette[0].r) * (h - minH) / (maxH - minH);
            int g = (palette[K - 1].g - palette[0].g) * (h - minH) / (maxH - minH);
            int b = (palette[K - 1].b - palette[0].b) * (h - minH) / (maxH - minH);
            glColor3f (palette[r].r / (palette[K - 1].r - palette[0].r), palette[g].g / (palette[K - 1].g - palette[K - 1].g), palette[b].b / (palette[K - 1].b - palette[0].b));
            glVertex3f (control[i + 1][j].x, control[i + 1][j].y, control[i + 1][j].z);
            glVertex3f (control[i][j + 1].x, control[i][j + 1].y, control[i][j + 1].z);
            glVertex3f (control[i + 1][j + 1].x, control[i + 1][j + 1].y, control[i + 1][j + 1].z);
            h = (control[i + 1][j].y + control[i][j + 1].y + control[i + 1][j + 1].y) / 3;
            r = (palette[K - 1].r - palette[0].r) * (h - minH) / (maxH - minH);
            g = (palette[K - 1].g - palette[0].g) * (h - minH) / (maxH - minH);
            b = (palette[K - 1].b - palette[0].b) * (h - minH) / (maxH - minH);
            glColor3f (palette[r].r / (palette[K - 1].r - palette[0].r), palette[g].g / (palette[K - 1].g - palette[K - 1].g), palette[b].b / (palette[K - 1].b - palette[0].b));
        }
    }
    glEnd();
}


void keyboardEvent (unsigned char key, int x, int y)
{
    if (TM)
    {
        switch (key)
        {
            case ('2'):
                TM = false;
                glutSetWindowTitle ("Surface Editing Mode");
                break;
            case ('q'):
                --surfaceTranslate.x;
                break;
            case ('w'):
                ++surfaceTranslate.x;
                break;
            case ('a'):
                --surfaceTranslate.y;
                break;
            case ('s'):
                ++surfaceTranslate.y;
                break;
            case ('z'):
                --surfaceTranslate.z;
                break;
            case ('x'):
                ++surfaceTranslate.z;
                break;
            case ('r'):
                ++surfaceRotate;
                break;
            case ('t'):
                --surfaceRotate;
                break;
        }
    }
    else
    {
        switch (key)
        {
            case ('1'):
                TM = true;
                glutSetWindowTitle ("Transformation Mode");
                break;
            case ('q'):
                --points[currentPointX][currentPointY].x;
                updateControl();
                break;
            case ('w'):
                ++points[currentPointX][currentPointY].x;
                updateControl();
                break;
            case ('a'):
                --points[currentPointX][currentPointY].y;
                updateControl();
                break;
            case ('s'):
                ++points[currentPointX][currentPointY].y;
                updateControl();
                break;
            case ('z'):
                --points[currentPointX][currentPointY].z;
                updateControl();
                break;
            case ('x'):
                ++points[currentPointX][currentPointY].z;
                updateControl();
                break;
            case ('i'):
                if (!(SampleR % 2))
                {
                    SampleR /= 2;
                    updateControl();
                }
                break;
            case ('o'):
                SampleR *= 2;
                updateControl();
                break;
            case ('k'):
                if (!(SampleC % 2))
                {
                    SampleC /= 2;
                    updateControl();
                }
                break;
            case ('l'):
                SampleC *= 2;
                updateControl();
                break;
            case (GLUT_KEY_UP):
                if (currentPointY < N - 1)
                {
                    ++currentPointY;
                }
                break;
            case (GLUT_KEY_DOWN):
                if (currentPointY)
                {
                    --currentPointY;
                }
                break;
            case (GLUT_KEY_LEFT):
                if (currentPointX)
                {
                    --currentPointX;
                }
                break;
            case (GLUT_KEY_RIGHT):
                if (currentPointX < M - 1)
                {
                    ++currentPointX;
                }
                break;
        }
    }
    glutPostRedisplay();
}


void changeDirection (int x, int y)
{
    float dist = sqrt (pow (camera.x, 2) + pow (camera.y, 2) + pow (camera.z, 2));
    camera.x = dist * sin (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532);
    camera.y = dist * cos (360.0 / 800 * y * 0.0174532);
    camera.z = dist * cos (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532);
    up.x = dist * sin (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532 - 1) - camera.x;
    up.y = dist * cos (360.0 / 800 * y * 0.0174532 - 1) - camera.y;
    up.z = dist * cos (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532 - 1) - camera.z;
    glutPostRedisplay();
}


void mouseEvent (int key, int state, int x, int y)
{
    if (key == GLUT_KEY_LEFT)
    {
        changeDirection (x, y);
    }
}



void readFile (char *fname)
{
    ifstream file (fname);
    if (file.is_open())
    {
        file >> SampleR >> SampleC;
        file >> M >> N;
        for (int i = 0; i < M; ++i)
        {
            vector <vertex> tempv;
            for (int j = 0; j < N; ++j)
            {
                vertex temp;
                file >> temp.x >> temp.y >> temp.z;
                tempv.push_back (temp);
            }
            points.push_back (tempv);
        }
        file >> K;
        for (int i = 0; i < K; ++i)
        {
            RGB temp;
            file >> temp.r >> temp.g >> temp.b;
            palette.push_back (temp);
        }
    }
    file.close();
}


int main (int argc, char *argv[])
{
    surfaceTranslate.x = surfaceTranslate.y = surfaceTranslate.z = toY.x = toY.y = toY.z = up.x = up.z = 0;
    up.y = 1;
    camera.x = camera.y = camera.z = 100;
    readFile (argv[1]);
    updateControl();
    glutInit (&argc,argv);
    glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition (50, 50);
    glutInitWindowSize (800, 800);
    main_window = glutCreateWindow ("Transformation Mode");
    glutDisplayFunc (display);
    glutKeyboardFunc (keyboardEvent);
    glutMouseFunc (mouseEvent);
    glutMotionFunc (changeDirection);
    initialDisplay();
    glutMainLoop();
}

共有1个答案

辛健
2023-03-14

你错过了在显示()函数结束时对贪婪调用。这是在使用双缓冲渲染时显示帧所必需的。

 类似资料:
  • 我正在使用Linux并试图学习OpenGL。我参考了learnopengl.com网站,并在这里编译了第一个可用的程序。 我似乎在编译程序时没有遇到命令问题 但是当我运行程序时,它会从后面显示东西,而不是像这样的空白窗口 但是请注意,此窗口不透明,因为如果我移动窗口,背景是相同的。但是,如果我最小化并重新打开窗口,则背景是新创建的。专用和集成 GPU 都会发生这种情况。 我需要做什么才能使它正常工

  • 我试图在linux red hat上使用GLFW打开一个OpenGL全屏窗口。我有一个桌面,它跨越两个显示器,总分辨率为3840*1080。 我有两个问题:1。窗口仅在一台显示器上打开,最大窗口宽度为1920(单个显示器的宽度)。2.窗口的最大高度是1003(我认为是屏幕的高度减去任务栏和顶栏的高度)。 这是我用来打开窗口的代码: 输出:宽度=1920高度=1003 编辑:我使用xrandr检查可

  • 查看这段代码,它们展示了一种在登录后显示新窗口的方法。当用户名和密码是正确的,它打开新的对话框。我想要一个按钮点击打开新的对话框,而不检查用户名和密码。

  • 我有A. fxml和B. fxml。运行Java应用程序覆盖启动方法。我想每40分钟循环(5次){打开新阶段B. fxml并等待stage.close,如果阶段关闭继续循环打开新阶段B fxml。循环五次。我尝试定时器timerment我不能。我尝试JavaFX服务我不能。我创建My线程扩展线程对象。这一次,我无法控制下一阶段的循环。当用于声明开始打开5阶段。但是我想循环等待当前阶段关闭,然后进入

  • 新窗口打开链接 该方法可以新起webview打开页面,由于客户端窗口过多会占用较多内存,请谨慎使用 Tida.pushWindow("http://www.tmall.com/go/chn/common/u-award.php?disableptf=1"); 关闭窗口 关闭当前webview窗口 Tida.popWindow();