问题六十一:三次b样条(b-spline)曲线的控制点和曲线形状的对应——以回旋体的“基本曲线”为例

198 篇文章 12 订阅
195 篇文章 27 订阅

问题六十:怎么用ray tracing画回旋体(rotational sweeping / revolution)”中的“基本曲线”是由三次b-spline曲线段拼接而成。

在这一章节,我们以其中一段曲线段为例,改变其对应的控制点,看看曲线段形状的改变,同时也看看对应的回旋体图形的改变。


控制点坐标如下图:


“问题六十”中的“基本曲线”的控制点对应如上ABCDEF六个点(其中A点在1位置)。对应输出的回旋体图形如下(再次贴出来):



说明一下:

1,由于我们接下来测试时的lookfrom坐标和“问题六十”中的坐标是有差异的,所以,输出的图形立体呈现是有差异的。

2,接下来,我们图片中的曲线段是从回旋体上切下来的,会得到两条关于y轴对称的曲线段,实际的“基本曲线”中的曲线段对应其中的一条。


我们知道如上回旋体的“基本曲线”是有三段三次b-spline曲线段拼接而成,分别对应的控制点为ABCD、BCDE、CDEF。

我们接下来要测试的是控制点ABCD对应的曲线段。

测试方式:BCD的位置保持不变,A点的位置依次如下改变(12,7,6,2,1,3,5,4,8,9,10,11),然后对比这12中情况的曲线段的变化情况和对应回旋体的变化情况。

//12
        vec3 ctrl_points[6] = {vec3(-2.0, -3.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//7
        vec3 ctrl_points[6] = {vec3(-4.0,  0.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//6
        vec3 ctrl_points[6] = {vec3(-4.0,  2.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//2
        vec3 ctrl_points[6] = {vec3(-4.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//1
        vec3 ctrl_points[6] = {vec3(-1.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//3
        vec3 ctrl_points[6] = {vec3( 2.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//5
        vec3 ctrl_points[6] = {vec3( 2.0,  7.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//4
        vec3 ctrl_points[6] = {vec3( 4.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//8--discover some problems
        vec3 ctrl_points[6] = {vec3( 4.0,  4.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//9
        vec3 ctrl_points[6] = {vec3( 4.0,  2.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//10
        vec3 ctrl_points[6] = {vec3( 4.0,  0.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};

//11
        vec3 ctrl_points[6] = {vec3( 3.0, -5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};



接下来,贴一份A在1位置的完整拆解图形:

=++

=++


最后,说一下,“曲线段”是怎么从回旋体中切出来的呢?

只需要对“一元六次方程”的根对应的z坐标的范围加以限制即可。对应修改的代码:

                roots_equation_6th(ss6, 0, 1, tol, roots);
                for (int j=1; j<(int(roots[0])+1); j++) {
                    yyv = matrix_c_v[0][i]+matrix_c_v[1][i]*roots[j]+matrix_c_v[2][i]*roots[j]*roots[j]+matrix_c_v[3][i]*roots[j]*roots[j]*roots[j];
                    roots_t[num_roots_t+1][0] = (yyv-yy0)/yyd;
                    rec.t = roots_t[num_roots_t+1][0];
                    rec.p = r.point_at_parameter(rec.t);
                    if (fabs(rec.p.z())<0.5) {
                        roots_t[num_roots_t+1][1] = i;
                        roots_t[num_roots_t+1][2] = roots[j];
                        num_roots_t ++;
                    }
                }
            }
            roots_t[0][0] = float(num_roots_t);


  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值