3. 3d ビューイング -...

22
3. 3D ビューイング 1. Dグラフィックス処理の一般過程 2. 射影と射影変換 3. ビューボリュームとクリッピング 4. 陰面処理とデプスバッファ 5. ビューポート変換 6. 3Dグラフィックスを描く 7. モデルビュー変換

Upload: others

Post on 04-Apr-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

3. 3D ビューイング

1. 3Dグラフィックス処理の一般過程

2. 射影と射影変換

3. ビューボリュームとクリッピング

4. 陰面処理とデプスバッファ

5. ビューポート変換

6. 3Dグラフィックスを描く

7. モデルビュー変換

Page 2: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. 3Dグラフィックス処理の一般過程

3Dグラフィックス処理の一般過程

Page 3: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. モデリング変換座標系の異なる複数のオブジェクトを仮想世界に配置し,統一的に扱うために,それぞれの座標系をワールド座標系に変換する

2. ビューイング変換ワールド座標系におけるオブジェクトの各座標系を,視点座標系における座標値に変換する

3Dグラフィックス処理の一般過程

uvn座標系;投影面を定義するための座標系視点座標系のZ軸は,uvn座標系の原点を通り,uv平面と直交する

Page 4: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. 正規化変換

① x,y 成分は,-1.0 ~ +1.0 の範囲

あるいは,0.0 ~ +1.0 の範囲

② z成分は,0.0 ~ +1.0 の範囲

あるいは, -1.0 ~ +1.0 の範囲

3Dグラフィックス処理の一般過程

Page 5: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. 透視投影

射影と射影変換

Page 6: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. 投影面における投影点座標の計算投影面における投影点(x,y)座標は相似三角形理論で計算できる

投影点のx座標と点Pのx座標Pxの比,

投影点のy座標と点Pのy座標Pyの比,

投影面の距離Nと点Pの投影中心との距離-Pz

の比は等しい

従って,

投影点の座標は,視点との距離に反比例する.

⇒遠いものは小さく,近いものは大きく見える

投影面の透視点の座標は投影面との距離に比例する

⇒投影される図形は投影面の距離によってスケーリングされる

しかし,射影変換された座標は最後にビューポートに変換されるので射影される図形の大きさは結果には影響しない

射影と射影変換

zyx PN

Py

Px

z

y

z

x

PP

NPPNyx ,,

Page 7: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. ビューボリュームとクリッピング

OpenGL;

glFrustum(Gldouble left, Gldouble right,Gldouble bottom, Gldouble top,Fldouble nera, G;double far);

gluPerspective(Gldouble fovy, /* y,z 平面における視角 */Gldouble aspect, /* 錐台の幅対高さ比 */Gldouble near,Gldouble far);

ビューボリュームとクリッピング

Page 8: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

正射影変換のビューボリューム

OpenGL;glOrtho(Gldouble left,

Gldouble right,Gldouble bottom,Gldouble top,Gldouble near,Gldouble far);

ビューボリュームとクリッピング

Page 9: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

射影中心から放射する直線上にある全ての点は同じ場所に射影される

右図の場合,P1がP2に隠されているのでP1を描く必要はない

隠されていることを見つける方法の1つ

視点から見る頂点の距離を利用すること,即ち遠い頂点が近い頂点に隠される

距離の表現:デプス(depth) --- 頂点の遠さを[-1, 1]の範囲で正規化したもの

near plane[N]; z=-1,

far plane[F]; z=1

3次元空間の点が射影変換により新たな3次元の点にマッピングされる,x,yは射影面の座標,zは視点からの距離

陰面処理とデプスバッファ

z

z

PbaPz

NF

FNb

NFNFa

2

z

z

z

y

z

xzyx P

baPPP

NPP

NzyxPPP ,,,,,,

Page 10: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

OpenGL depth-buffer/z-bufferpixel 毎にデプス値を記憶する

Depth test;frame-bufferにある輝度あるいは色の値を更新するか否かを判断する

被射影の頂点のデプス値は現在より小さければ,そのバッファ値を更新する

処理終了時,デプスバッファの値は一番近い点の値が保存される

この結果,陰面(陰線)を除去され,見える部分のみが描画される

OpenGL;glCLearDepthMask(Glclampd depth); 初期値を指定

glClear(); 初期化

glEnable(GL_DEPTH_TEST); デプステストを有効にする

glDepthFunc(Glenum func); func=GL_LESS;値が小さい場合更新

陰面処理とデプスバッファ

Page 11: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. ビューポート変換

一連の変換で計算される図形が最後に,このviewportにマッピングされる

2. OpenGl

glViewport(GLint x, GLint y, Glsizei width, Glsizei height);デバイス座標またはウィンドウ座標

