✠OpenGL-11-参数曲面
Posted itzyjr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了✠OpenGL-11-参数曲面相关的知识,希望对你有一定的参考价值。
“贝塞尔曲线”和“贝塞尔曲面”,这些方法通常用于高效地对各种曲面 3D 物体进行建模。用它们可以生成任意精度的曲线。
二次贝塞尔曲线
二次贝塞尔曲线
由一组参数方程定义, 方程组中使用 3 个控制点指定特定的曲线的形状,每个控制点都是 2D 空间中的一个点。
针对各种 t 值收集大量的点 P(t),则会产生一条曲线,如上图所示。采样的 t 的参数值越多,生成的点 P(t)越多,得到的曲线则越平滑。
现在可以导出二次贝塞尔曲线的分析定义。首先,我们注意到连接两个点 pa 和 pb 的线段 pa−pb 上的任意点 p 可以用参数 t 表示如下:
p
(
t
)
=
t
p
a
+
(
1
−
t
)
p
b
p(t)=tp_a+(1-t)p_b
p(t)=tpa+(1−t)pb
使用该等式,我们解出点 p01 和 p12(分别在 p0−p1 和 p1−p2 上的点)如下:
p
01
=
t
p
1
+
(
1
−
t
)
p
0
p
12
=
t
p
2
+
(
1
−
t
)
p
1
p_{01}=tp_1+(1-t)p_0\\\\ p_{12}=tp_2+(1-t)p_1
p01=tp1+(1−t)p0p12=tp2+(1−t)p1
可参见Blog“第7章 CustomView绘图进阶-贝济埃曲线”
P
(
t
)
=
(
1
−
t
)
2
p
0
+
(
−
2
t
2
+
2
t
)
p
1
+
t
2
p
2
P(t) = (1-t)^2p_0 + (-2t^2+2t)p_1+t^2p_2
P(t)=(1−t)2p0+(−2t2+2t)p1+t2p2
三次贝塞尔曲线
P
(
t
)
=
∑
i
=
0
3
p
i
B
i
(
t
)
其
中
,
B
0
(
t
)
=
(
1
−
t
)
3
B
1
(
t
)
=
3
t
3
−
6
t
2
+
3
t
B
2
(
t
)
=
−
3
t
3
+
3
t
2
B
3
(
t
)
=
t
3
P(t)=\\sum_{i=0}^3{p_iB_i(t)}\\\\ 其中,\\\\ B_0(t)=(1-t)^3\\\\ B_1(t)=3t^3-6t^2+3t\\\\ B_2(t)=-3t^3+3t^2\\\\ B_3(t)=t^3
P(t)=i=0∑3piBi(t)其中,B0(t)=(1−t)3B1(t)=3t3−6t2+3tB2(t)=−3t3+3t2B3(t)=t3
渲染贝塞尔曲线时,可以使用许多不同的技术。其中一种方法是,使用固定的增量,在0.0~1.0 范围内,迭代增加得出 t 的后继值。例如,当增量为 0.1 时,我们可以使用 t 值为0.0、 0.1、 0.2、 0.3 等的循环。对于 t 的每个值,计算贝塞尔曲线上的对应点,并绘制连接连续点的一系列线段,算法如下:
void drawBezierCurve(controlPointVector C) {
currentPoint = C[0];// 曲线从第一个控制点开始
t = 0.0;
while (t <= 1.0) {
// 计算混合函数在t时对控制点的加权和,作为曲线的下一个点
nextPoint = (0, 0);
for (int i = 0; i <= 3; i++)
nextPoint += blending(i, t) * C[i];
drawLine(currentPoint, nextPoint);
currentPoint = nextPoint;
t += increment;
}
}
double blending(int i, double t) {
switch(i) {
case 0: return (1-t)*(1-t)*(1-t);// (1-t)^3
case 1: return 3*t*(1-t)*(1-t);// 3t(1-t)^2
case 2: return 3*t*t*(1-t);// 3t^2(1-t)
case 3: return t*t*t;// t^3
}
}
下面画一个曲线:
vector<glm::vec3> drawBezierCurve(vector<glm::vec3> Ctrl) {
vector<glm::vec3> points;
points.push_back(Ctrl[0]);
double t = 0.0;
while (t <= 1.0) {
glm::vec3 nextPoint;
nextPoint.x = 0;
nextPoint.y = 0;
nextPoint.z = 0;
for (int i = 0; i <= 3; i++) {
nextPoint.x += blending(i, t) * C[i].x;
nextPoint.y += blending(i, t) * C[i].y;
}
points.push_back(nextPoint);
t += 0.1;
}
return points;
}
void setupVertices(void) {
vector<glm::vec3> Ctrl;
Ctrl.push_back(glm::vec3(0.1, 0.5, 0));
Ctrl.push_back(glm::vec3(0.4, 0.9, 0));
Ctrl.push_back(glm::vec3(0.6, 0.95, 0));
Ctrl.push_back(glm::vec3(0.9, 0.55, 0));
vector<glm::vec3> points = drawBezierCurve(Ctrl);
...
}
void display(...) {
...
glLineWidth(1.0);
glDrawArrays(GL_LINE_STRIP, 0, values.size() / 3);
}
在XY平面画了一条三次贝塞尔曲线,如下图:
二次贝塞尔曲面
贝塞尔曲线定义了曲线(在 2D 或 3D 空间中),而贝塞尔曲面定义了 3D 空间中的曲面。将我们在曲线中看到的概念扩展到曲面, 需要将参数方程组中的参数个数从一个扩展到两个。对于贝塞尔曲线,我们将参数称为 t。对于贝塞尔曲面,我们将参数称为 u 和 v。曲线由点 P(t)组成,而曲面将由点 P(u, v)组成,如下图所示。
对于二次贝塞尔曲面,每个轴 u 和 v 上有3 个控制点,总共 9 个控制点。下图使用蓝色展示了一组共 9 个控制点(通常称为控制点“网格”
)的示例,以及相应的曲面(红色)。
P
(
u
,
v
)
=
∑
i
=
0
2
∑
j
=
0
2
p
i
j
B
i
(
u
)
B
j
(
v
)
其
中
,
B
0
(
u
)
=
(
1
−
u
)
2
B
1
(
u
)
=
−
2
u
2
+
2
u
B
2
(
u
)
=
u
2
B
0
(
v
)
=
(
1
−
v
)
2
B
1
(
v
)
=
−
2
v
2
+
2
v
B
2
(
v
)
=
v
2
P(u,v)=\\sum_{i=0}^2\\sum_{j=0}^2{p_{ij}B_i(u)B_j(v)}\\\\ 其中,\\\\ B_0(u)=(1-u)^2\\\\ B_1(u)=-2u^2+2u\\\\ B_2(u)=u^2\\\\ B_0(v)=(1-v)^2\\\\ B_1(v)=-2v^2+2v\\\\ B_2(v)=v^2\\\\
P(u,v)=i=0∑2j=0∑2pijBi(u)Bj(v)其中,B0(u)=(1−u)2B1(u)=−2u2+2uB2(u)=u2B0(v)=(1−v)
MATLAB | 如何绘制三维曲线曲面多边形投影(三视图)?