0,引入
前续:
Q79:怎么用三角形网格(Triangle Mesh)细分曲面
http://blog.youkuaiyun.com/libing_zeng/article/details/60600404
Q80:平坦着色(Flat Shading)和平滑着色(Smooth Shading)——“Q79:怎么用三角形网格(Triangle Mesh)细分曲面”(补充)
http://blog.youkuaiyun.com/libing_zeng/article/details/60760296
【修正】问题五十五:怎么用ray tracing画Utah teapot (bicubic bezier patches)
http://blog.youkuaiyun.com/libing_zeng/article/details/69258616
这一章节,我们以Utah Teapot(Bicubic Bezier Patches)为例来进行说明。
1,理论分析
我们知道Utah Teapot是由若干个Bicubic Bezier Patch拼接而成(我们这里用到的数据是32-patches、306-vertices版本)。
关于Bezier曲面的介绍,参考:“问题五十四:怎么用ray tracing画参数方程表示的曲面(2)—— bezier surface”
http://blog.youkuaiyun.com/libing_zeng/article/details/54565264
Bezier曲面的本质是:参数方程表示的曲面。这个“参数方程”就是两条Bezier曲线的的张量积。
在求得球面的参数方程之后,用三角形网格细分该曲面的方式可以参考:
“Q79:怎么用三角形网格(Triangle Mesh)细分曲面”
http://blog.youkuaiyun.com/libing_zeng/article/details/60600404
2,C++代码实现
2.1 读取teapot数据文件
本人是将文件读取函数移植到Vector3D.cpp中
// ---------------------------------------------------------- get_teapot_data
// read utah teapot with 32 patches and 306 vertices from external file
bool get_teapot_data(int (&patches)[32][16], float (&vertices)[306][3]) {
ifstream infile( ".\\teaset\\teapot");
char str[100];
char *token;
int item_num;
int patch_num = 0;
int vertex_num = 0;
int flag = 0;
int tokens_i[16];
float tokens_f[3];
while (infile >> str) {
item_num = 0;
token = strtok(str, ",");
if ((flag == 0) || (flag == 1)) {
sscanf(token, "%d", &(tokens_i[item_num]));
if (tokens_i[0] == 32) {
flag = 1;
}
else if (tokens_i[0] == 306) {
flag = 2;
}
else {
patches[patch_num][item_num] = tokens_i[item_num];
item_num ++;
}
token = strtok(NULL, ",");
}
while (token != NULL) {
if (flag == 1) {
sscanf(token, "%d", &(tokens_i[item_num]));
patches[patch_num][item_num] = tokens_i[item_num];
}
if (flag == 2) {
sscanf(token, "%f", &(tokens_f[item_num]));
vertices[vertex_num][item_num] = tokens_f[item_num];
}
item_num ++;
token = strtok(NULL, ",");
}
if ((flag == 1) && (tokens_i[0] != 32)) {patch_num ++;}
if (flag == 2) {
if ((tokens_i[0] ==