數媒筆記整理3

1. 題目:Implement an OpenGL-like 3D Rendering Pipeline

這裏寫圖片描述

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

  • object: filer name, load a 3D model file, apply current modeling transform to the object.
  • translate X Y: do a translation by (X, Y), multiply the current matrix by a translation matrix.
  • rotate X Y: do a rotation by R degree, multiply the current matrix by a rotation matrix.
  • scale X Y: do a scaling by (X, Y), multiply the current matrix by a scaling matrix.
  • observer: PX PY PZ CX CY CZ Tilt zNear zFar hFOV. (PX, PY, PX): eye’s position; (CX, CY, CZ): COI(center of interest); Tilt: tilt degree of camera; zNear: distance of near clipping plane; zFar: distance of far clipping plane; hFOV: half Field of View.
    這裏寫圖片描述

1.3. Examples

# Sample1
# load a teapot
object teapot.asc
# set viewport
viewport 0 800 0 600
# Eye (0,0,10)  Look at (0,0,0)
observer 0 0 10  0 0 0  0 1 100 45
display
end

這裏寫圖片描述

# Sample2
# modeling trasnform
translate 3 0 0
# load a teapot
object teapot.asc
# set viewport
viewport 0 800 0 600
# Eye at(5,5,5)  Look at (0,0,0)
observer 5 5 5  0 0 0  0 1 100 45
display
end

這裏寫圖片描述

2. 源碼

translate,scale以及rotate矩陣寫法已經在上一次的文章中註明,這一次主要貼一些新的矩陣:

/* Calculate and get the eye tanslate matrix. */
void Eye_Translate(float a,  float b,  float c)  {
    float translation_matrix[4][4];
    float Eye_Translate_Matrix_Copy[4][4];
    int i,  j,  k;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            translation_matrix[i][j] = 0;
            Eye_Translate_Matrix_Copy[i][j] = Eye_Translate_Matrix[i][j];
            Eye_Translate_Matrix[i][j] = 0;
        }
    }
    translation_matrix[0][0] = 1;
    translation_matrix[1][1] = 1;
    translation_matrix[2][2] = 1;
    translation_matrix[3][3] = 1;
    translation_matrix[0][3] = a;
    translation_matrix[1][3] = b;
    translation_matrix[2][3] = c;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            for (k = 0 ; k < 4 ; k++)  {
                Eye_Translate_Matrix[i][j] += translation_matrix[i][k] * Eye_Translate_Matrix_Copy[k][j];
            }
        }
    }

}
/* Calculate and get the eye tilt matrix. */
void Eye_Tilt(float c)  {
    float rotate_matrix[4][4];
    float Eye_Tilt_Matrix_Copy[4][4];
    int i,  j,  k;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            rotate_matrix[i][j] = 0;
            Eye_Tilt_Matrix_Copy[i][j] = Eye_Tilt_Matrix[i][j];
            Eye_Tilt_Matrix[i][j] = 0;
        }
    }
    rotate_matrix[0][0] = cos((c / 180.0 * 3.14159265 ));
    rotate_matrix[0][1] = -sin((c / 180.0 * 3.14159265 ));
    rotate_matrix[1][0] = sin((c / 180.0 * 3.14159265 ));
    rotate_matrix[1][1] = cos((c / 180.0 * 3.14159265 ));
    rotate_matrix[2][2] = 1;
    rotate_matrix[3][3] = 1;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            for (k = 0 ; k < 4 ; k++)  {
                Eye_Tilt_Matrix[i][j] += rotate_matrix[i][k] * Eye_Tilt_Matrix_Copy[k][j];
            }
        }
    }
}
/* 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;  
    cout << "GRM Matrix:" << endl;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            printf("%.2f ",  GRM[i][j]);
        }
        cout << endl;
    }
    cout << "---------------------------------------------------------" <<endl << endl;
    cout << "Eye Mirror Matrix:" << endl;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            printf("%.2f ",  Mirror[i][j]);
        }
        cout << endl;
    }
    cout << "---------------------------------------------------------" <<endl << endl;
    Eye_Translate(-x1,  -x2,  -x3);
    Eye_Tilt(-x7);
    cout << "Eye Tilt Matrix: "<< endl;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            printf("%.2f ",  Eye_Tilt_Matrix[i][j]);
        }

        cout << endl;
    }
    cout << "---------------------------------------------------------" <<endl << endl;
    cout << "Eye Translate Matrix: "<< endl;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            printf("%.2f ",  Eye_Translate_Matrix[i][j]);
        }

        cout << endl;
    }
    cout << "---------------------------------------------------------" <<endl << endl;
}
/* 3D rendering pipeline, multiply PM, eye tilt, mirror, GRM, eye translate, translate. Then get the final vertex.*/
void Display()  {
    int i,  j,  k;
    float AR = w / h;
    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 ));
    cout << "Projection Matrix: " << endl;
    for (i = 0 ; i < 4 ; i++)  {
        for (j = 0 ; j < 4 ; j++)  {
            printf("%.2f ",  PM[i][j]);
        }
        cout << endl;
    }
    cout << "---------------------------------------------------------" <<endl << endl;
    int l = 0;
    for (l = 0 ; l < number_of_translate_matrix ; l++)  {
        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 < cube.num_vertex ; 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 < cube.num_vertex ; 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 (j = 0 ; j < cube.num_face ; j++)  {
            if  (number_of_vertex_in_one_face == 3)  {
                drawLine(result_vertex_point[cube.face[j][0] - 1][0],  result_vertex_point[cube.face[j][1] - 1][0],  result_vertex_point[cube.face[j][0] - 1][1],  result_vertex_point[cube.face[j][1] - 1][1],  2);
                drawLine(result_vertex_point[cube.face[j][1] - 1][0],  result_vertex_point[cube.face[j][2] - 1][0],  result_vertex_point[cube.face[j][1] - 1][1],  result_vertex_point[cube.face[j][2] - 1][1],  2);
                drawLine(result_vertex_point[cube.face[j][2] - 1][0],  result_vertex_point[cube.face[j][0] - 1][0],  result_vertex_point[cube.face[j][2] - 1][1],  result_vertex_point[cube.face[j][0] - 1][1],  2);
            }
            else if  (number_of_vertex_in_one_face == 4)  {
                drawLine(result_vertex_point[cube.face[j][0] - 1][0],  result_vertex_point[cube.face[j][1] - 1][0],  result_vertex_point[cube.face[j][0] - 1][1],  result_vertex_point[cube.face[j][1] - 1][1],  2);
                drawLine(result_vertex_point[cube.face[j][1] - 1][0],  result_vertex_point[cube.face[j][2] - 1][0],  result_vertex_point[cube.face[j][1] - 1][1],  result_vertex_point[cube.face[j][2] - 1][1],  2);
                drawLine(result_vertex_point[cube.face[j][2] - 1][0],  result_vertex_point[cube.face[j][3] - 1][0],  result_vertex_point[cube.face[j][2] - 1][1],  result_vertex_point[cube.face[j][3] - 1][1],  2);
                drawLine(result_vertex_point[cube.face[j][3] - 1][0],  result_vertex_point[cube.face[j][0] - 1][0],  result_vertex_point[cube.face[j][3] - 1][1],  result_vertex_point[cube.face[j][0] - 1][1],  2);
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章