在vs中用c++绘制bezier曲面并改变网格定点位置(书写代码)
时间: 2023-12-19 08:07:56 浏览: 137

c++ BEIZER曲面的绘制

以下是一个简单的示例代码,可以在 Visual Studio 中使用 C++ 绘制一个 Bezier 曲面,并通过改变网格定点位置来调整曲面形状:
```c++
#include <iostream>
#include <vector>
#include <cmath>
#include <GL/glut.h> // OpenGL 窗口库头文件
using namespace std;
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const float PI = 3.1415926f;
// 定义控制点数组,共有 16 个点,用于构建 4x4 网格
vector<float> controlPoints = {
-1.5f, -1.5f, 4.0f, -0.5f, -1.5f, 2.0f, 0.5f, -1.5f, -1.0f, 1.5f, -1.5f, -2.0f,
-1.5f, -0.5f, 1.5f, -0.5f, -0.5f, 3.0f, 0.5f, -0.5f, 0.0f, 1.5f, -0.5f, -1.0f,
-1.5f, 0.5f, 4.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 3.0f, 1.5f, 0.5f, 4.0f,
-1.5f, 1.5f, -2.0f, -0.5f, 1.5f, -0.5f, 0.5f, 1.5f, -1.0f, 1.5f, 1.5f, 2.0f
};
// 定义网格数组,共有 16x3 个点,用于绘制 4x4 网格
vector<float> gridPoints;
// 定义 Bezier 曲面的阶数
const int ORDER = 3;
// 计算组合数
int nChoosek(int n, int k) {
if (k > n) return 0;
if (k == 0) return 1;
return nChoosek(n-1, k-1) * n / k;
}
// 计算 Bezier 基函数
float basisFunc(int i, int k, float t) {
return nChoosek(ORDER, i) * pow(t, i) * pow(1-t, ORDER-i);
}
// 计算 Bezier 曲面上某个点的坐标
vector<float> computePointOnSurface(float u, float v) {
vector<float> point = {0, 0, 0};
for (int i = 0; i <= ORDER; i++) {
for (int j = 0; j <= ORDER; j++) {
float basis = basisFunc(i, ORDER, u) * basisFunc(j, ORDER, v);
int index = (i * (ORDER+1) + j) * 3;
point[0] += controlPoints[index] * basis;
point[1] += controlPoints[index+1] * basis;
point[2] += controlPoints[index+2] * basis;
}
}
return point;
}
// 初始化 OpenGL
void init() {
// 设置清空颜色为黑色
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 计算网格点坐标
for (float v = 0; v <= 1.0f; v += 0.1f) {
for (float u = 0; u <= 1.0f; u += 0.1f) {
vector<float> point = computePointOnSurface(u, v);
gridPoints.push_back(point[0]);
gridPoints.push_back(point[1]);
gridPoints.push_back(point[2]);
}
}
}
// 绘制 Bezier 曲面
void drawBezierSurface() {
// 设置颜色为白色
glColor3f(1.0f, 1.0f, 1.0f);
// 绘制曲面
glBegin(GL_QUADS);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int index1 = (i * 10 + j) * 3;
int index2 = ((i+1) * 10 + j) * 3;
int index3 = ((i+1) * 10 + j+1) * 3;
int index4 = (i * 10 + j+1) * 3;
glVertex3f(gridPoints[index1], gridPoints[index1+1], gridPoints[index1+2]);
glVertex3f(gridPoints[index2], gridPoints[index2+1], gridPoints[index2+2]);
glVertex3f(gridPoints[index3], gridPoints[index3+1], gridPoints[index3+2]);
glVertex3f(gridPoints[index4], gridPoints[index4+1], gridPoints[index4+2]);
}
}
glEnd();
// 绘制网格
glColor3f(0.5f, 0.5f, 0.5f);
glBegin(GL_LINES);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
int index1 = (i * 10 + j) * 3;
int index2 = (i * 10 + j+1) * 3;
int index3 = ((i+1) * 10 + j) * 3;
int index4 = ((i+1) * 10 + j+1) * 3;
if (j != 9) {
glVertex3f(gridPoints[index1], gridPoints[index1+1], gridPoints[index1+2]);
glVertex3f(gridPoints[index2], gridPoints[index2+1], gridPoints[index2+2]);
}
if (i != 9) {
glVertex3f(gridPoints[index1], gridPoints[index1+1], gridPoints[index1+2]);
glVertex3f(gridPoints[index3], gridPoints[index3+1], gridPoints[index3+2]);
}
}
}
glEnd();
}
// 窗口重绘回调函数
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清空颜色和深度缓冲区
glLoadIdentity(); // 重置变换矩阵
// 将曲面平移、旋转、缩放到合适位置
glTranslatef(0.0f, 0.0f, -10.0f);
glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
glScalef(2.0f, 2.0f, 2.0f);
drawBezierSurface(); // 绘制 Bezier 曲面
glutSwapBuffers(); // 切换前后缓冲区,显示绘制结果
}
// 窗口大小改变回调函数
void reshape(int width, int height) {
glViewport(0, 0, width, height); // 设置视口大小
glMatrixMode(GL_PROJECTION); // 选择投影矩阵
glLoadIdentity(); // 重置投影矩阵
gluPerspective(60.0f, (float)width/height, 1.0f, 100.0f); // 设置投影矩阵
glMatrixMode(GL_MODELVIEW); // 选择模型视图矩阵
}
// 鼠标移动回调函数
void mouseMove(int x, int y) {
// 将鼠标坐标转换为 [-1, 1] 范围内的坐标
float u = (float)x / WINDOW_WIDTH * 2.0f - 1.0f;
float v = (float)(WINDOW_HEIGHT-y) / WINDOW_HEIGHT * 2.0f - 1.0f;
// 遍历控制点数组,将鼠标附近的控制点位置改变一定值
for (int i = 0; i < 16; i++) {
int index = i * 3;
float dx = controlPoints[index] - u;
float dy = controlPoints[index+1] - v;
float distance = sqrt(dx*dx + dy*dy);
if (distance < 0.05f) {
controlPoints[index] += dx * 0.1f;
controlPoints[index+1] += dy * 0.1f;
}
}
// 清空网格点数组,重新计算网格点坐标
gridPoints.clear();
for (float v = 0; v <= 1.0f; v += 0.1f) {
for (float u = 0; u <= 1.0f; u += 0.1f) {
vector<float> point = computePointOnSurface(u, v);
gridPoints.push_back(point[0]);
gridPoints.push_back(point[1]);
gridPoints.push_back(point[2]);
}
}
glutPostRedisplay(); // 标记窗口需要重绘
}
int main(int argc, char **argv) {
glutInit(&argc, argv); // 初始化 GLUT 库
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // 设置双缓冲、RGB 颜色模式和深度测试
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); // 设置窗口大小
glutCreateWindow("Bezier Surface"); // 创建窗口并设置标题
init(); // 初始化 OpenGL
glutDisplayFunc(display); // 设置窗口重绘回调函数
glutReshapeFunc(reshape); // 设置窗口大小改变回调函数
glutPassiveMotionFunc(mouseMove); // 设置鼠标移动回调函数
glEnable(GL_DEPTH_TEST); // 启用深度测试
glutMainLoop(); // 进入事件循环,等待窗口事件发生
return 0;
}
```
这个示例代码使用了 OpenGL 库来绘制 Bezier 曲面和网格,你需要在 Visual Studio 中添加 OpenGL 库的链接库和头文件,否则代码将无法编译。另外,示例代码中使用了鼠标移动事件来改变控制点位置,你需要在窗口显示时移动鼠标才能看到效果。
阅读全文
相关推荐














