绘制简单小屋的真实感图形
设计内容
绘制真实感房屋简图
设计要求
1. 绘制任意视点下真实感房屋简图 2. 房屋顶点空间坐标如下图所示:
3. 房屋表面的光照参数
表:物体表面的光学参数
环境光反射率
光源漫反射率
光源镜面反射 率
高光指 数
颜 色
𝐾
𝐾
𝐾
𝐾
𝐾
𝐾
𝐾
𝐾
𝐾
屋 顶
前
0.05
0.05
0.3
0.2
0.2
0.7
0.8
0.8
0.8
3
蓝
后
0.3
0.3
0.05
0.7
0.7
0.2
0.8
0.8
0.8
3
黄
墙 壁
左
0.05
0.3
0.05
0.2
0.5
0.2
0.8
0.8
0.8
3
绿
右
0.3
0.05
0.05
0.5
0.2
0.2
0.8
0.8
0.8
3
红
前
0.3
0.05
0.3
0.5
0.2
0.5
0.8
0.8
0.8
3
品 红
后
0.05
0.3
0.3
0.2
0.5
0.5
0.8
0.8
0.8
3
青
4. 参考思路
a) 创建菜单项;
b) 创建对话框输入光源坐标和视点坐标;
c) 使用坐标变换的相关公式,将视点变换到 Z 轴上,房屋每个面的多边形顶点依
此进行变换;
d) 计算各个表面的法线;
e) 根据表面法线确定“前向面”和“后向面”;
f) 准备对视点位置可见的“前向面”进行多边形填充,计算每个填充点的坐标;
g) 根据改良深度缓存器算法确定当前点是否需要绘制;
h) 若需要绘制,根据简单光照明模型确定填充点的颜色;
Phong 光照明模型:物体表面上任意一点的反射光强等于环境光反射光强、 理 想漫反射光强和镜面反射光强之和。
公式:
I I I I I K I K LNI K RVn R eR dR sR aR aR pR dR pR sR
I I I I I K I K LNI K RVn G eG dG sG aG aG pG dG pG sG
I I I I I K I K LNI K RVn B eB dB sB aB aB pB dB pB sB
5. 实现要求
a) 编程语言:C 或 C++,MFC 框架(不要使用 OpenGL 和 DirectX 等)
b) 程序输入:
1) 视点三维坐标xv,yv,zv
2) 点光源三维坐标xo,yo,zo
c) 程序输出:满足输入参数的真实感图形输出
提交内容
1. 源程序(VS2010) 实现课程设计程序的全部源代码,要求可以编译生成可执行文件。
2. 文档 文档记录具有代表性的结果展示,包括输入参数值的界面、对应的运行结果、收获 总结。
提交文件格式
提交内容采用 RAR 压缩文件格式。压缩文件内包含“提交内容”中的所有内容,压缩 包文件名为:XXXX_09.RAR,其中 XXXX 为作者学号。
提交方式
提交地点:云班课上机班。 提交截止时间:2020 年 6 月 26 日 24 时。
特别提示
1. 课程设计内容尽量提前完成,提早提交,以免由于网络故障造成提交方面的问题。 课程不接受其它方式的提交。
2. 课程设计鼓励同学间进行讨论,但实现内容请独立完成,如发现抄袭等违规现象, 以零分计算。
附录:绘制真实感房屋简图参考——绘制立方体
一、建项目
1) 新建“MFC 应用程序”项目,选择项目存储路径,并设置项目名称 17000001_09。 2) 应用程序类型,选择“单个文档”。
二、添加菜单
1) 打开项目的资源视图,为项目添加“设置”菜单。
2) 在“设置”子菜单下,添加“绘制房屋”菜单项。根据菜单项的意义设置 ID:
ID_DRAWHOUSE。
3) 为菜单项“绘制房屋”添加相应的响应函数。
操作方法:在“绘制房屋”菜单项上右键,选择“添加事件处理程序”。
4) 设置响应函数的函数名,以及所属的类。如下图所示:
5) 此时,在 view 类内,已经添加了此菜单的响应函数。 程序运行后,单击“绘制房屋”菜单项触发的功能,在此函数内实现。
三、添加新对话框
1) 打开“资源视图”,在“Dialog”上右键,选择“插入 Dialog”。
2) 选中新插入的对话框,修改“属性窗口”中的“Caption”属性,设置对话框的
标题:绘制房屋。
3) 在对话框中,添加控件,设置界面如下:
4) 双击对话框的空白位置,为对话框设置类名“SetPositionDlg”。
5) 返回“资源视图”,为对话框中的控件添加关联变量。
各控件的关联变量如下表所示。
编辑框的关联变量
灯源位置
x
int m_lightX;
y
int m_lightY;
z
int m_lightZ;
视点位置
x
int m_viewX;
y
int m_viewY;
z
int m_viewZ;
至此,新增对话框内的所有操作完毕。
四、颜色类 MyRGB
由于需要在房子上绘制不同的颜色,所以建立自己的颜色类 MyRGB,用来记录 每个点的 RGB 颜色值。此类很简单,只包含有参和无参的构造函数。 如下所示:
五、三维坐标点类 Point3D
为了方便绘制三维物体中的点,建立类 Point3D,主要包括每个点的坐标和颜 色。如下所示:
六、矢量类 MyVector
画房子、填充颜色、计算光照模型的过程中,会用到很多数学中的矢量运算, 因此建立自己的矢量类 MyVector。为其添加需要的成员函数,如下所示:
七、表面类 Surface
房子是由很多面组成的,为了记录每个面的顶点信息、法向量、光照参数等信 息,建立表面类 Surface。如下所示:
八、立方体类 Cube
为项目添加立方体类 Cube,用来存储绘制的立方体信息,包括面的信息和顶点 信息。如下所示:
依据要求绘制的物体,自行修改顶
点个数和面的个数。
注意:显示立方体时,后续需要根据平面的法向量,判断这个平面是否填充、 显示。可以通过平面中两个向量的叉乘运算(见 MyVector 类成员函数),得 到平面的法向量。而进行叉乘运算的两个向量,分别由平面中第 0、1 个点和 第 0、2 个点组成。为了使得到的法向量向外,平面中顶点的位置顺序必须满 足右手法则。
九、坐标转换类 Transform3D
为了将立方体显示在二维屏幕中,需要对三维坐标点进行转换,因此添加三维 坐标转换类 Transform3D。如下所示:
十、完善 view 类
1) 有了前面的各种辅助类,回到 view 类,准备绘制立方体。为了绘制立方体,为 view 类添加如下成员属性:
Cube cube;//要绘制的立方体
Transform3D tran;//坐标转换 //深度缓冲器的记录深度,决定当前点是否需要绘制
double depth[801][801];//水平垂直范围[-400,400],垂直范围[-400, 400]
2) 在 view 类的 cpp 文件内引入 SetPositionDlg 类的头文件,为产生相应的对话框 做准备。
3) 为记录用户输入的光源和视点位置,继续在 view 类的头文件内添加如下成员: Point3D m_viewPoint; //视点位置
Point3D m_lightPos; //光源位置
int flag;//是否绘制
在 view 类的构造函数内,将 flag 初始化为 0。
4) 进入前面“绘制房屋”菜单项的响应函数 OnDrawhouse。首先,在函数内生成 对话框类 SetPositionDlg 的具体对象,并显示该对话框。当对话框内的数据填入 完毕后,点击“确定”或“取消”按钮,关闭对话框,回到此函数。通过 DoModal() 函数的返回值,可以判断用户关闭对话框时,单击的是“确定”按钮,还是“取 消”按钮。若单击的是“确定”按钮,则获取用户输入的数据。并根据视点位 置,对立方体的顶点坐标进行转换,使屏幕中显示的图形,与视点看到的图形 一致。
OnDrawhouse 函数代码如下:
其中,initDepth()将每个像素点的深度,初始化为很小的值。
5) 根据视点坐标,计算转换角度的函数如下:
点的数量根据实际情况,自行修改。
默认观测视点在地面上方,所以,上面根据视点位置,计算转换角度的方法, 只是针对视点 y 值大于 0 时的情况。如果测试 y<0 的情况,需要进一步完善该 函数。 6) 进入到 view 类的 OnDraw 函数,设置坐标系方向和原点位置。代码如下: 使用前面建好的类,在函数 DrawObject 中绘制立方体。此函数由同学补充。 参考代码框架如下: 提示:如何判断两个向量的方向是否一致?可以计算两个向量间的夹角,夹角 小于 90 度,则方向一致。利用向量点乘运算可以得到向量的夹角。 7) 在填充多边形函数 fillPolygon 内,设置了要填充多边形的顶点信息。然后,使 用前面作业中填充多边形的功能,并对此功能进行完善,加入深度缓冲器、光 照模型。在构造函数中,传入了视点和光源位置。 代码如下: 点的数量根据实际情况,自行修改。 十一、填充多边形类 FillPolygon 在前面作业的基础上,完善填充多边形类 FillPolygon,加入深度缓冲器和 Phong 光照模型。 面的数量根据实际情况,自行修改。 1) View 类内,已经对当前表面的光照系数进行了设置,为计算光照后的颜色。 代码如下: 2) 现在的任务是填充三维物体的平面,需要根据当前填充点的 x,y 坐标,计算其 z 坐标。 有了当前点的(x,y,z)值,才能计算其与光源和视点构成向量的夹角。从而 计算 Phong 光照模型中,此点的颜色。 提示:三维平面方程为 Ax+By+Cz+D=0,使用平面中的顶点坐标,可以计算出 系数 A、B、C、D 的值。有了平面方程系数,就可以通过当前填充点 x,y 的值, 计算出 z 值。 那么根据顶点坐标,如何求三维平面方程?方程中的系数 A、B、C,就是该平 面的一个法向量的坐标。所以,可以选取平面中的三个顶点坐标,形成两个向 量,做叉乘,得到该平面的法向量。将法向量的坐标作为平面方程中的系数 A、 B、C,然后,任意带入一个顶点的坐标(x,y,z)值,求系数 D。 3) 当 z 值大于深度缓冲器中此位置的深度时,用 z 值更新此位置的深度,并显示 该点。 4) 显示该点前,需要采用 Phong 光照模型计算当前点的最终颜色。 参考代码框架如下: 至此,整个项目流程结束,下面是运行效果。 十二、测试 根据程序中的参数,预计立方体的位置和颜色,如下图所示。 1) 光源位置(290,140,10),视点位置(300,300,300)。 对话框中输入的数据,如下所示: 运行结果: 可以看出,观测到了物体的前、右、上三个面,与预测观测到的表面一致,同 时由于加入了光照模型,可以在黄色、红色平面内观察到明暗过度,越靠近光 源的位置,越亮。 2) 光源位置(-40,130,90),视点位置(-50,180,-50)。 对话框中输入的数据,如下所示: 运行结果: 此时,我们调整光源位置,同时把视点转到了物体的后面,观测到了物体的后、 左、上三个面,同时由于加入了光照模型,可以在黄色、绿色平面内观察到明 暗过度,越靠近光源的位置,越亮。 前面两次测试,与预测结果一致,运行正确。 十三、补充说明 本次作业要求绘制房子,本参考文档中的例子是绘制立方体。 同学们需要在参考文档的基础上,将立方体的“上面”改为“双坡式屋顶”。 此时,要记住修改参考案例中涉及到的顶点个数、平面个数,并合理设置每个 平面内顶点的顺序。 自己可以修改程序中的光照模型参数,测试更好的效果。 再次提醒: 1、 提交的文档中,只包含运行结果和这学期学习本门课程的收获总结即可(若 没话说,可以不写)。 2、 如果提交的程序不能运行或没有结果,0 分。 3、 按照流程,确保前面的步骤没问题,再做后面的,做的过程中,多做备份。 档次 满分 30 分 差 只绘制出房屋的线条 10 分 中 填充房屋表面,遮挡关系正确 20 分 优 在遮挡关系正确的基础上,加入光照模型 30 分