35.3 椭球抛物面

35.3.1 数学推导

椭球抛物面的方程如下:

所以,其一:我们需要对两个实根进行排序(先处理小的)

另外,由于,是开放曲面,也就是,光线有可能撞击到曲面的正反两面,所以,对于撞击点处的标准化之后的法向量,我们需要做如下判断:

if (dot(rec.normal,r.direction()) > 0) {

rec.normal =-rec.normal;

}//(法向量决定着反射光线和折射光线)

还有,由于我们引入了height_y参数来限制曲面的高度,但是,我们要注意到:小实根对应的交点超出高度范围时(之前的一贯做法:小根不在t_min、t_max范围,就直接return false),大实根是有可能在高度范围的(而且,如果在范围的话,光线撞击的曲面的内表面,这时的法向量是需要反向的)。

35.3.2 看C++代码实现

----------------------------------------------quadratic_paraboloid.h ------------------------------------------

quadratic_paraboloid.h

#ifndef QUADRATIC_PARABOLOID_H
#define QUADRATIC_PARABOLOID_H#include <hitable.h>class quadratic_paraboloid : public hitable
{public:quadratic_paraboloid() {}quadratic_paraboloid(vec3 cen, float p, float q, int hy, material *m) : center(cen), focus_directrix_p(p), focus_directrix_q(q), height_half_y(hy), ma(m) {}
/*
(x-xc)^2/2*p + (z-zc)^2/2*q = (y-yc)
(p>0, q>0)
*/virtual bool hit(const ray& r, float tmin, float tmax, hit_record& rec) const;vec3 center;float focus_directrix_p;float focus_directrix_q;int height_half_y;material *ma;
};#endif // QUADRATIC_PARABOLOID_H

----------------------------------------------quadratic_paraboloid.cpp ------------------------------------------

quadratic_paraboloid.cpp

