數媒筆記整理4

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();
    }
}

4. 結果

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章