【OpenGL】自己实现B-Spline曲线

【OpenGL】自己实现B-Spline曲线

1.绘制目标

自己实现B-Spline曲线。

2.核心代码

/TO DO///
///基于CdM公式计算B-Spline混合函数///

float bspline(float* knots, int i, int order, float u) {
	// 特殊情形:一阶B-splines
	if (order == 1) {
		if (i == 0)
		{
			if (u >= knots[i] && u <= knots[i + 1])
			{
				return 1.0;
			}
			else
			{
				return 0.0;
			}
		}
		else if (i >= 1)
		{
			if (u > knots[i] && u <= knots[i + 1])
			{
				return 1.0;
			}
			else
			{
				return 0.0;
			}
		}
	}
	// 一般情形
	else {
		// 用于存储CdM公式右边和式的第一项和第二项的值
		float b1(0.f), b2(0.f);

		// 计算CdM公式右边和式的第一项
		if (knots[i + order - 1] - knots[i] == 0)
		{
			if (u - knots[i] == 0)
			{
				b1 = bspline(knots, i, order - 1, u);
			}
			else
			{
				b1 = 0;
			}
		}
		else
		{
			float x = u - knots[i];
			float y = knots[i + order - 1] - knots[i];
			b1 = x / y * bspline(knots, i, order - 1, u);
		}

		// 计算CdM公式右边和式的第二项
		if (knots[i + order] - knots[i + 1] == 0)
		{
			if (knots[i + order] - u == 0)
			{
				b2 = bspline(knots, i + 1, order - 1, u);
			}
			else
			{
				b2 = 0;
			}
		}
		else
		{
			float x = knots[i + order] - u;
			float y = knots[i + order] - knots[i + 1];
			b2 = x / y * bspline(knots, i + 1, order - 1, u);
		}

		return b1 + b2;
	}
}
/TO DO///
绘制B-Spline曲线//

void drawBSplineCurve(float* knots, float* controlPoints, int numControlPoints, int order, int numSamples) 
{
	float a = knots[order - 1];
	float num = (knots[numControlPoints] - knots[order - 1]) / numSamples;
	glColor3f(0.0f, 0.0f, 1.0f);
	glBegin(GL_LINE_STRIP);
	for (float j = a; j <= knots[numControlPoints]; j += num)
	{
		float x = 0, y = 0, z = 0;
		for (int i = 0; i < numControlPoints; i++)
		{
			x = x + controlPoints[i * POINT_DIMS] * bspline(knots, i, order, j);
			y = y + controlPoints[i * POINT_DIMS + 1] * bspline(knots, i, order, j);
			z = z + controlPoints[i * POINT_DIMS + 2] * bspline(knots, i, order, j);
		}
		glVertex3f(x, y, z);
	}
	glEnd();
}

///
/// TO DO ///
///创建OpenGL GLU NURBS 对象并设置采样方法和采样阈值/

		NURBS_OBJ = gluNewNurbsRenderer();
		gluNurbsProperty(NURBS_OBJ, GLU_SAMPLING_METHOD, GLU_PATH_LENGTH);
		gluNurbsProperty(NURBS_OBJ, GLU_SAMPLING_TOLERANCE, 10.0);

/

/// 使用自己实现的函数绘制B-Spline曲线//

		drawBSplineCurve(KNOT_ARRAY, CONTROL_POINTS_ARRAY, NUM_POINTS, BSPLINE_ORDER, 200);
		

3.运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
下面是一个简单的 C++ 和 OpenGL 实现生成 B 样条曲线的代码示例: ```cpp #include <GL/glut.h> #include <vector> using namespace std; const int WINDOW_WIDTH = 600; const int WINDOW_HEIGHT = 600; vector<pair<float, float>> controlPoints; // 控制点数组 vector<pair<float, float>> splinePoints; // 样条曲线点数组 int degree = 3; // B 样条曲线的次数 int segments = 32; // 曲线的线段数 // 计算 B 样条基函数 float Bspline(int i, int k, float t) { if (k == 1) { if (t >= controlPoints[i].first && t < controlPoints[i + 1].first) { return 1.0f; } else { return 0.0f; } } else { float w1 = 0.0f, w2 = 0.0f; if (controlPoints[i + k - 1].first != controlPoints[i].first) { w1 = (t - controlPoints[i].first) / (controlPoints[i + k - 1].first - controlPoints[i].first); } if (controlPoints[i + k].first != controlPoints[i + 1].first) { w2 = (controlPoints[i + k].first - t) / (controlPoints[i + k].first - controlPoints[i + 1].first); } return w1 * Bspline(i, k - 1, t) + w2 * Bspline(i + 1, k - 1, t); } } // 计算 B 样条曲线上的点 void calculateSplinePoints() { splinePoints.clear(); if (controlPoints.size() < degree + 1) { return; } for (int i = 0; i <= segments; i++) { float t = controlPoints[degree].first + (controlPoints[controlPoints.size() - degree - 1].first - controlPoints[degree].first) * i / segments; float x = 0.0f, y = 0.0f; for (int j = 0; j < controlPoints.size(); j++) { float b = Bspline(j, degree, t); x += controlPoints[j].second * b; y += controlPoints[j].first * b; } splinePoints.push_back(make_pair(y, x)); } } // 绘制 B 样条曲线 void drawSpline() { glBegin(GL_LINE_STRIP); for (int i = 0; i < splinePoints.size(); i++) { glVertex2f(splinePoints[i].second, splinePoints[i].first); } glEnd(); } // 绘制控制点 void drawControlPoints() { glPointSize(5.0f); glBegin(GL_POINTS); for (int i = 0; i < controlPoints.size(); i++) { glVertex2f(controlPoints[i].second, controlPoints[i].first); } glEnd(); } // 鼠标事件处理函数 void onMouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { controlPoints.push_back(make_pair(WINDOW_HEIGHT - y, x)); calculateSplinePoints(); glutPostRedisplay(); } } // 渲染函数 void render() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 1.0f, 1.0f); drawSpline(); glColor3f(1.0f, 0.0f, 0.0f); drawControlPoints(); glutSwapBuffers(); } // 初始化函数 void initialize() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); glutCreateWindow("B-spline Curve"); initialize(); glutDisplayFunc(render); glutMouseFunc(onMouse); glutMainLoop(); return 0; } ``` 这段代码使用了 GLUT 库来创建窗口和处理鼠标事件,计算 B 样条曲线上的点,并在 OpenGL 中绘制出 B 样条曲线和控制点。你可以根据自己的需要修改代码来适配不同的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码两年半的练习生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值