#include<iostream>
#include<GL/glut.h>
#include<math.h>
const double PI = 3.14159265;
//変形させる対象
double vertices[][3]={//頂点の座標
{0.0, 0.5, 0.0},
{0.0, 0.0, 0.0},
{0.5, 0.0, 0.0},
{0.5, 0.5, 0.0},
};
const int nv = 4;//頂点数
//変換行列
double transformation_mat[4][4]={
{0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0}
};
//r行、c列の配列の表示(テスト用)
void printMat(double mat[4][4], int r, int c){
for(int i = 0; i < r; i++){
for(int j=0; j < c; j++)
std::cout << " "<<mat[i][j];
std::cout << std::endl;
}
}
//引数を強制的に単位行列にする
void setIdentity44(double mat[4][4]){
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++)
if(i == j) mat[i][j] = 1.0;
else mat[i][j] = 0.0;
}
}
void copy44(double out_mat[4][4], const double in_mat[4][4]){
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
out_mat[i][j] = in_mat[i][j];
}
}
}
//4*4行列の掛け算
void makeTransformationMatrix(double out_mat[4][4], const double in_mat1[4][4], const double in_mat2[4][4]){
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
out_mat[i][j] =
in_mat1[i][0] * in_mat2[0][j] +
in_mat1[i][1] * in_mat2[1][j] +
in_mat1[i][2] * in_mat2[2][j] +
in_mat1[i][3] * in_mat2[3][j];
}
}
}
//4*4行列の掛け算。out_matとin_mat1,in_mat2は同じでも大丈夫
void multiply44by44(double out_mat[4][4], const double in_mat1[4][4], const double in_mat2[4][4]){
double temp_mat1[4][4]={
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0}
};
copy44(temp_mat1, in_mat1);
double temp_mat2[4][4]={
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0}
};
copy44(temp_mat2, in_mat2);
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
out_mat[i][j] =
temp_mat1[i][0] * temp_mat2[0][j] +
temp_mat1[i][1] * temp_mat2[1][j] +
temp_mat1[i][2] * temp_mat2[2][j] +
temp_mat1[i][3] * temp_mat2[3][j];
}
}
}
//平行移動行列の生成。mat:結果、tx:x方向の移動量、ty:y方向の移動量
void makeTranslationMatrix(double mat[4][4], const double tx, const double ty, const double tz){
mat[0][0] = 1.0; mat[0][1] = 0.0; mat[0][2] = 0.0; mat[0][3] = tx;
mat[1][0] = 0.0; mat[1][1] = 1.0; mat[1][2] = 0.0; mat[1][3] = ty;
mat[2][0] = 0.0; mat[2][1] = 0.0; mat[2][2] = 1.0; mat[2][3] = tz;
mat[3][0] = 0.0; mat[3][1] = 0.0; mat[3][2] = 0.0; mat[3][3] = 1.0;
}
void setTranslation(const double tx, const double ty, const double tz){
double translation_mat[4][4]={
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0}
};
makeTranslationMatrix(translation_mat, tx, ty, tz);
multiply44by44(transformation_mat, translation_mat, transformation_mat);
}
//X軸周りの回転行列の生成。mat:結果、r:回転角
void makeRotationXMatrix(double mat[4][4], const double r){
mat[0][0] = 1; mat[0][1] = 0; mat[0][2] = 0; mat[0][3] = 0;
mat[1][0] = 0; mat[1][1] = cos(r); mat[1][2] = -1*sin(r); mat[1][3] = 0;
mat[2][0] = 0; mat[2][1] = sin(r); mat[2][2] = cos(r); mat[2][3] = 0;
mat[3][0] = 0; mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1;
}
void setRotationX(const double r){
double rotation_mat[4][4]={
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0}
};
makeRotationXMatrix(rotation_mat, r);
multiply44by44(transformation_mat, rotation_mat, transformation_mat);
}
//Y軸周りの回転行列の生成。mat:結果、r:回転角
void makeRotationYMatrix(double mat[4][4], const double r){
mat[0][0] = cos(r); mat[0][1] = 0; mat[0][2] = sin(r); mat[0][3] = 0;
mat[1][0] = 0; mat[1][1] = 1; mat[1][2] = 0; mat[1][3] = 0;
mat[2][0] = -1*sin(r);mat[2][1] = 0; mat[2][2] = cos(r); mat[2][3] = 0;
mat[3][0] = 0; mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1;
}
void setRotationY(const double r){
double rotation_mat[4][4]={
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 0.0, 0.0}
};
makeRotationYMatrix(rotation_mat, r);
multiply44by44(transformation_mat, rotation_mat, transformation_mat);
}
//4*4行列Aと4(実際は3)*1行列vの掛け算Avの計算。vertex:v(破壊されて結果が入る)、mat:A
void transform(double vertex[], double mat[4][4]){
double temp_x = vertex[0];
double temp_y = vertex[1];
double temp_z = vertex[2];
printMat(mat,4,4);
for(int i=0; i<3; i++){
vertex[i] = temp_x*mat[i][0] + temp_y*mat[i][1] + temp_z*mat[i][2] + 1.0 * mat[i][3];
}
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
//座標軸の表示
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2d(-1.0, 0.0);
glVertex2d(1.0, 0.0);
glVertex2d(0.0, -1.0);
glVertex2d(0.0, 1.0);
glEnd();
//座標変換
setIdentity44(transformation_mat);
// setRotationX(0);
setRotationY(PI*1.3);
// setTranslation(0.0,0.0, 1.0);
// setTranslation(0.0,-1.0);
for(int i = 0; i < nv; i++)
transform(vertices[i], transformation_mat);
double s = 1.0;
double d = 1.9;
glColor3f(0.0, 1.0, 0.0);
//表示
#if 1
//透視投影変換
glBegin(GL_LINE_LOOP);
for(int i = 0; i < nv; i++){
glVertex2d(s / (d - vertices[i][2]) * vertices[i][0], s / (d - vertices[i][2]) * vertices[i][1]);
}
glEnd();
#else
//正射影
glBegin(GL_LINE_LOOP);
for(int i = 0; i < nv; i++)
glVertex2d(vertices[i][0]/vertices[i][2], vertices[i][1]/vertices[i][2]);
glEnd();
#endif
glFlush();
}
int main(int argc, char *argv[]){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutCreateWindow(argv[0]);
glClearColor(0.0, 0.0, 0.0, 0.0);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}