Q104:怎么用ray tracing画基于磨边楔形的“花环(Rosette)”
来源:互联网 发布:贵州省政法委数据维稳 编辑:程序博客网 时间:2024/04/30 12:35
0,引入
在Q103中,咱了解了磨边的楔形物体。
接下来,咱用这种楔形物体来拼出一个“花环”。
先看看,咱要画的花环是长什么样子:
从上图来看,我们需要完成两件事情:
1,用磨边楔形拼出“花环”的几何模型;
2,给“花环”中的每一个磨边楔形设置不同/随机的大理石纹理。
1,花环的几何模型
回忆一下磨边楔形的构造函数中的相关参数:
BeveledWedge::BeveledWedge( const double _y0, // minimum y value const double _y1, // maximum y value const double _r0, // inner radius const double _r1, // outer radius const double _rb, // bevel radius const double _phi0, // minimum azimuth angle in degrees const double _phi1) // maximum azimuth angle in degrees
从如上参数来看:
纵向控制楔形形状的是内经r0和外径r1;
横向控制楔形形状的是起始方位角phi0和终止方位角phi1。
所以,为了是所有的楔形刚好拼成一个“花环”,我们的做法是:
根据单层环上楔形的个数来等分圆周;
根据花环的层数来等分花环的内经和外径之间的距离(宽度)。
C++代码实现:
新建一个称为“Rosette”的类,该类是继承于Grid:
class Rosette: public Grid { public: Rosette(void); Rosette( const int _num_rings, const double _hole_radius, const double _ring_width, const double _rb, const double _y0, const double _y1); Rosette(const Rosette& bb); virtual Rosette* clone(void) const; Rosette& operator= (const Rosette& rhs); virtual ~Rosette(void); void construct_rosette(void); private: double num_rings; // maximum of 6 double hole_radius; double ring_width; double rb; // bevel radius double y0, y1; // y axis extents static const int num_wedges[6]; // number of wedges in each ring};
具体实现construct_rosette(void)成员方法:
const int Rosette::num_wedges[6] = {10, 12, 15, 18, 24, 36}; // these numbers exactly divide into 360// ------------------------------------------------------------------------------ construct_rosette// this function constructs the wedges in a rosette pattern and stores them in a grid// this is the regular version, for Figure 21.11voidRosette::construct_rosette(void) { for (int k = 0; k < num_rings; k++) { for (int j = 0; j < num_wedges[k]; j++) { double angle_width = 360 / num_wedges[k]; // the azimuth angle extent of each wedge double r0 = hole_radius + k * ring_width; double r1 = hole_radius + (k + 1) * ring_width; double phi0 = j * angle_width; double phi1 = (j + 1) * angle_width; BeveledWedge* wedge_ptr = new BeveledWedge(y0, y1, r0, r1, rb, phi0 , phi1); add_object(wedge_ptr); } }}
2,给“花环”中的每一个磨边楔形设置不同/随机的大理石纹理。
相关代码片段如下:
// put a different random marble texture on each wedge // ramp image: Image* image_ptr = new Image; image_ptr->read_ppm_file(".\\TextureFiles\\ppm\\BlueMarbleRamp.ppm"); // marble texture parameters int num_octaves = 4; float lacunarity = 2.0; float gain = 0.5; float perturbation = 3.0; int num_objects = rosette_ptr->get_num_objects(); for (int j = 0; j < num_objects; j++) { // noise: CubicNoise* noise_ptr = new CubicNoise; noise_ptr->set_num_octaves(num_octaves); noise_ptr->set_gain(gain); // not relevant when num_octaves = 1 noise_ptr->set_lacunarity(lacunarity); // not relevant when num_octaves = 1 // marble texture: FBmTextureRamp* marble_ptr = new FBmTextureRamp(image_ptr); marble_ptr->set_noise(noise_ptr); marble_ptr->set_perturbation(perturbation); // transformed marble texture InstanceTexture* wedge_marble_ptr = new InstanceTexture(marble_ptr); set_rand_seed(j * 10); wedge_marble_ptr->scale(0.25); wedge_marble_ptr->rotate_x(20.0 * (2.0 * rand_float() - 1.0)); wedge_marble_ptr->rotate_y(30.0 * (2.0 * rand_float() - 1.0)); wedge_marble_ptr->rotate_z(45.0 * (2.0 * rand_float() - 1.0)); wedge_marble_ptr->translate(10.0 * (2.0 * rand_float() - 1.0), 20.0 * (2.0 * rand_float() - 1.0), 30.0 * (2.0 * rand_float() - 1.0)); // marble material SV_Matte* sv_matte_ptr = new SV_Matte; sv_matte_ptr->set_ka(0.35); sv_matte_ptr->set_kd(0.75); sv_matte_ptr->set_cd(wedge_marble_ptr); rosette_ptr->store_material(sv_matte_ptr, j); // store material in the specified wedge }
(Rosette是继承于Grid的,Grid中按顺序保存了每一个楔形的对象指针。先获取Rosette中总的楔形个数num_objects,然后依次给每一楔形设置随机的大理石纹理。)
3,Debug
在当前代码的基础上(主要指的是BeveledWedge),生成的“花环”图形是这样的:
当前的问题是:有些磨边楔形的磨边处的圆环面缺失了。
老实说,针对这个问题,本人算是付出了“惨重”的代价:
其一:一开始竟然没有发现这个问题,然后将Rosette用到了后面的一个场景中,由于该场景涉及的图形较多,生成高分辨率的图形耗时长达4~5个小时,本人花费了几十个小时生成了若干个不同距离的图形,后来发现Rosette的问题,一切重来;
其二:在发现Rosette存在部分缺失时,小生愚钝,又花了好几个小时才调试好。
出现该问题的原因是什么?
官网提供的BeveledWedge的相关代码,对应的phi是标准的“与+Z轴的夹角”(但又不是通常情况那样以+Z轴为起点顺时针旋转,而是逆时针旋转),而本人的“部分圆环”实现代码对应的phi用的是“与+X轴的夹角”(因为,我们一般是从+Z轴向着-Z的视角,选“与+X轴的夹角更为直观”)。所以,在给“部分圆环”传参数时,需要将“与+Z轴的夹角”转换为“与+X的夹角”。
怎么解决这个问题呢?
当前的做法是:直接减个90度。
这样,在减90度之后的phi_min或者phi_max都有可能出现负数。
而“部分圆环”中判断撞击点是否有效是依据phi是否在该[phi_min,phi_max]内,这个phi的范围是[0,360]。
所以,当phi_min或者phi_max中出现一个负数时,咱就给phi_min和phi_max分别加上360。
但是,这还有一个问题:考虑到phi_max原本可能是正数,而加360之后的值就大于了360度。而“部分圆环”中尚未考虑这种情况。
所以,“部分圆环”中判断phi值是否有效时,添加一种情况:若phi+360之后还小于phi_max,则phi值肯定有效。
代码修改
查这个问题花了很长时间,但是需要修改的代码却不多:
在给“部分圆环”传参数时,添加如下绿框标注的代码:
在“部分圆环”中判断phi是否有效时,添加如下绿框标注的代码:
4,其他说明
完整代码下载链接:
http://download.csdn.net/detail/libing_zeng/9815623
- Q104:怎么用ray tracing画基于磨边楔形的“花环(Rosette)”
- 问题五十三:怎么用ray tracing画参数方程表示的曲面(1)
- Q77:怎么用Ray Tracing画仿射变换之后的图形
- 问题十二:怎么用ray tracing画第一张图
- 问题三十九:怎么用ray tracing画圆环
- 问题四十二:怎么用ray tracing画任意圆环片段
- 问题四十六:怎么用ray tracing画superellipsoid
- 问题四十七:怎么用ray tracing画superellipsoid (2)
- 问题五十:怎么用ray tracing画blobs
- 问题五十一:怎么用ray tracing画tear drop
- 问题五十七:怎么用ray tracing画translational sweeping图形
- 问题五十八:怎么用ray tracing画conic sweeping图形
- 问题六十三:怎么用ray tracing画sphere sweeping图形
- 问题五十四:怎么用ray tracing画参数方程表示的曲面(2)—— bezier surface
- 问题五十六:怎么用ray tracing画参数方程表示的曲面(3)—— b-spline surface
- 问题四十四:怎么用ray tracing画空间任意位置的圆环的任意片段
- 问题三十二:怎么用ray tracing画多边形(polygon, triangle)
- 问题三十三:怎么用ray tracing画特殊长方体(box)
- 如何快速转载CSDN中的博客
- JAVA保存文件
- 面向对象原则:高内聚、低耦合。
- 机器学习实战 step-01
- 离散数学逻辑运算符C++实现
- Q104:怎么用ray tracing画基于磨边楔形的“花环(Rosette)”
- java--面向对象
- <<HTML5从入门到精通>>
- 计算某日是该年第几天
- JAVA去重复字符串
- android标题栏中添加返回按钮
- Spring Task 任务调度器
- layabox笔记 目录结构
- OpenGL系列教程(1)——认识OpenGL