Q97:怎么用三角形网格细分Bezier曲面——以Utah Teapot为例
0,引入
前续:
Q79:怎么用三角形网格(Triangle Mesh)细分曲面
http://blog.csdn.net/libing_zeng/article/details/60600404
Q80:平坦着色(Flat Shading)和平滑着色(Smooth Shading)——“Q79:怎么用三角形网格(Triangle Mesh)细分曲面”(补充)
http://blog.csdn.net/libing_zeng/article/details/60760296
【修正】问题五十五:怎么用ray tracing画Utah teapot (bicubic bezier patches)
http://blog.csdn.net/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.csdn.net/libing_zeng/article/details/54565264
Bezier曲面的本质是:参数方程表示的曲面。这个“参数方程”就是两条Bezier曲线的的张量积。
在求得球面的参数方程之后,用三角形网格细分该曲面的方式可以参考:
“Q79:怎么用三角形网格(Triangle Mesh)细分曲面”
http://blog.csdn.net/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 filebool 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] == 306)) {tokens_i[0] = 0;}
else {vertex_num ++;}
}
}
infile.close();
return true;
}// ---------------------------------------------------------- matrix_4_4_multiply_4_4void matrix_4_4_multiply_4_4(const float matrix1[4][4], const float matrix2[4][4], float (&result)[4][4]) {
for (int k=0; k<4; k++) { for (int i=0; i<4; i++) { result[i][k] = 0.0;
for (int j=0; j<4; j++) { result[i][k] = result[i][k] + matrix1[i][j]*matrix2[j][k];
}
}
}
}
2.2 矩阵运算
计算过程会用到“矩阵运算”(没有使用“矩阵类”,仍旧使用二维数组表示矩阵)。矩阵运算的相关函数也是在Vector3D.cpp中实现:
// ---------------------------------------------------------- matrix_4_4_multiply_4_4void matrix_4_4_multiply_4_4(const float matrix1[4][4], const float matrix2[4][4], float (&result)[4][4]) {
for (int k=0; k<4; k++) { for (int i=0; i<4; i++) { result[i][k] = 0.0;
for (int j=0; j<4; j++) { result[i][k] = result[i][k] + matrix1[i][j]*matrix2[j][k];
}
}
}
}// ---------------------------------------------------------- matrix_1_4_multiply_4_4void matrix_1_4_multiply_4_4(const float matrix1[1][4], const float matrix2[4][4], float (&result)[1][4]) {
for (int k=0; k<4; k++) { result[0][k] = 0.0;
for (int j=0; j<4; j++) { result[0][k] = result[0][k] + matrix1[0][j]*matrix2[j][k];
}
}
}// ---------------------------------------------------------- matrix_1_4_multiply_4_1void matrix_1_4_multiply_4_1(const float matrix1[1][4], const float matrix2[4][1], float &result) {
result = 0.0;
for (int j=0; j<4; j++) { result = result + matrix1[0][j]*matrix2[j][0];
}
}
2.3 细分Bezier曲面
像之前一样,细分函数在Grid.cpp中实现。
// ------------------------------------ tessellate_flat_bezier_patches ---------------------------------------
// tesselate a cubic bezier patch into flat triangles that are stored directly in the gridvoid
Grid::tessellate_flat_bezier_patches(const int horizontal_steps, const int vertical_steps,float vertices[306][3], int patches[32][16], const int patches_num) {Vector3D patches_vertices[patches_num][16];float matrix_c_x[4][4], matrix_c_y[4][4], matrix_c_z[4][4];float points_x[4][4], points_y[4][4], points_z[4][4];float points_x_t[4][4], points_y_t[4][4], points_z_t[4][4];float uuu[1][4], vvv[4][1];float uuu1[1][4], vvv1[4][1];float xxx_t[1][4], yyy_t[1][4], zzz_t[1][4];float xxx, yyy, zzz;float xxx1, yyy1, zzz1;float xxx2, yyy2, zzz2;float xxx3, yyy3, zzz3;float matrix_t[4][4] = {{ 1, 0, 0, 0},{-3, 3, 0, 0},{ 3, -6, 3, 0},{-1, 3, -3, 1}};float matrix[4][4] = {{1, -3, 3, -1},{0, 3, -6, 3},{0, 0, 3, -3},{0, 0, 0, 1}};int ip1, ip2, ipv;for (int i=0; i<patches_num; i++) {for (int j=0; j<16; j++) {ip1 = int(j/4);ip2 = int(j%4);ipv = patches[i][j] - 1;points_x[ip1][ip2] = vertices[ipv][0];points_y[ip1][ip2] = vertices[ipv][1];points_z[ip1][ip2] = vertices[ipv][2];}matrix_4_4_multiply_4_4(matrix_t, points_x, points_x_t);matrix_4_4_multiply_4_4(points_x_t, matrix, matrix_c_x);matrix_4_4_multiply_4_4(matrix_t, points_y, points_y_t);matrix_4_4_multiply_4_4(points_y_t, matrix, matrix_c_y);matrix_4_4_multiply_4_4(matrix_t, points_z, points_z_t);matrix_4_4_multiply_4_4(points_z_t, matrix, matrix_c_z);for (int k = 0; k <= vertical_steps - 1; k++) {for (int m = 0; m <= horizontal_steps - 1; m++) {uuu[0][0] = 1.0;uuu[0][1] = float(m) / float(horizontal_steps);uuu[0][2] = uuu[0][1] * uuu[0][1];uuu[0][3] = uuu[0][1] * uuu[0][2];vvv[0][0] = 1.0;vvv[1][0] = float(k) / float(vertical_steps);vvv[2][0] = vvv[0][1] * vvv[0][1];vvv[3][0] = vvv[0][1] * vvv[0][2];uuu1[0][0] = 1.0;uuu1[0][1] = float(m+1) / float(horizontal_steps);uuu1[0][2] = uuu1[0][1] * uuu1[0][1];uuu1[0][3] = uuu1[0][1] * uuu1[0][2];vvv1[0][0] = 1.0;vvv1[1][0] = float(k+1) / float(vertical_steps);vvv1[2][0] = vvv1[0][1] * vvv1[0][1];vvv1[3][0] = vvv1[0][1] * vvv1[0][2];matrix_1_4_multiply_4_4(uuu, matrix_c_x, xxx_t);matrix_1_4_multiply_4_1(xxx_t, vvv, xxx);matrix_1_4_multiply_4_4(uuu, matrix_c_y, yyy_t);matrix_1_4_multiply_4_1(yyy_t, vvv, yyy);matrix_1_4_multiply_4_4(uuu, matrix_c_z, zzz_t);matrix_1_4_multiply_4_1(zzz_t, vvv, zzz);matrix_1_4_multiply_4_4(uuu, matrix_c_x, xxx_t);matrix_1_4_multiply_4_1(xxx_t, vvv1, xxx1);matrix_1_4_multiply_4_4(uuu, matrix_c_y, yyy_t);matrix_1_4_multiply_4_1(yyy_t, vvv1, yyy1);matrix_1_4_multiply_4_4(uuu, matrix_c_z, zzz_t);matrix_1_4_multiply_4_1(zzz_t, vvv1, zzz1);matrix_1_4_multiply_4_4(uuu1, matrix_c_x, xxx_t);matrix_1_4_multiply_4_1(xxx_t, vvv, xxx2);matrix_1_4_multiply_4_4(uuu1, matrix_c_y, yyy_t);matrix_1_4_multiply_4_1(yyy_t, vvv, yyy2);matrix_1_4_multiply_4_4(uuu1, matrix_c_z, zzz_t);matrix_1_4_multiply_4_1(zzz_t, vvv, zzz2);matrix_1_4_multiply_4_4(uuu1, matrix_c_x, xxx_t);matrix_1_4_multiply_4_1(xxx_t, vvv1, xxx3);matrix_1_4_multiply_4_4(uuu1, matrix_c_y, yyy_t);matrix_1_4_multiply_4_1(yyy_t, vvv1, yyy3);matrix_1_4_multiply_4_4(uuu1, matrix_c_z, zzz_t);matrix_1_4_multiply_4_1(zzz_t, vvv1, zzz3);// define the first trianglePoint3D v0(xxx2, yyy2, zzz2);Point3D v1(xxx3, yyy3, zzz3);Point3D v2( xxx, yyy, zzz);Triangle* triangle_ptr1 = new Triangle(v0, v1, v2);objects.push_back(triangle_ptr1);// define the second trianglev0 = Point3D(xxx1, yyy1, zzz1);v1 = Point3D( xxx, yyy, zzz);v2 = Point3D(xxx3, yyy3, zzz3);Triangle* triangle_ptr2 = new Triangle(v0, v1, v2);objects.push_back(triangle_ptr2);}}}}
如上代码的截图分析如下:
3,测试图形
3.1 测试代码
3.2 输出图形
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_20,20
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_40,40_190s_ns1
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_40,40_207s_ns16
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_40,40_176s_ns16_marble,p0.1
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_40,40_183s_ns16_marble,p4
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_40,40_226s_ns16_sandstone,p0.1
teapot_32_0,0,100_rx-90,ts(0,-2,0)_light,directional(10,-20,-20)_40,40_234s_ns16_wood
4,其他说明
完整代码链接:http://download.csdn.net/detail/libing_zeng/9804597
Q97:怎么用三角形网格细分Bezier曲面——以Utah Teapot为例相关推荐
- Q98:三角形网格细分Bezier曲面时,注意三角形顶点的顺序(确保其对应的法向量向外)
这一章节又是修正之前的错误."Q97:怎么用三角形网格细分Bezier曲面--以Utah Teapot为例" (http://blog.csdn.net/libing_zeng/a ...
- Q99:当Bezier曲面(Utah Teapot)同时遇上“噪声纹理”和“Phong反射模型”
1,理论介绍 完整标题应该是:当"三角形网格细分后的"Bezier曲面(Utah Teapot)同时遇上"噪声纹理"和"Phong反射模型" ...
- Q100:怎么用三角形网格细分回旋体(rotational sweeping / revolution)
0,引入 我们在"问题六十:怎么用ray tracing画回旋体(rotational sweeping / revolution)"中已经学习了这类曲面的画法: http://b ...
- Geometry 曲面细分和曲面简化
Geometry 曲面细分和曲面简化 1 曲面细分 a) Loop细分 b) Catmull-Clark细分(Catmull-Clark Subdivision) 曲面简化 边坍缩 总结: 1 曲面细 ...
- OpenGL(可编程管线):Bezier曲面
Bezier曲面 Bezier线 de Casteljau算法 Bezier曲面 bezier曲面编程思想 实例 代码 运行结果 Bezier线 贝塞尔曲线由一组参数方程定义,方程组中使用控制点指定特 ...
- MFC绘制双有理Bezier曲面
MFC绘制双有理Bezier曲面 双有理Bezier曲面可以精确表示任意二次曲面,如球面.柱面及圆锥面等,下面给出1/8球面的绘制类. 参考<计算几何算法与实现>–孔令德 #pragma ...
- 计算机图形学【GAMES-101】5、几何(距离函数SDF、点云、贝塞尔曲线、曲面细分、曲面简化)
快速跳转: 1.矩阵变换原理Transform(旋转.位移.缩放.正交投影.透视投影) 2.光栅化(反走样.傅里叶变换.卷积) 3.着色计算(深度缓存.着色模型.着色频率) 4.纹理映射(重心坐标插值 ...
- MFC绘制旋转Bezier曲面
MFC绘制旋转Bezier曲面 给出一条Bezier曲线,通过旋转64个控制点,4个曲面片,绘制出一个完整曲面 已知四个控制点:(50,100)(150,70)(120,-30)(90,-80) 理论 ...
- 曲面细分(subdivision)曲面细分着色器GPU的LOD
曲面细分是指将一个模型的面合理的分成更多小的面,从而提升模型精度,提高渲染效果 曲面简化是指将一个模型的面合理的合成更少的面,从而降低模型精度,为特定情形下提供使用(如LOD技术) .这一过程是可以在 ...
最新文章
- [BZOJ2527]Meteors
- 你在做大数据?你有目标么?
- python颜色填充随机_使用python中的随机数据填充mysql表
- PC如何接管手机的双因子身份验证 靠的是英特尔的CPU
- ESP8266串口模块的基本使用【转】
- 配合理lcd的c语言小游戏,C语言源程序LCD.doc
- Spring的核心机制依赖注入,Junit测试与Java基础Getter和Setter两种方法意义——2017.07.26...
- STM32F7xx —— QSPI
- SpringCloud Config手动刷新及自动刷新
- python儿童入门视频-Python入门视频课程
- html pt兼容,FCKEditor,一个HTML可视化编辑器,兼容很好
- c语言正弦函数图像,正弦函数图像
- 计算机科学技术学院迎新晚会主题,我校计算机科学与技术学院举行迎新晚会
- 报错:TypeError: Image data of dtype object cannot be converted to float
- SendMessgae
- 剑指offer刷题笔记-篇2
- 电子秤称重系统设计,HX711压力传感器,51单片机(Proteus仿真、C程序、原理图、论文等全套资料)
- 【B端·BI系统实战分析】BI系统概述
- nginx隐藏Vary头信息
- 站内搜寻引擎 php mysql_迅搜(xunsearch) - 开源免费中文全文搜索引擎|PHP全文检索|mysql全文检索|站内搜索...