问题五十八:怎么用ray tracing画conic sweeping图形

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

58.1 概述

在上一章节中画的translational sweeping图形是将曲线沿着y轴平移后得到的,在平移的过程中曲线保持不变。接下来,我们要画的是conic sweeping图形。这种图形也是曲线沿着y轴平移后得到的,但是,在平移的过程中对曲线进行了一定比例的缩放,这个比例一般是和y坐标成正比。示意图如下:





58.2 求根






后面求根的步骤和translational sweeping是完全一样了。

对应“57.2.5”和“57.2.6”

 

58.3 求法向量

t0_t1_smaller在曲线内:

法向量即为cap plane的法向量:(0, 1, 0)

 

 

t0_t1_bigger在曲线内

或者

t0t1都不在曲线内

 

这两种情况的根是通过投影光线和曲线相交求得,对应的法向量即为曲线在该处的切向量和“该处和conic sweeping顶点连线向量”的叉乘。

Conic sweeping的法向量示意如下图:





58.4 看C++代码实现


下面只贴出在“问题五十七”的基础上有改动的部分代码。

 

----------------------------------------------sweeping_translational.h ------------------------------------------

sweeping_translational.h

 

class sweeping_translational : public hitable
{
    public:
        sweeping_translational() {}
        sweeping_translational(vec3 *cp, float by, float cy, material *m, int ty){
/*
ty=1: translational sweeping
ty=2: conic sweeping
*/
            base_y = by;
            cap_y = cy;
            ma = m;
            type = ty;

……

        material *ma;

        inttype;

};

 

----------------------------------------------sweeping_translational.cpp ------------------------------------------

sweeping_translational.cpp

 

bool sweeping_translational::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {
#if SWEEPING_TRANSLATIONAL_LOG == 1
        std::cout << "-------------sweeping_translational::hit---1-------------" << endl;
#endif // SWEEPING_TRANSLATIONAL_LOG
        float t_near, t_far;
        if (ray_hit_box_st(r, sweeping_bl, sweeping_bh, t_near, t_far)) {
……
……
            t0 = (base_y - y0) / yd;
            t1 = (cap_y - y0) / yd;
            t0_t1_smaller = (t0>t1)? t1:t0;
            t0_t1_bigger = (t0>t1)? t0:t1;
            for (int i=0; i<14; i++) {

                if (type == 1) {
                    a3 = zd*matrix_c_x[3][i] - xd*matrix_c_z[3][i];
                    a2 = zd*matrix_c_x[2][i] - xd*matrix_c_z[2][i];
                    a1 = zd*matrix_c_x[1][i] - xd*matrix_c_z[1][i];
                    a0 = zd*matrix_c_x[0][i] - xd*matrix_c_z[0][i] + xd*z0 - zd*x0;
                }
                if (type == 2) {
/*对应“式子58.6”*/
                    a3 = ((y0-base_y)*zd-z0*yd)*matrix_c_x[3][i] - ((y0-base_y)*xd-x0*yd)*matrix_c_z[3][i];
                    a2 = ((y0-base_y)*zd-z0*yd)*matrix_c_x[2][i] - ((y0-base_y)*xd-x0*yd)*matrix_c_z[2][i];
                    a1 = ((y0-base_y)*zd-z0*yd)*matrix_c_x[1][i] - ((y0-base_y)*xd-x0*yd)*matrix_c_z[1][i];
                    a0 = ((y0-base_y)*zd-z0*yd)*matrix_c_x[0][i] - ((y0-base_y)*xd-x0*yd)*matrix_c_z[0][i] + (cap_y-base_y)*(xd*z0 - zd*x0);
                }

                roots3_base = roots_cubic_equation(a3, a2, a1, a0);
                if (roots3_base[0] != 0.0) {
                    for (int j=1; j<(int(roots3_base[0])+1); j++) {
                        u = roots3_base[j];
                        if ((u>=0.0) && (u<=1.0)) {
                            xu = matrix_c_x[0][i]+matrix_c_x[1][i]*u+matrix_c_x[2][i]*u*u+matrix_c_x[3][i]*u*u*u;

                            if (type == 1) {
                                roots_base[num_roots_base+1][0] = (xu-x0)/xd;
                                roots_base[num_roots_base+1][1] = i;
                                roots_base[num_roots_base+1][2] = u;
                                num_roots_base ++;
                            }
                            if (type == 2) {
/*对应“式子58.3”*/
                                rbt = ((y0-base_y)*xu-(cap_y-base_y)*x0)/((cap_y-base_y)*xd-yd*xu);
                                if (yd > 0) {
                                    rbt_s = (base_y-y0)/yd;
                                    rbt_b = (cap_y-y0)/yd;
                                }
                                if (yd < 0) {
                                    rbt_s = (cap_y-y0)/yd;
                                    rbt_b = (base_y-y0)/yd;
                                }
                                if ((rbt>rbt_s) && (rbt<rbt_b)) {
//                                if (1) {
                                    roots_base[num_roots_base+1][0] = rbt;
                                    roots_base[num_roots_base+1][1] = i;
                                    roots_base[num_roots_base+1][2] = u;
                                    num_roots_base ++;
                                }
                            }

                        }
                    }
                    roots_base[0][0] = float(num_roots_base);
                }
                delete [] roots3_base;
……
……
                            float nx, nz, nu;
                            int num = int(root[3]);
                            nu = root[4];
                            nx = matrix_c_x[1][num]+2.0*matrix_c_x[2][num]*nu+3.0*matrix_c_x[3][num]*nu*nu;
                            nz = matrix_c_z[1][num]+2.0*matrix_c_z[2][num]*nu+3.0*matrix_c_z[3][num]*nu*nu;

                            if (type == 1) {
                                rec.normal = unit_vector(vec3(-nx, 0, nz));
                            }
                            if (type == 2) {
/*对应“58.3 求法向量”*/
                                vec3 va = vec3(nx, 0, nz);
                                float bx = matrix_c_x[0][num]+matrix_c_x[1][num]*nu+matrix_c_x[2][num]*nu*nu+matrix_c_x[3][num]*nu*nu*nu;
                                float bz = matrix_c_z[0][num]+matrix_c_z[1][num]*nu+matrix_c_z[2][num]*nu*nu+matrix_c_z[3][num]*nu*nu*nu;
                                vec3 vb = vec3(bx, (cap_y-base_y), bz);
                                rec.normal = unit_vector(cross(va, vb));
                            }

                        }
                        if(dot(r.direction(), rec.normal) > 0) {
                            rec.normal = - rec.normal;
                        }
                        rec.mat_ptr = ma;
                        rec.u = -1.0;
                        rec.v = -1.0;
                        return true;
}

----------------------------------------------main.cpp ------------------------------------------

main.cpp

 

        vec3 ctrl_points[17] = {vec3(-4.0,  0.0, -1.0), vec3(-3.0,  0.0, -4.0), vec3(-2.0,  0.0, -4.0), vec3(-1.0,  0.0,  -1.0),
                                vec3( 1.0,  0.0, -1.0), vec3( 1.0,  0.0, -5.0), vec3( 3.0,  0.0, -5.0), vec3( 4.0,  0.0,   1.0),
                                vec3( 2.0,  0.0,  2.0), vec3( 0.5,  0.0,  2.0), vec3(-2.0,  0.0,  1.0), vec3(-2.0,  0.0,  -2.0),
                                vec3(-2.5,  0.0, -3.0), vec3(-3.0,  0.0, -1.0), vec3(-4.0,  0.0, -1.0), vec3(-3.0,  0.0,  -4.0), vec3(-2.0,  0.0, -4.0)};
        
hitable *list[1];
        list[0] = new sweeping_translational(ctrl_points, -2.0, 3.0, new lambertian(vec3(1.0, 0.0, 0.0)), 2);
        hitable *world = new hitable_list(list,1);

        vec3 lookfrom(0.0001, 10, 20);
        vec3 lookat(0, 1, 0);
        float dist_to_focus = (lookfrom - lookat).length();
        float aperture = 0.0;
        camera cam(lookfrom, lookat, vec3(0,1,0), 20, float(nx)/float(ny), aperture, 0.7*dist_to_focus);

 

输出图形如下:(前边为conicsweeping,后边为translational sweeping)

(0.0001,10, 20)

 

如果将“式子58.3”和“式子58.6”中的“(y0-yb)”换成“y0”,则图形变成这个样子:


58.5 问题说明


如果在“58.2 求根”中不做如下验证:

 

----------------------------------------------main.cpp ------------------------------------------

main.cpp

 

        vec3 ctrl_points[17] = {vec3(-4.0,  0.0, -1.0), vec3(-3.0,  0.0, -4.0), vec3(-2.0,  0.0, -4.0), vec3(-1.0,  0.0,  -1.0),
                                vec3( 1.0,  0.0, -1.0), vec3( 1.0,  0.0, -5.0), vec3( 3.0,  0.0, -5.0), vec3( 4.0,  0.0,   1.0),
                                vec3( 2.0,  0.0,  2.0), vec3( 0.5,  0.0,  2.0), vec3(-2.0,  0.0,  1.0), vec3(-2.0,  0.0,  -2.0),
                                vec3(-2.5,  0.0, -3.0), vec3(-3.0,  0.0, -1.0), vec3(-4.0,  0.0, -1.0), vec3(-3.0,  0.0,  -4.0), vec3(-2.0,  0.0, -4.0)};
        hitable *list[1];
        list[0] = new sweeping_translational(ctrl_points, 0.0, 3.0, new lambertian(vec3(1.0, 0.0, 0.0)), 2);
        hitable *world = new hitable_list(list,1);

        vec3 lookfrom(-5, 20, 12);
        vec3 lookat(0, 1.5, 0);
        float dist_to_focus = (lookfrom - lookat).length();
        float aperture = 0.0;
        camera cam(lookfrom, lookat, vec3(0,1,0), 30, float(nx)/float(ny), aperture, 0.7*dist_to_focus);

 

输出图形会多出一部分:

 

(-5, 20, 12)


 

(-5, 20, 8)


 

(-5, 20, 4)

(-5, 20, 4)(添加“验证投影光线是否有效”之后)


购物商城项目采用PHP+mysql有以及html+css jq以及layer.js datatables bootstorap等插件等开发,采用了MVC模式,建立一个完善的电商系统,通过不同用户的不同需求,进行相应的调配和处理,提高对购买用户进行配置….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值