素材中有四个.bmp格式的纹理文件和一个.txt的模型参数文件
文件格式说明:
纹理文件数量
纹理文件1(字符串)//.bmp
纹理文件2(字符串)
纹理文件3(字符串)
.
.
.
材质数量
ambient(float[4])
diffuse(float[4])
specular(float[4]])
emission(float[4])
shininess(float[1])
纹理文件索引(int[1])//0表示无
ambient(float[4])
diffuse(float[4])
specular(float[4]])
emission(float[4])
shininess(float[1])
纹理文件索引(int[1])//0表示无
ambient(float[4])
diffuse(float[4])
specular(float[4]])
emission(float[4])
shininess(float[1])
纹理文件索引(int[1])//0表示无
.
.
顶点数量
v1(float[3])
v2(float[3])
v3(float[3])
.
.
贴图坐标数量
t1(float[2])
t2(float[2])
t3(float[2])
.
.
法线数量
n1(float[3])
n2(float[3])
n3(float[3])
.
.
模型分组数量
缩放系数(float[3])
submodel1 三角形数量
材质索引(int)//0表示无
vi1 ti1 ni1 vi2 ti2 ni2 vi3 ti3 ni3 (unsigned int[9])
vi1 ti1 ni1 vi2 ti2 ni2 vi3 ti3 ni3 (unsigned int[9])
vi1 ti1 ni1 vi2 ti2 ni2 vi3 ti3 ni3 (unsigned int[9])
.
.
submodel2 三角形数量
材质索引(int)//0表示无
vi1 ti1 ni1 vi2 ti2 ni2 vi3 ti3 ni3 (unsigned int[9])
vi1 ti1 ni1 vi2 ti2 ni2 vi3 ti3 ni3 (unsigned int[9])
vi1 ti1 ni1 vi2 ti2 ni2 vi3 ti3 ni3 (unsigned int[9])
.
.
.
人物分为四个子模型,分别有不同的顶点坐标,纹理文件,材质。
纹理文件名用来打开纹理文件
材质列表是用来设置每个子模型的材质,opengl中设置材质的函数将会用到这些参数,下面会详细说明
顶点列表给出了需要使用的所有顶点,这里不分子模型,不直接绘出(当然直接画出来也没关系,只是没有必要),而是在连线时引用这些参数
贴图坐标给出了二维的纹理文件到三维的人物模型表面的映射,每个三维顶点将会对应一个二维坐标,具体的对应关系会在文件的其他部分给出
法线给出了光照的参数,光照在生成时会依据三维物体表面的法线属性,一个三位顶点对应一个法线,具体的对应关系 会在文件的其他部分给出
每个子模型由一个三角形阵列表示,每个三角形由九个参数给出,三个vi表示三个顶点的索引,三个ti表示三个贴图坐标的索引,三个ni表示三个法线向量的索引。(索引为上面读入的数组,注意这里的索引是从1开始的)
人物绘制
模型是由多个三角形面片组合在表面形成的,每个三角形由三个顶点坐标指定,并且每个顶点有对应的法线参数,对应的纹理坐标,在OpenGL中指定后程序会自动的使用这些参数绘制。
将人物的绘制分为三步:画出线框图-->添加界面交互-->添加纹理
这里先画出线框图是为了先看到效果,实际在一步绘制时用的是三角形绘制而不是线,但是三角形绘制的结果是一片白,线框可以看到细节
界面交互是用来指定三维变换,三维观察,投影等参数
绘制线框图
这里只是用到了txt中的顶点坐标和三角形索引中的ti值
main函数中进行初始化:
int main(int argc, char *argv[]) //主函数: 参数数量&参数值
{
glutInit(&argc, argv); //初始化glut: 接收主函数的参数
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //显示模式:颜色&缓冲
glutInitWindowPosition(0, 0); //窗口相对屏幕位置
glutInitWindowSize(720, 720); //窗口大小
glutCreateWindow("luweiqi"); //创建窗口: 标题
glutDisplayFunc(&display); //指定显示函数,这个函数由自己实现
gluLookAt(0.1, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); //这个是三维观察函数,这里不详细说明,如果不指定这些参数人物的角度会很奇怪
glutMainLoop(); //主循环,程序执行到这里将循环调用指定的display函数
return 0;
}
display函数进行绘制:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT); //当前背景色填充窗口
//画线
glBegin(GL_LINE_LOOP); //参数指定绘制类型,将会根据类型确定每次取几个点绘制
for (int i = 0; i < allTriangleNum; i++)
{
glVertex3f(vertex[triangle[i]