60.1 概述

回旋体,大概是长这个样子:

回旋体是指曲线(称为“基本曲线”)围绕y轴转一圈得到的图形。

(基本曲线是由多段b-spline曲线段连接而成)

这里先强调一下:

上图中有两个坐标系:熟悉的空间三维xyz坐标系和曲线的局部二维uv坐标系。

对于回旋体,有如下特点:

上面这两个坐标系有这种关系:

对于回旋体上任意一点P(x,y,z)都对应一条曲线,则对应一个曲线的局部二维uv坐标系,则对应这个局部坐标系中一个坐标(u,v)。

60.2 求根

60.3 求法向量

60.4 看C++代码实现

----------------------------------------------sweeping_rotational.h ------------------------------------------

sweeping_rotational.h

/*这个文件和sweeping_translational.h差别不大,可以对比参照来理解*/

#ifndef SWEEPING_ROTATIONAL_H
#define SWEEPING_ROTATIONAL_H#include <hitable.h>
#include <log.h>class sweeping_rotational : public hitable
{public:sweeping_rotational() {}sweeping_rotational(vec3 cen, vec3 *cp, material *m){center = cen;ma = m;float matrix_t_6[4][4] = {{ 1,  4,  1, 0},{-3,  0,  3, 0},{ 3, -6,  3, 0},{-1,  3, -3, 1}};float matrix_t[4][4];for (int i=0; i<4; i++) {for (int j=0; j<4; j++) {matrix_t[i][j] = matrix_t_6[i][j] / 6.0;}}float points_u[6], points_v[6], b_points_u[4][1], b_points_v[4][1], b_result_u[4][1], b_result_v[4][1];int b_num = 0;float max_u, min_v, max_v;for (int i=0; i<6; i++) {points_u[i] = cp[i].x();points_v[i] = cp[i].y();}max_u = points_u[0];min_v = points_v[0];max_v = points_v[0];for (int i=0; i<6; i++) {if (max_u < points_u[i]) {max_u = points_u[i];}if (min_v > points_v[i]) {min_v = points_v[i];}if (max_v < points_v[i]) {max_v = points_v[i];}}sweeping_bl = vec3(-max_u+center.x(), min_v+center.y(), -max_u+center.z());sweeping_bh = vec3( max_u+center.x(), max_v+center.y(),  max_u+center.z());for (int i=0; i<3; i=i+1) {b_points_u[0][0] = points_u[i];b_points_u[1][0] = points_u[i+1];b_points_u[2][0] = points_u[i+2];b_points_u[3][0] = points_u[i+3];b_points_v[0][0] = points_v[i];b_points_v[1][0] = points_v[i+1];b_points_v[2][0] = points_v[i+2];b_points_v[3][0] = points_v[i+3];matrix_4_4_multiply_4_1(matrix_t, b_points_u, b_result_u);matrix_4_4_multiply_4_1(matrix_t, b_points_v, b_result_v);for (int j=0; j<4; j++) {matrix_c_u[j][b_num] = ((fabs(b_result_u[j][0])<1e-6)? (0.0):(b_result_u[j][0]));matrix_c_v[j][b_num] = ((fabs(b_result_v[j][0])<1e-6)? (0.0):(b_result_v[j][0]));}b_num ++;}}virtual bool hit(const ray& r, float tmin, float tmax, hit_record& rec) const;float matrix_c_u[4][3], matrix_c_v[4][3];vec3 sweeping_bl, sweeping_bh, center;material *ma;
};#endif // SWEEPING_ROTATIONAL_H

----------------------------------------------sweeping_rotational.cpp ------------------------------------------

sweeping_rotational.cpp