初期値は,(0, 0, winWidth, winHeight)

注:ビューポート変換には,並行移動に加えスケーリング変換も含むこのために,図形が変形する(「ゆがみ」が生じる)ビューポートの縦横比を near plane と同じにすると,ゆがみは生じない

ビューポート変換

Page 12: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. 3Dグラフィックスを描く program 3.1

faces; 6個の面を構成する頂点の番号を保存

カメラは,初期には原点にある

投影関係は, reshape() の中で次のように指定する

gluPerspective(60.0, (Glfloat)w/(GLfloat)h, 1.0, 20.0);視界角fovy=60,視点と前面,後面との距離は,1.0, 20.0カメラ位置は原点だから,全面z=-1.0, 後面z=-20.0

reshape() は,ウィンドウを再描画する度にパラメータとして幅wと高さhが,渡されるので,この縦横比を調整する

立方体の描画は,display()の中でDrawBox()を呼び出して行う各面毎に,面の頂点を用いて,プリミティブGL_LINE_LOOPを指定する

3Dグラフィックスを描く

Page 13: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. モデルビュー変換 program 3.2program 3.1 では,物体を視点座標で定義し,カメラ位置を考慮して,

物体の座標を決めている ⇒ これは不自然

モデルを移動したり,カメラ位置と視線方向を変えるモデルビュー変換により物体は,カメラとは無関係にユーザ座標で設計できる

2. モデリング変換・・・移動・回転・スケーリング

3. ビューイング変換・・・カメラ位置と視線方向

モデルビュー変換

Page 14: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

#include <stdlib.h>#include <GL/glut.h>

GLint faces[6][4]={ /* 頂点番号と面の情報 */{0,1,2,3},{3,2,6,7},{7,6,5,4},{4,5,1,0},{5,6,2,1},{7,4,0,3}};

GLfloat v[8][3]; /* 頂点座標 {x0,y0,z0}, {x1,y1,z1},….*/void drawBox(void){

int i;for(i=0; i<6; i++){

glBegine(GL_LINE_LOOP);glVertex3fv(&v[faces[i][0]][0]);glVertex3fv(&v[faces[i][1]][0]);glVertex3fv(&v[faces[i][2]][0]);glVertex3fv(&v[faces[i][3]][0]);glEnd(); /* pointer i/f */

}}void init(void){

glClearColor(0.0,0.0,0.0,0.0);v[0][0]=v[1][0]=v[2][0]=v[3][0]=-1; /* x-axis*/v[4][0]=v[5][0]=v[6][0]=v[7][0]=1;v[0][1]=v[1][1]=v[4][1]=v[5][1]=-1; /* y-axis*/v[2][1]=v[3][1]=v[6][1]=v[7][1]=1;v[0][2]=v[3][2]=v[4][2]=v[7][2]=-4; /* z-axis*/v[1][2]=v[2][2]=v[5][2]=v[6][2]=-6;

}void display(void){

glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0);drawBox();glFlush();

}

void reshape(int w, int h){glViewport(0, 0, (GLsizei)w, (GLsizei)h);glLoadIdentity();glMatrixMode(GL_PROJECTION); /* 射影変換 */gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);

} /* camera = origine *//* ViewVolume w/h = ViewPort w/h*/

void keyboard(unsigned char key, int x, int y){switch(key){

case 27;exit(0);break;

}}

int main(int argc, char **argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(200, 200);glutInitWindowPosition(100, 100);glutCreatWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 0;

}

3.1

0 4

3

2

76

51

Page 15: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

#include <stdlib.h># include <GL/glut.h>GLint faces[6][4]={

{0,1,2,3},{3,2,6,7},{7,6,5,4},{4,5,1,0},{5,6,2,1},{7,4,0,3}};GLfloat v[8][3];void drawBox(void){

int i;for(i=0; i<6; i++){

glBegine(GL_LINE_LOOP);glVertex3fv(&v[faces[i][0]][0]);glVertex3fv(&v[faces[i][1]][0]);glVertex3fv(&v[faces[i][2]][0]);glVertex3fv(&v[faces[i][3]][0]);glEnd();

}}void init(void){ /* オブジェクトをユーザ座標で定義 */

glClearColor(0.0,0.0,0.0,0.0);v[0][0]=v[1][0]=v[2][0]=v[3][0]=-1;v[4][0]=v[5][0]=v[6][0]=v[7][0]=1;v[0][1]=v[1][1]=v[4][1]=v[5][1]=-1;v[2][1]=v[3][1]=v[6][1]=v[7][1]=1;v[0][2]=v[3][2]=v[4][2]=v[7][2]=1; // -4 1v[1][2]=v[2][2]=v[5][2]=v[6][2]=-1; // -6 -1

}void display(void){

glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0);glLoadIdentity();glutLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);drawBox(); /* camera位置の設定 */glFlush();

}

