我尝试使用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();
}
你错过了在显示
()函数结束时对贪婪
的调用。这是在使用双缓冲渲染时显示帧所必需的。
我正在使用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();