#include "sweeping_rotational.h"#include <iostream>
#include <limits>
#include "float.h"bool ray_hit_box_sr(const ray& r, const vec3& vertex_l, const vec3& vertex_h, float& t_near, float& t_far) {
/*罪恶般地又抄了一遍这个函数,光线撞击包围回旋体外面的最小盒子*/t_near = (numeric_limits<float>::min)();t_far = (numeric_limits<float>::max)();vec3 direction = r.direction();vec3 origin = r.origin();vec3 bl = vertex_l;vec3 bh = vertex_h;float array1[6];if(direction.x() == 0) {if((origin.x() < bl.x()) || (origin.x() > bh.x())) {return false;}array1[0] = (numeric_limits<float>::min)();array1[1] = (numeric_limits<float>::max)();}if(direction.y() == 0) {if((origin.y() < bl.y()) || (origin.y() > bh.y())) {return false;}array1[2] = (numeric_limits<float>::min)();array1[3] = (numeric_limits<float>::max)();}if(direction.z() == 0) {if((origin.z() < bl.z()) || (origin.z() > bh.z())) {return false;}array1[4] = (numeric_limits<float>::min)();array1[5] = (numeric_limits<float>::max)();}if((direction.x() != 0) && (direction.y() != 0) && (direction.z() != 0)) {array1[0] = (bl.x()-origin.x())/direction.x();array1[1] = (bh.x()-origin.x())/direction.x();array1[2] = (bl.y()-origin.y())/direction.y();array1[3] = (bh.y()-origin.y())/direction.y();array1[4] = (bl.z()-origin.z())/direction.z();array1[5] = (bh.z()-origin.z())/direction.z();}for (int i=0; i<6; i=i+2){if(array1[i] > array1[i+1]) {float t = array1[i];array1[i] = array1[i+1];array1[i+1] = t;}if(array1[i] >= t_near) {t_near = array1[i];}if(array1[i+1] <= t_far) {t_far = array1[i+1];}if(t_near > t_far) {return false;}if(t_far < 0) {return false;}}if (t_near != t_near) {t_near = t_near * 1;}return true;
}bool sweeping_rotational::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {
#if SWEEPING_ROTATIONAL_LOG == 1std::cout << "-------------sweeping_rotational::hit---1-------------" << endl;
#endif // SWEEPING_ROTATIONAL_LOGfloat t_near, t_far;if (ray_hit_box_sr(r, sweeping_bl, sweeping_bh, t_near, t_far)) {float xx0 = r.origin().x() - center.x();float yy0 = r.origin().y() - center.y();float zz0 = r.origin().z() - center.z();float xxd = r.direction().x();float yyd = r.direction().y();float zzd = r.direction().z();if (fabs(xxd) < 1e-6) {xxd = 1e-6;}if (fabs(yyd) < 1e-6) {yyd = 1e-6;}if (fabs(zzd) < 1e-6) {zzd = 1e-6;}
/*对应“式子60.3”*/float aaa = xxd*xxd + zzd*zzd;float bbb = 2 * ((xx0*xxd+zz0*zzd)*yyd - aaa*yy0);float ccc = (xx0*yyd-xxd*yy0)*(xx0*yyd-xxd*yy0) + (zz0*yyd-zzd*yy0)*(zz0*yyd-zzd*yy0);float ddd = yyd*yyd;float ss6[7], roots[7], roots_t[19][3], yyv, temp0, temp1, temp2;float tol = 1e-6;int num_roots_t = 0;for (int i=0; i<3; i++) {
/*“基本曲线”是有三段b-spline曲线段组成,分别对每一段求交。对应“式子60.5”*/ss6[0] = aaa*matrix_c_v[3][i]*matrix_c_v[3][i] - ddd*matrix_c_u[3][i]*matrix_c_u[3][i];ss6[1] = aaa*2*matrix_c_v[2][i]*matrix_c_v[3][i] - ddd*2*matrix_c_u[2][i]*matrix_c_u[3][i];ss6[2] = aaa*(matrix_c_v[2][i]*matrix_c_v[2][i]+2*matrix_c_v[1][i]*matrix_c_v[3][i]) -ddd*(matrix_c_u[2][i]*matrix_c_u[2][i]+2*matrix_c_u[1][i]*matrix_c_u[3][i]);ss6[3] = aaa*2*(matrix_c_v[0][i]*matrix_c_v[3][i]+matrix_c_v[1][i]*matrix_c_v[2][i]) + bbb*matrix_c_v[3][i] -ddd*2*(matrix_c_u[0][i]*matrix_c_u[3][i]+matrix_c_u[1][i]*matrix_c_u[2][i]);ss6[4] = aaa*(matrix_c_v[1][i]*matrix_c_v[1][i]+2*matrix_c_v[0][i]*matrix_c_v[2][i]) + bbb*matrix_c_v[2][i] -ddd*(matrix_c_u[1][i]*matrix_c_u[1][i]+2*matrix_c_u[0][i]*matrix_c_u[2][i]);ss6[5] = aaa*2*matrix_c_v[0][i]*matrix_c_v[1][i] + bbb*matrix_c_v[1][i]  - ddd*2*matrix_c_u[0][i]*matrix_c_u[1][i];ss6[6] = aaa*matrix_c_v[0][i]*matrix_c_v[0][i] + bbb*matrix_c_v[0][i]  - ddd*matrix_c_u[0][i]*matrix_c_u[0][i] + ccc;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;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);if (roots_t[0][0] != 0.0) {
/*对所有的交点t从小到大排序,所以最小的值跑到了最前面*/for (int i=1; i<int(roots_t[0][0]); i++) {for (int j=i+1; j<int(roots_t[0][0])+1; j++) {if (roots_t[i][0] > roots_t[j][0]) {temp0 = roots_t[i][0];roots_t[i][0] = roots_t[j][0];roots_t[j][0] = temp0;temp1 = roots_t[i][1];roots_t[i][1] = roots_t[j][1];roots_t[j][1] = temp1;temp2 = roots_t[i][2];roots_t[i][2] = roots_t[j][2];roots_t[j][2] = temp2;}}}if ((roots_t[1][0] < t_max) && (roots_t[1][0] > t_min)) {rec.t = roots_t[1][0];rec.p = r.point_at_parameter(rec.t);float nx = rec.p.x() - center.x();float nz = rec.p.z() - center.z();int num = int(roots_t[1][1]);float sss = roots_t[1][2];float nu = -(matrix_c_v[1][num]+2.0*matrix_c_v[2][num]*sss+3.0*matrix_c_v[3][num]*sss*sss);float nv =  (matrix_c_u[1][num]+2.0*matrix_c_u[2][num]*sss+3.0*matrix_c_u[3][num]*sss*sss);float ny = sqrt(nx*nx+nz*nz)*nv/nu - center.y();
/*求法向量,对应“式子60.6”*/rec.normal = unit_vector(vec3(nx, ny, nz));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;}}}return false;
}

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