void reshape(int w, int h){glViewport(0, 0, (GLsizei)w, (GLsizei)h);glLoadIdentity();glMatrixMode(GL_PROJECTION);gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);glMatrixMode(GL_MODELVIEW);

}

void keyboard(unsigned char key, int x, int y){switch(key){

case 27;exit(0);break;

}}

int main(int argc, char **argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(200, 200);glutInitWindowPosition(100, 100);glutCreatWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 0;

}

3.2 モデル・ビュー変換

Page 16: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, /* camera 位置 */GLdouble centerx, GLdouble centery, GLdouble centerz, /* cameraの注視点 */GLdouble upx, GLdouble upy, GLdouble upz) /* cameraの上方向 */

OpenGLにおけるカメラの設定

OpenGLにおけるカメラの設定OpenGLにおけるモデルビュー変換の一般的な手順

1. モデルビュー変換を指定 glMatrixMode(GL_MODELVIEW);2. 変換マトリクスの初期化 glLoadIdentity();3. モデルビュウー変換 gluLookAt();

Page 17: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

#include <stdlib.h>#include <GL/glut.h>GLint faces[6][4]={

{0,1,1,3},{3,2,6,7},{7,6,5,4},{4,5,1,0},{5,6,2,1},{7,4,0,3}};GLfloat v[8][3];void drawBox(void){

int i;for(i=0; i<6; i++){

glBegine(GL_LINE_LOOP);glVertex3fv(&v[faces[i][0]][0]);glVertex3fv(&v[faces[i][1]][0]);glVertex3fv(&v[faces[i][2]][0]);glVertex3fv(&v[faces[i][3]][0]);glEnd();

}}void init(void){

glClearColor(0.0,0.0,0.0,0.0);v[0][0]=v[1][0]=v[2][0]=v[3][0]=-1;v[4][0]=v[5][0]=v[6][0]=v[7][0]=1;v[0][1]=v[1][1]=v[4][1]=v[5][1]=-1;v[2][1]=v[3][1]=v[6][1]=v[7][1]=1;v[0][2]=v[3][2]=v[4][2]=v[7][2]=1; v[1][2]=v[2][2]=v[5][2]=v[6][2]=-1;

}

viod LookAt(void){ /* 視点の変化に対するビューアップベクトルの計算*/int i;GLdouble look[3], norm;GLdouble ViewAt[3] = {5.0, 7.5, 5.0}; /* 位置 */GLdouble ViewTo[3] = {0.0, 0.0, 0.0}; /* 注視方向 */GLdouble ViewUp[3]; /* 上方向 */ for(i=0; i<3; i++){

look[i] =ViewTo[i] - ViewAt[i];}ViewUp[0] = - look[0] * look[2];ViewUp[1] = - look[1] * look[2];ViewUp[2] = look[0] * look[0] + look[1] * look[1] + look[2] * look[2];norm = ViewUp[0]*ViewUp[0] + ViewUp[1]*ViewUp[1] + ViewUp[2]*ViewUp[2];norm = sqrt(norm);for(i=0; i<3; i++){

ViewUp[i] /= norm;}gluLookAt(ViewAt[0], ViewAt[1], ViewAt[2],

ViewTo[0], ViewTo[1], ViewTo[2],ViewUp[0], ViewUp[1], ViewUp[2]);

}

void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0);glLoadIdentity();LookAt();drawBox();glFlush();

}

3.3 視点を変化

Page 18: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

void reshape(int w, int h){glViewport(0, 0, (GLsizei)w, (GLsizei)h);glLoadIdentity();glMatrixMode(GL_PROJECTION);gluPerspective(30.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);glMatrixMode(GL_MODELVIEW);

}

void keyboard(unsigned char key, int x, int y){switch(key){

case 27;exit(0);break;

}}

int main(int argc, char **argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(200, 200);glutInitWindowPosition(100, 100);glutCreatWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 0;

}

3.3

Page 19: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

#include <stdlib.h>#include <GL/glut.h>GLint faces[6][4]={

{0,1,1,3},{3,2,6,7},{7,6,5,4},{4,5,1,0},{5,6,2,1},{7,4,0,3}};

