1. 题目:Implement Gouraud Shading or Phong Shading based on hw3
1.1. Goal
You are to write a program to read a set of commands from file and display result on screen.
1.2. Commands
大部分与《数媒笔记整理3》中的命令相同,这里只贴出新的:
- object [filename] R G B Kd Ks N: Load a 3d model file, apply current modeling transform to the object, (R, G, B) is the Material Color of 3D Model, Kd, Ks, N is Constants for Lighting Equation.
- ambient Ka: The ambient light intensity for current 3d scene.
- background R G B: The background Color of window.
- light ID Ip X Y Z: create a point light source at Position(X, Y, Z), Ip is intensity of point light source, ID is an ID number (1~4) of light source, There are at most 4 light sources.
2. 分析
首先,像上次一样读数据文件,还有图形文件,读完图形文件之后,可以取每个面的三个点计算每个面的正向向量之后可以获得每个点的正向向量,方法是点遍历所有面,所处在的面的正向向量加和的平均值;
之后计算每个点的I,按照公式:首先Ka就是第一种光,没有Ia,之后第二种光fatt设置为1,然后其他向量之间的计算应该没有难点;
之后进行上次的那些转换,变到SS空间,用zBuffer那些算法,首先全设为背景色,之后遍历每个点,看是否在一个面内(判断一个点是否在所围成的全部直线的左边或者右边),然后用转换的坐标,计算每个面的
plan function,求出A,B,C,D。
这样遍历屏幕,就会得到每个屏幕点的z值,之后与zBuffer比较,小于,就改zBuffer和cBuffer。
这一点的所在面的某一顶点的I乘以Object R,G,B,之后用drawdot()就可以画出图了。
3. 源码
/* Calculate and get GRM, Mirror Matrix. */
void Observer(float x1, float x2, float x3, float x4, float x5, float x6, float x7, float x8, float x9, float x10) {
H = x8, y = x9, theta = x10;
int i, j;
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
GRM[i][j] = 0;
Mirror[i][j] = 0;
}
}
Mirror[0][0] = -1, Mirror[1][1] = 1, Mirror[2][2] = 1, Mirror[3][3] = 1;
float vt[3], vz[3], v1[3], v2[3], v3[3];
vt[0] = 0, vt[1] = 1, vt[2] = 0;
vz[0] = x4 - x1, vz[1] = x5 - x2, vz[2] = x6 - x3;
float length_of_vz = sqrt(vz[0] * vz[0] + vz[1] * vz[1] + vz[2] * vz[2]);
float length_of_vt = 1;
v3[0] = vz[0] / length_of_vz, v3[1] = vz[1] / length_of_vz, v3[2] = vz[2] / length_of_vz;
float length_of_v3 = 1;
v1[0] = vt[1] * vz[2] - vt[2] * vz[1], v1[1] = vt[2] * vz[0] - vt[0] * vz[1], v1[2] = vt[0] * vz[1] - vt[1] * vz[0];
float length_of_v1 = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
v1[0] = v1[0] / length_of_v1, v1[1] = v1[1] / length_of_v1, v1[2] = v1[2] / length_of_v1;
v2[0] = v3[1] * v1[2] - v3[2] * v1[1], v2[1] = v3[2] * v1[0] - v3[0] * v1[1], v2[2] = v3[0] * v1[1] - v3[1] * v1[0];
float length_of_v2 = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
v2[0] = v2[0] / length_of_v2, v2[1] = v2[1] / length_of_v2, v2[2] = v2[2] / length_of_v2;
GRM[0][0] = v1[0], GRM[0][1] = v1[1], GRM[0][2] = v1[2];
GRM[1][0] = v2[0], GRM[1][1] = v2[1], GRM[1][2] = v2[2];
GRM[2][0] = v3[0], GRM[2][1] = v3[1], GRM[2][2] = v3[2], GRM[3][3] = 1;
Eye_Translate(-x1, -x2, -x3);
Eye_Tilt(-x7);
}
/* 3D rendering pipeline, multiply PM, eye tilt, mirror, GRM, eye translate, translate. Then get the final vertex.*/
void Display() {
int i, j, k;
int l = 0;
float AR = 1;
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
PM[i][j] = 0;
}
}
PM[0][0] = 1;
PM[1][1] = AR;
PM[2][2] = y * tan((theta / 180.0 * 3.14159265 )) / (y - H);
PM[2][3] = H * y * tan((theta / 180.0 * 3.14159265 )) / (H - y);
PM[3][2] = tan((theta / 180.0 * 3.14159265 ));
for (i = 0 ; i < 600 ; i++) {
for (j = 0 ; j < 600 ; j++) {
zBuffer[i][j] = 12353093;
cBuffer[i][j].r = background_r;
cBuffer[i][j].g = background_g;
cBuffer[i][j].b = background_b;
}
}
/* L presents the number of objects. */
for (l = 0 ; l < number_of_read_object ; l++) {
for (i = 0 ; i < store_current_num_vertex[l] ; i++) {
for (j = 0 ; j < store_current_num_face[l] ; j++) {
if (number_of_vertex_in_one_face[l] == 3) {
if ((i == vertex_face[l][j][0]-1) || (i == vertex_face[l][j][1]-1) || (i == vertex_face[l][j][2]-1)) {
average_normal_vector_point[l][i].a += normal_vector_face[l][j].a;
average_normal_vector_point[l][i].b += normal_vector_face[l][j].b;
average_normal_vector_point[l][i].c += normal_vector_face[l][j].c;
counter_of_vertex_vector++;
}
}
else if (number_of_vertex_in_one_face[l] == 4) {
if ((i == vertex_face[l][j][0]-1) || (i == vertex_face[l][j][1]-1) || (i == vertex_face[l][j][2]-1) || (i == vertex_face[l][j][3]-1)) {
average_normal_vector_point[l][i].a += normal_vector_face[l][j].a;
average_normal_vector_point[l][i].b += normal_vector_face[l][j].b;
average_normal_vector_point[l][i].c += normal_vector_face[l][j].c;
counter_of_vertex_vector++;
}
}
}
average_normal_vector_point[l][i].a /= counter_of_vertex_vector;
average_normal_vector_point[l][i].b /= counter_of_vertex_vector;
average_normal_vector_point[l][i].c /= counter_of_vertex_vector;
float Length_Of_N = sqrt(average_normal_vector_point[l][i].a * average_normal_vector_point[l][i].a + average_normal_vector_point[l][i].b * average_normal_vector_point[l][i].b + average_normal_vector_point[l][i].c * average_normal_vector_point[l][i].c);
/* N vector */
average_normal_vector_point[l][i].a /= Length_Of_N;
average_normal_vector_point[l][i].b /= Length_Of_N;
average_normal_vector_point[l][i].c /= Length_Of_N;
counter_of_vertex_vector = 0;
/* L vector */
I_Value[l][i] = Ka;
for (k = 0 ; k < number_of_light ; k++) {
float px, py, pz;
px = vertex_point[l][i][0] - light_vector[k].x;
py = vertex_point[l][i][1] - light_vector[k].y;
pz = vertex_point[l][i][2] - light_vector[k].z;
float Length_Of_L = sqrt(px*px + py*py + pz*pz);
px /= Length_Of_L, py /= Length_Of_L, pz /= Length_Of_L;
/* N*L */
float Diffuse_Value = ol[l].Kd * light_vector[k].ip * (px * average_normal_vector_point[l][i].a + py * average_normal_vector_point[l][i].b + pz * average_normal_vector_point[l][i].c);
if (Diffuse_Value < 0) {
Diffuse_Value = 0;
}
I_Value[l][i] += Diffuse_Value;
}
for (k = 0 ; k < number_of_light ; k++) {
float a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0, m = 0;
/* L vector */
a = light_vector[k].x - vertex_point[l][i][0];
b = light_vector[k].y - vertex_point[l][i][1];
c = light_vector[k].z - vertex_point[l][i][2];
/* V vector */
d = Px - vertex_point[l][i][0];
e = Py - vertex_point[l][i][1];
f = Pz - vertex_point[l][i][2];
/* H vector */
g = a + d, h = b + e, m = c + f;
float Length_Of_H = sqrt(g*g + h*h + m*m);
g /= Length_Of_H, h /= Length_Of_H, m /= Length_Of_H;
double temp = g * average_normal_vector_point[l][i].a + h * average_normal_vector_point[l][i].b + m * average_normal_vector_point[l][i].c;
if (temp < 0) {
temp = 0;
}
double Specular_Value = ol[l].Ks * light_vector[k].ip * pow(temp, ol[l].N);
I_Value[l][i] += Specular_Value;
}
if (IMAX <= I_Value[l][i]) {
IMAX = I_Value[l][i];
}
}
cout << "WTF!" << endl << endl;
if (IMAX <= 1) {
IMAX = 1;
}
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
Current_Matrix_Copy[i][j] = 0;
}
}
/* PM * Tilt */
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
for (k = 0 ; k < 4 ; k++) {
Current_Matrix_Copy[i][j] += PM[i][k] * Eye_Tilt_Matrix[k][j];
}
}
}
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
Current_Matrix[l][i][j] = Current_Matrix_Copy[i][j];
Current_Matrix_Copy[i][j] = 0;
}
}
/* Mirror*/
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
for (k = 0 ; k < 4 ; k++) {
Current_Matrix_Copy[i][j] += Current_Matrix[l][i][k] * Mirror[k][j];
}
}
}
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
Current_Matrix[l][i][j] = Current_Matrix_Copy[i][j];
Current_Matrix_Copy[i][j] = 0;
}
}
/* *GRM */
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
for (k = 0 ; k < 4 ; k++) {
Current_Matrix_Copy[i][j] += Current_Matrix[l][i][k] * GRM[k][j];
}
}
}
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
Current_Matrix[l][i][j] = Current_Matrix_Copy[i][j];
Current_Matrix_Copy[i][j] = 0;
}
}
/* *Eye_Translate*/
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
for (k = 0 ; k < 4 ; k++) {
Current_Matrix_Copy[i][j] += Current_Matrix[l][i][k] * Eye_Translate_Matrix[k][j];
}
}
}
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
Current_Matrix[l][i][j] = Current_Matrix_Copy[i][j];
Current_Matrix_Copy[i][j] = 0;
}
}
/* *Translate_Matrix */
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
for (k = 0 ; k < 4 ; k++) {
Current_Matrix_Copy[i][j] += Current_Matrix[l][i][k] * Translate_Matrix[l][k][j];
}
}
}
for (i = 0 ; i < 4 ; i++) {
for (j = 0 ; j < 4 ; j++) {
Current_Matrix[l][i][j] = Current_Matrix_Copy[i][j];
Current_Matrix_Copy[i][j] = 0;
}
}
for (i = 0 ; i < store_current_num_vertex[l] ; i++) {
for (j = 0 ; j < 4 ; j++) {
float temp = 0;
for (k = 0 ; k < 4 ; k++) {
temp += Current_Matrix[l][j][k] * vertex_point[l][i][k];
}
result_vertex_point[i][j] = temp;
}
}
for (i = 0 ; i < store_current_num_vertex[l] ; i++) {
float divide = result_vertex_point[i][3];
result_vertex_point[i][0] = result_vertex_point[i][0] / divide;
result_vertex_point[i][1] = result_vertex_point[i][1] / divide;
result_vertex_point[i][2] = result_vertex_point[i][2] / divide;
result_vertex_point[i][3] = result_vertex_point[i][3] / divide;
result_vertex_point[i][0] *= (Vr - Vl) / 2;
result_vertex_point[i][0] += (Vr - Vl) / 2;
result_vertex_point[i][1] *= (Vt - Vb) / 2;
result_vertex_point[i][1] += (Vt - Vb) / 2;
}
for (i = 0 ; i < store_current_num_face[l] ; i++) {
float x1, x2, x3, y1, y2, y3, z1, z2, z3, x4, y4, z4, z;
float a[3], b[3], c[3];
x1 = result_vertex_point[vertex_face[l][i][0]-1][0], y1 = result_vertex_point[vertex_face[l][i][0]-1][1], z1 = result_vertex_point[vertex_face[l][i][0]-1][2];
x2 = result_vertex_point[vertex_face[l][i][1]-1][0], y2 = result_vertex_point[vertex_face[l][i][1]-1][1], z2 = result_vertex_point[vertex_face[l][i][1]-1][2];
x3 = result_vertex_point[vertex_face[l][i][2]-1][0], y3 = result_vertex_point[vertex_face[l][i][2]-1][1], z3 = result_vertex_point[vertex_face[l][i][2]-1][2];
a[0] = x2 - x1, a[1] = y2 - y1, a[2] = z2 - z1;
b[0] = x3 - x2, b[1] = y3 - y2, b[2] = z3 - z2;
c[0] = a[1]*b[2] - a[2]*b[1], c[1] = a[2]*b[0] - a[0]*b[2], c[2] = a[0]*b[1] - a[1]*b[0];
pe[i].A = c[0], pe[i].B = c[1], pe[i].C = c[2], pe[i].D = -(c[0] * x1 + c[1] * y1 + c[2] * z1);
for (j = 0 ; j < 600 ; j++) {
for (k = 0 ; k < 600 ; k++) {
if (number_of_vertex_in_one_face[l] == 3) {
if ((((j - x1)*(y2 - y1) - (x2 - x1)*(k - y1)) <= 0) && (((j - x2)*(y3 - y2) - (x3 - x2)*(k - y2)) <= 0) && (((j - x3)*(y1 - y3) - (x1 - x3)*(k - y3)) <= 0) || (((j - x1)*(y2 - y1) - (x2 - x1)*(k - y1)) >= 0) && (((j - x2)*(y3 - y2) - (x3 - x2)*(k - y2)) >= 0) && (((j - x3)*(y1 - y3) - (x1 - x3)*(k - y3)) >= 0)) {
z = -(pe[i].A*j + pe[i].B*k + pe[i].D) / pe[i].C;
if (z < zBuffer[j][k]) {
zBuffer[j][k] = z;
cBuffer[j][k].r = ol[l].r*(I_Value[l][vertex_face[l][i][0]-1] + I_Value[l][vertex_face[l][i][1]-1] + I_Value[l][vertex_face[l][i][2]-1])/(3*IMAX);
cBuffer[j][k].g = ol[l].g;
cBuffer[j][k].b = ol[l].b;
}
}
}
else if (number_of_vertex_in_one_face[l] == 4) {
x4 = result_vertex_point[vertex_face[l][i][3]-1][0], y4 = result_vertex_point[vertex_face[l][i][3]-1][1], z4 = result_vertex_point[vertex_face[l][i][3]-1][2];
if ((((j - x1)*(y2 - y1) - (x2 - x1)*(k - y1)) <= 0) && (((j - x2)*(y3 - y2) - (x3 - x2)*(k - y2)) <= 0) && (((j - x3)*(y4 - y3) - (x4 - x3)*(k - y3)) <= 0) && (((j - x4)*(y1 - y4) - (x1 - x4)*(k - y4)) <= 0) || (((j - x1)*(y2 - y1) - (x2 - x1)*(k - y1)) >= 0) && (((j - x2)*(y3 - y2) - (x3 - x2)*(k - y2)) >= 0) && (((j - x3)*(y4 - y3) - (x4 - x3)*(k - y3)) >= 0) && (((j - x4)*(y1 - y4) - (x1 - x4)*(k - y4)) >= 0)) {
z = -(pe[i].A*j + pe[i].B*k + pe[i].D) / pe[i].C;
if (z < zBuffer[j][k]) {
cBuffer[j][k].r = ol[l].r*(I_Value[l][vertex_face[l][i][0]-1] + I_Value[l][vertex_face[l][i][1]-1] + I_Value[l][vertex_face[l][i][2]-1] + I_Value[l][vertex_face[l][i][3]-1])/(4*IMAX);
cBuffer[j][k].g = ol[l].g;
cBuffer[j][k].b = ol[l].b;
zBuffer[j][k] = z;
}
}
}
}
}
}
for (i = 0 ; i < 600 ; i++) {
for (j = 0 ; j < 600 ; j++) {
drawDot(i, j, cBuffer[i][j].r, cBuffer[i][j].g, cBuffer[i][j].b);
}
}
glFlush();
}
}