main.cpp

        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)};
/*“基本曲线的控制点,6个点对应3条曲线段”*/hitable *list[1];list[0] = new sweeping_rotational(vec3( 0.0, 0.0,  0.0), ctrl_points, new lambertian(vec3(1.0, 0.0, 0.0)));hitable *world = new hitable_list(list,1);vec3 lookfrom(0, 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);

输出图形如下:

vec3 lookfrom(0, 10, 20);

vec3 lookfrom(10, 10, 10);

来张组合图:

        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)};hitable *list[4];list[0] = new sweeping_rotational(vec3( 0.0, 0,  0.0), ctrl_points, new dielectric(4.5));list[1] = new sweeping_rotational(vec3(-5.0, 0,  0.0), ctrl_points, new lambertian(vec3(1.0, 0.0, 0.0)));list[2] = new sweeping_rotational(vec3( 5.0, 0,  0.0), ctrl_points, new lambertian(vec3(1.0, 0.0, 1.0)));list[3] = new sphere(vec3(0,-103,-1), 100, new metal(vec3(0.0, 1.0, 0.5), 0.0), 0);hitable *world = new hitable_list(list,4);vec3 lookfrom(0, 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), 25, float(nx)/float(ny), aperture, 0.7*dist_to_focus);

输出图形如下:

一个玻璃材质,两个漫射材质,最下面的大球是镜面材质的

三个全是红色漫射材质时的图形如下:

问题六十:怎么用ray tracing画回旋体(rotational sweeping / revolution)相关推荐

  1. 问题六十六:怎么用ray tracing画CSG(Constructive Solid Geometry 构造实体几何)图形

    66.1 概述 什么是CSG图形? 若干简单图形通过集合运算后得到的复杂图形,被称为"CSG图形". 其中"简单图形",包括:sphere, box, cyli ...

  2. 问题五十六:怎么用ray tracing画参数方程表示的曲面(3)—— b-spline surface

    接"问题五十四",已经简单学习了bezier曲线曲面,知道了双三次bezier曲面的矩阵表示形式,同时也以此画出了曲面图形. 这一章节主要以对比bezier曲线曲面和b-splin ...

  3. 问题四十六:怎么用ray tracing画superellipsoid

    46.1 数学推导 书上有给出超级椭圆面的方程: 同时也给出了参考图: 只有当足够接近真实值时,迭代才会收敛,才能求得满足精确条件的方程解. 对于超级椭圆,我们采用的的迭代初值是光线于如下四个长方体交 ...

  4. 问题三十三:怎么用ray tracing画特殊长方体(box)

    33.1 怎么用ray tracing画特殊长方体 在光线追踪中被用到的一种常见形态是长方体盒子.这种基本物体被用于可见物体和包围盒,包围盒被用于加速复杂物体的相交测试. 吐槽:单词都认识,就是不知道 ...

  5. 问题五十三:怎么用ray tracing画参数方程表示的曲面(1)

    首先,以球面为例学习怎么用ray tracing画参数方程表示的曲面:然后,再画一个牛角面. 特别说明:这一章节所画的曲面只是示意性的,所以先不care图片上的瑕疵. 53.1 数学推导 球面的参数方 ...

  6. 问题五十四:怎么用ray tracing画参数方程表示的曲面(2)—— bezier surface

    首先,需要说明的是: 这一章节可以看作"问题五十三"的另一个例子--bicubic bezier surface: 之前已经用"球面"和"牛角面&qu ...

  7. 问题六十三:怎么用ray tracing画sphere sweeping图形

    63.1 概述 Translational sweeping.conic sweeping.rotational sweeping都是任意曲线以某种固定方式移动后形成的图形. 接下来,我们要画的sph ...

  8. 问题六十三:怎么用ray tracing画sphere sweeping图形(2)——teapot

    63.5 组合rotational sweeping和sphere sweeping画一个teapot ----------------------------------------------ma ...

  9. Q77:怎么用Ray Tracing画仿射变换之后的图形

    77.1 理论说明 如上图所示,椭球面是球面通过仿射变换T得到的. 现在我们的问题是:怎么ray trace变换后的椭球面? (先重申一点:经过仿射变换之后,直线还是直线,光线还是光线) 我们应该这么 ...

最新文章

  1. Science:微生物组“淘金热”,从人体中发现新型抗菌剂
  2. 逆天改命,机械飞升:渐冻症科学家拒绝等死,将自己改造成了「半机械人」...
  3. 智能车竞赛技术报告 | 电磁越野组 - 哈尔滨工业大学 - 紫丁香三队
  4. 新手零基础学习Python第一步,搭建开发环境!
  5. [Qt教程] 第36篇 网络(六)UDP
  6. css3 - target
  7. 计算思维c语言软件,C语言编程入门与计算思维
  8. html对话框跳转页面,html5各种页面切换效果和模态对话框用法总结
  9. http status code —— http 状态码
  10. CocoaPods加载第三方库
  11. Pr 入门教程,如何在节目监视器中修剪剪辑?
  12. 超链接小点html,html超链接取消鼠标点指显示小手
  13. 使用vuex实现一个简单的小应用
  14. 是面试官放水,还是实在公司太缺人?这都没挂,阿里巴巴原来这么容易进...
  15. Vue中使用Tinymce-edtio
  16. 【高级篇 / FortiGate-VM】(6.4) ❀ 04. 虚拟 PC 通过 FortiGate VM 上网 ❀ FortiGate 防火墙
  17. Kotlin版 极简 干货集中营 APP
  18. 一个毕业6年的程序员工作经历和成长感悟(下)
  19. 别耍小聪明—leo看赢在中国第三季(1)
  20. CCPC-Wannafly Winter Camp 总结

热门文章

  1. 91期:2016阿里安全峰会重点资料新鲜开放,不能错过
  2. 多线程 之 生产者与消费者
  3. 元数据驱动设计 —— 设计一套用于API数据检索的灵活引擎
  4. 第四章——SQLServer2008-2012资源及性能监控(1)
  5. RabbitMQ之路由选择
  6. 配置 MVC3 时,403 404 错误
  7. 清华大学MBA在职班第一学年第二学期课表
  8. 【前端】关于事件的代码片段
  9. python 实现SOM:代码注释与应用示例
  10. Oracle数据库DBA必备基本技能