GLfloat v[8][3];GLfloat n[6][3]={

{-1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{1.0, 0.0, 0.0},{0.0, -1.0, 0.0},{0.0, 0.0, -1.0},{0.0, 0.0, 1.0}};

void drawBox(void){int i;for(i=0; i<6; i++)

glBegin(GL_POLYGON);glNormal3fv(&n[i][0]);glVertex3fv(&v[faces[i][0]][0]);glVertex3fv(&v[faces[i][1]][0]);glVertex3fv(&v[faces[i][2]][0]);glVertex3fv(&v[faces[i][3]][0]);glEnd();

}}void init(void){

GLfloat mat_amb_diff[4]={1.0,1.0,1.0,1.0};GLfloat light_amb[4]={1.0,5.5,1.0,1.0};glClearColor(0.0,0.0,0.0,0.0);glShadeModel(GL_SMOOTH);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_amb_diff);glLightfv(GL_LIGHT0, GL_POSITION, light_amb);

glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glEnable(GL_DEPTH_TEST);

v[0][0]=v[1][0]=v[2][0]=v[3][0]=-1;v[4][0]=v[5][0]=v[6][0]=v[7][0]=1;v[0][1]=v[1][1]=v[4][1]=v[5][1]=-1;v[2][1]=v[3][1]=v[6][1]=v[7][1]=1;v[0][2]=v[3][2]=v[4][2]=v[7][2]=1; v[1][2]=v[2][2]=v[5][2]=v[6][2]=-1;

}

viod LookAt(void){ /* 視点の変化に対するビューアップベクトルの計算*/int i;GLdouble look[3], norm;GLdouble ViewAt[3] = {5.0, 7.5, 5.0}; /* 位置 */GLdouble ViewTo[3] = {0.0, 0.0, 0.0}; /* 注視方向 */GLdouble ViewUp[3]; /* 上方向 */ for(i=0; i<3; i++){

look[i] =ViewTo[i] - ViewAt[i];}ViewUp[0] = - look[0] * look[2];ViewUp[1] = - look[1] * look[2];ViewUp[2] = look[0] * look[0] + look[1] * look[1] + look[2] * look[2];norm = ViewUp[0]*ViewUp[0] + ViewUp[1]*ViewUp[1] + ViewUp[2]*ViewUp[2];norm = sqrt(norm);for(i=0; i<3; i++){

ViewUp[i] /= norm;}gluLookAt(ViewAt[0], ViewAt[1], ViewAt[2],

ViewTo[0], ViewTo[1], ViewTo[2],ViewUp[0], ViewUp[1], ViewUp[2]);

}

3.4 照明・材料などの光学特性

Page 20: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0);glLoadIdentity();LookAt();drawBox();glFlush();

}

void reshape(int w, int h){glViewport(0, 0, (GLsizei)w, (GLsizei)h);glLoadIdentity();glMatrixMode(GL_PROJECTION);gluPerspective(30.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);glMatrixMode(GL_MODELVIEW);

glClear(GL_DEPTH_BUFFER_BIT);}

void keyboard(unsigned char key, int x, int y){switch(key){

case 27;exit(0);break;

}}

int main(int argc, char **argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(200, 200);glutInitWindowPosition(100, 100);glutCreatWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 0;

}

3.4

Page 21: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

glMaterialf*(材質が設定される面,材質の特性,設定値);

1) 材質が設定される面

GL_FRONT:ポリゴンの表面

GL_BACK: ポリゴンの裏面

GL_FRONT_AND_BACK: ポリゴンの表面と裏面

2) 材質の特性

GL_DIFFUSE:拡散反射成分,R,G,B,A強度を0.0~1.0で指定

GL_SPECULAR:鏡面反射成分,同上

GL_AMBIENT:環境光反射成分,同上

GL_EMISSION:発光物体の設定,同上

GL_SHININESS:鏡面反射光の強さを0.0~128.0で指定

3) 設定値と設定方法

1> 配列にR,G,B,A強度を予め定義し,glMaterialfv を用いる

float diffuse[ ]={1.0,1.0,10.,1.0};float specular[ ]={ 1.0,1.0,10.,1.0};float ambient[ ]={0.1,0.1,0.1,1.0};

glMateialfv(GL_FRONT, GL_DIFFUSE, diffuse);glMaterialv(GL_FRONT, GL_SPECULAR, specular);glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);

2> GL_SHININESSを設定する場合は,glMaterialf を用いる

glMaterialf(GL_FRONT, GL_SHINENESS, 128.0);

Page 22: 3. 3D ビューイング - shonan-it.ac.jp射影中心から放射する直線上にある全ての点は同じ場所 に射影される 右図の場合,P1がP2に隠されているのでP1を描く必要は

1. P61の演習問題 問1~6を実施

2. 提出は,12月2日(月)の授業開始時まで1. 問1~3は,指定の用紙に記載

2. プログラムのソースコードはプリントしたものを提出

3. 実行結果を示すウィンドウの図を “PrtScn” にてプリントしたものを提出(当該ソースコードの裏面に)

3. 作業場所1. 1207教室のオープン時間

1. 月・火,3&4限

2. 木・金,4限

演習課題