#include "quadratic_paraboloid.h"#include <iostream>
using namespace std;bool quadratic_paraboloid::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {
        float A = focus_directrix_q*r.direction().x()*r.direction().x()+ focus_directrix_p*r.direction().z()*r.direction().z();float B = 2*focus_directrix_q*r.direction().x()*(r.origin().x()-center.x())+ 2*focus_directrix_p*r.direction().z()*(r.origin().z()-center.z())- 2*focus_directrix_p*focus_directrix_q*r.direction().y();float C = focus_directrix_q*(r.origin().x()-center.x())*(r.origin().x()-center.x())+ focus_directrix_p*(r.origin().z()-center.z())*(r.origin().z()-center.z())- 2*focus_directrix_p*focus_directrix_q*(r.origin().y()-center.y());
        float temp, temp1, temp2;vec3 pc;if(A == 0) {if (B == 0) {return false;}else {temp = -C/B;if (temp < t_max && temp > t_min) {rec.t = temp;rec.p = r.point_at_parameter(rec.t);if (((rec.p.y()-center.y()) > -height_half_y)
&& ((rec.p.y()-center.y()) < height_half_y)) {pc = rec.p - center;
                        rec.normal = unit_vector(vec3(2*focus_directrix_q*pc.x(), -2*focus_directrix_p*focus_directrix_q, 2*focus_directrix_p*pc.z()));
                        if (dot(rec.normal, r.direction()) > 0) {rec.normal = -rec.normal;}rec.mat_ptr = ma;return true;}else {return false;}}}}else {float discriminant = B*B - 4*A*C;if (discriminant >= 0) {temp1 = (-B - sqrt(discriminant)) / (2.0*A);temp2 = (-B + sqrt(discriminant)) / (2.0*A);if (temp1 > temp2) {//make sure that temp1 is smaller than temp2temp = temp1;temp1 = temp2;temp2 = temp;}if (temp1 < t_max && temp1 > t_min) {rec.t = temp1;rec.p = r.point_at_parameter(rec.t);if (((rec.p.y()-center.y()) > -height_half_y)
&& ((rec.p.y()-center.y()) < height_half_y)) {pc = rec.p - center;
                        rec.normal = unit_vector(vec3(2*focus_directrix_q*pc.x(), -2*focus_directrix_p*focus_directrix_q, 2*focus_directrix_p*pc.z()));
                        if (dot(rec.normal, r.direction()) > 0) {rec.normal = -rec.normal;}rec.mat_ptr = ma;return true;}else {
//                        return false;}}if (temp2 < t_max && temp2 > t_min) {rec.t = temp2;rec.p = r.point_at_parameter(rec.t);if (((rec.p.y()-center.y()) > -height_half_y)
&& ((rec.p.y()-center.y()) < height_half_y)) {pc = rec.p - center;
                        rec.normal = unit_vector(vec3(2*focus_directrix_q*pc.x(), -2*focus_directrix_p*focus_directrix_q, 2*focus_directrix_p*pc.z()));
                        if (dot(rec.normal, r.direction()) > 0) {rec.normal = -rec.normal;}rec.mat_ptr = ma;return true;}else {
//                        return false;}}}return false;}
}

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

main.cpp

        hitable *list[2];list[0] = new sphere(vec3(0.0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));list[1] = new quadratic_paraboloid(vec3(0.5, 1.5, 0), 1, 2, 1, new lambertian(vec3(0.9, 0.1, 0.5)));hitable *world = new hitable_list(list,2);vec3 lookfrom(0,5,10);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);

输出图片:

问题三十五: 怎么用ray tracing画二次曲面(quadratic surfaces)(3)——椭球抛物面相关推荐

  1. 问题三十五: 怎么用ray tracing画二次曲面(quadratic surfaces)(1)——椭球面

    二次曲面包括:球面.椭圆球面.单页双曲面.双页双曲面.椭圆锥面.椭圆柱面.椭圆抛物面.双曲抛物面等等. 注意到:只有球面和椭球面是封闭面,其他的都是开放面. 二次曲面是有方程的(我们已经学过的多边形. ...

  2. 问题三十五: 怎么用ray tracing画二次曲面(quadratic surfaces)(2)——单页双曲面、双页双曲面、椭圆锥面、椭圆柱面

    35.2.1 数学推导 单页双曲面.双页双曲面.椭圆锥面.椭圆柱面. 这四个二次曲面方程共同形式: 但是,注意到,这些曲面都是开放曲面.在画图时,需要限制曲面的范围(以免曲面覆盖整个画面). 我们在这 ...

  3. 问题三十五: 怎么用ray tracing画二次曲面(quadratic surfaces)(4)——双曲抛物面(马鞍面)

    35.4 双曲抛物面(马鞍面) 35.4.1 数学推导 双曲抛物面的方程如下: 35.4.2 看C++代码实现 -------------------------------------------- ...

  4. 问题三十五: 怎么用ray tracing画二次曲面(quadratic surfaces)(5)——汇总

    二次曲面来张合照: hitable *list[9];list[0] = new sphere(vec3(0.0,-100.5,-1), 100, new lambertian(vec3(0.8, 0 ...

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

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

  6. 问题五十:怎么用ray tracing画blobs

    这一节,画这个: 参考文献: Blinn, J.F., A generalization of algebraic surfacedrawing. ACM Trans. Graph. 1(3) , 2 ...

  7. 问题六十:怎么用ray tracing画回旋体(rotational sweeping / revolution)

    60.1 概述 回旋体,大概是长这个样子: 回旋体是指曲线(称为"基本曲线")围绕y轴转一圈得到的图形. (基本曲线是由多段b-spline曲线段连接而成) 这里先强调一下: 上图 ...

  8. NeHe OpenGL第三十五课:播放AVI

    NeHe OpenGL第三十五课:播放AVI 在OpenGL中播放AVI: 在OpenGL中如何播放AVI呢?利用Windows的API把每一帧作为纹理绑定到OpenGL中,虽然很慢,但它的效果不错. ...

  9. 微信小程序把玩(三十五)Video API

    原文:微信小程序把玩(三十五)Video API 电脑端不能测试拍摄功能只能测试选择视频功能,好像只支持mp4格式,值得注意的是成功之后返回的临时文件路径是个列表tempFilePaths而不是tem ...

最新文章

  1. Kendall’s tau-b,pearson、spearman三种相关性的区别(有空整理信息检索评价指标)
  2. spring装配Bean过程
  3. Mongodb分布式集群搭建
  4. IIS+php无法上传图片(转载自http://hi.baidu.com/0wem/blog/item/d222db163c3c831e972b4306.html)...
  5. java 90 训练营 二期下载_90天java进阶营二期 主流java技术与热门开源项目视频教程...
  6. java swing jdk_javax.swing
  7. Deal with relational data using libFM with blocks
  8. OSChina 周五乱弹 ——变态要从娃娃抓起
  9. 【感悟】人生本如梦,学会看淡一切。
  10. 中文文档列表 - Oracle Database (文档 ID 1533057.1)
  11. 文字处理技术:新布局思路验证成功
  12. dubbogo PMC何鑫铭:没有热爱就做不成这件事情
  13. 分享大牛们的刷题经验——比你聪明的人还在拼命努力,你有什么资格浪费时间
  14. Docker上安装DM8数据库
  15. HTML网页设计制作大作业 html+css+js萌宠之家 网页设计与实现
  16. html返回到处乱跑,电脑鼠标乱动不受控制(鼠标到处乱跑不听使唤)
  17. 固定效应还是随机效应?
  18. 如何将LaTeX公式拷贝到Word中
  19. 阿里api网关接口客户端demo,java实现源码,其他语言可参考
  20. 绘画系统(02):【纲】Paint Devices and Backends[官翻]

热门文章

  1. 【案例】复制静止问题一则
  2. 在鼠标点击的位置 ,添加一个div ,类似手表右键菜单
  3. 宏、函数、宏和函数的区别
  4. BZOJ1111 : [POI2007]四进制的天平Wag
  5. OSPF(Open Shortest Path First)开放式最短路径优先协议05
  6. 【EOS】2.4 EOS数据存储
  7. Cache之全相连映射
  8. Python中容易忽视的知识点
  9. SOA架构设计和相关案例分析
  10. continue跳转