在vs中用c++绘制Bezier 曲面,要求用不同颜色显示曲面和曲面的控制网格,并且可以取消曲面控制网格的显示,允 许交互式地改变控制网格的定点位置,以观看曲面形状的改变;能够通过对话框、菜单等方式设置曲面的配置参数;(书写具体代码)
时间: 2024-02-03 20:11:59 浏览: 33
以下是一个基本的实现代码,实现了Bezier曲面的绘制、控制网格的显示和交互式修改控制点位置。同时,也可以通过菜单设置曲面的配置参数。
```cpp
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include <vector>
using namespace std;
// 控制点信息
struct Point {
GLfloat x, y, z;
};
// 配置参数
struct Config {
int u_num; // u方向控制点数目
int v_num; // v方向控制点数目
GLfloat step_u; // u方向步长
GLfloat step_v; // v方向步长
bool show_grid; // 是否显示控制网格
};
// 全局变量
vector<Point> control_points; // 控制点数组
Config config = {4, 4, 0.1f, 0.1f, true}; // 默认配置参数
GLfloat rotate_x = 0.0f; // x轴旋转角度
GLfloat rotate_y = 0.0f; // y轴旋转角度
bool dragging = false; // 是否正在拖拽控制点
int dragging_index = -1; // 正在拖拽的控制点的下标
// 绘制控制点
void drawControlPoints() {
glColor3f(1.0f, 0.0f, 0.0f);
glPointSize(5.0f);
glBegin(GL_POINTS);
for (int i = 0; i < control_points.size(); ++i) {
glVertex3f(control_points[i].x, control_points[i].y, control_points[i].z);
}
glEnd();
}
// 绘制控制网格
void drawControlGrid() {
glColor3f(0.5f, 0.5f, 0.5f);
glBegin(GL_LINES);
for (int i = 0; i < config.u_num; ++i) {
for (int j = 0; j < config.v_num; ++j) {
if (i < config.u_num - 1) {
glVertex3f(control_points[i * config.v_num + j].x, control_points[i * config.v_num + j].y, control_points[i * config.v_num + j].z);
glVertex3f(control_points[(i + 1) * config.v_num + j].x, control_points[(i + 1) * config.v_num + j].y, control_points[(i + 1) * config.v_num + j].z);
}
if (j < config.v_num - 1) {
glVertex3f(control_points[i * config.v_num + j].x, control_points[i * config.v_num + j].y, control_points[i * config.v_num + j].z);
glVertex3f(control_points[i * config.v_num + j + 1].x, control_points[i * config.v_num + j + 1].y, control_points[i * config.v_num + j + 1].z);
}
}
}
glEnd();
}
// 绘制Bezier曲面
void drawBezierSurface() {
glColor3f(0.0f, 1.0f, 0.0f);
for (int i = 0; i < config.u_num - 3; ++i) {
for (int j = 0; j < config.v_num - 3; ++j) {
glBegin(GL_QUADS);
for (GLfloat u = 0.0f; u <= 1.0f; u += config.step_u) {
for (GLfloat v = 0.0f; v <= 1.0f; v += config.step_v) {
GLfloat p[3];
GLfloat q[4];
GLfloat r[4];
for (int k = 0; k < 4; ++k) {
q[k] = control_points[(i + k) * config.v_num + j].x * (1 - v) + control_points[(i + k) * config.v_num + j + 1].x * v;
r[k] = control_points[(i + k) * config.v_num + j].y * (1 - v) + control_points[(i + k) * config.v_num + j + 1].y * v;
}
p[0] = q[0] * (1 - u) * (1 - u) * (1 - u) + 3 * q[1] * u * (1 - u) * (1 - u) + 3 * q[2] * u * u * (1 - u) + q[3] * u * u * u;
p[1] = r[0] * (1 - u) * (1 - u) * (1 - u) + 3 * r[1] * u * (1 - u) * (1 - u) + 3 * r[2] * u * u * (1 - u) + r[3] * u * u * u;
p[2] = control_points[(i + 1) * config.v_num + j + 1].z * v + control_points[(i + 1) * config.v_num + j].z * (1 - v);
glVertex3f(p[0], p[1], p[2]);
}
}
glEnd();
}
}
}
// 绘制函数
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(rotate_x, 1.0f, 0.0f, 0.0f);
glRotatef(rotate_y, 0.0f, 1.0f, 0.0f);
if (config.show_grid) {
drawControlGrid();
}
drawBezierSurface();
drawControlPoints();
glFlush();
}
// 初始化函数
void init() {
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
// 鼠标按下事件
void mouseClick(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
for (int i = 0; i < control_points.size(); ++i) {
GLfloat dist = sqrt(pow(posX - control_points[i].x, 2) + pow(posY - control_points[i].y, 2) + pow(posZ - control_points[i].z, 2));
if (dist < 0.2f) {
dragging = true;
dragging_index = i;
break;
}
}
} else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
dragging = false;
dragging_index = -1;
}
}
// 鼠标拖拽事件
void mouseDrag(int x, int y) {
if (dragging) {
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
control_points[dragging_index].x = posX;
control_points[dragging_index].y = posY;
control_points[dragging_index].z = posZ;
glutPostRedisplay();
}
}
// 菜单处理函数
void menuHandler(int value) {
switch (value) {
case 1:
config.u_num = 4;
config.v_num = 4;
config.step_u = 0.1f;
config.step_v = 0.1f;
break;
case 2:
config.u_num = 5;
config.v_num = 5;
config.step_u = 0.05f;
config.step_v = 0.05f;
break;
case 3:
config.u_num = 8;
config.v_num = 8;
config.step_u = 0.01f;
config.step_v = 0.01f;
break;
case 4:
config.show_grid = !config.show_grid;
break;
}
glutPostRedisplay();
}
// 创建菜单
void createMenu() {
int submenu1 = glutCreateMenu(menuHandler);
glutAddMenuEntry("4x4", 1);
glutAddMenuEntry("5x5", 2);
glutAddMenuEntry("8x8", 3);
int submenu2 = glutCreateMenu(menuHandler);
glutAddMenuEntry("显示控制网格", 4);
glutCreateMenu(menuHandler);
glutAddSubMenu("设置控制点数目", submenu1);
glutAddSubMenu("显示选项", submenu2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
// 主函数
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutCreateWindow("Bezier曲面");
init();
control_points.push_back({-1.0f, -1.0f, 0.0f});
control_points.push_back({-0.5f, -1.0f, 1.0f});
control_points.push_back({0.5f, -1.0f, -1.0f});
control_points.push_back({1.0f, -1.0f, 0.0f});
control_points.push_back({-1.0f, 0.0f, 1.0f});
control_points.push_back({-0.5f, 0.0f, -1.0f});
control_points.push_back({0.5f, 0.0f, 1.0f});
control_points.push_back({1.0f, 0.0f, -1.0f});
control_points.push_back({-1.0f, 1.0f, 0.0f});
control_points.push_back({-0.5f, 1.0f, -1.0f});
control_points.push_back({0.5f, 1.0f, 1.0f});
control_points.push_back({1.0f, 1.0f, 0.0f});
glutDisplayFunc(display);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseDrag);
createMenu();
glutMainLoop();
return 0;
}
```