190 likes | 358 Views
ICG08 Modeler. TA : 大森 , 後藤,魏. Modeler 概要. 今回からは簡単な 3DCG モデルとそのアニメーション作成を行っていきます 以下のスケルトンコードをダウンロードして使用してください 課題のページ http://130.158.80.141/‾cai/Project/Project3/Project3-Modeler08.html スケルトン http://130.158.80.141/‾cai/Project/Project3/ ModelerSkeleton2008.zip この配布資料はここにあります
E N D
ICG08 Modeler TA : 大森,後藤,魏
Modeler概要 • 今回からは簡単な3DCGモデルとそのアニメーション作成を行っていきます • 以下のスケルトンコードをダウンロードして使用してください 課題のページ http://130.158.80.141/‾cai/Project/Project3/Project3-Modeler08.html スケルトン http://130.158.80.141/‾cai/Project/Project3/ModelerSkeleton2008.zip • この配布資料はここにあります http://130.158.80.141/‾cai/Project/Project3/Modeler2008-1.ppt
Modelerプログラム概要 • モデルビューウィンドウと、スライダーを持つコントロールウィンドウの2つのメインウィンドウがある
Modelerプログラム概要 • スケルトンのコンパイル • 再度fltkの設定をする • プリミティブの追加 • スライダーの追加 • 階層モデル • アニメーション
ソースファイル概要 • modelerapp.h, modelerapp.cpp 変更しない! • modelerui.h, modelerui.cxx ユーザーインターフェース関連 • modelerdraw.h, modelerdraw.cpp 変更しない!
ソースファイル概要 • modelerview.h, modelerview.cpp このクラスのサブクラスを作っていって もらう このファイル自体は変更しない • modelerui.fl 変更しない!
ソースファイル概要 • vec.h, mat.h 変更しない! • camara.h, camera.cpp カメラに関する部分 • sample.cpp 例としてBoxModelクラスが記述して ある
sample.cpp やっていること: • main関数でスライダーを追加 • ModelerViewクラスを拡張して(この例ではBoxModelクラス)、draw関数をオーバーライドしてモデルを記述する
ModelerViewクラスの拡張 • BoxModelクラスを真似しよう! • 作ったクラスのdraw関数の部分だけを変更すればOK
OpenGLの階層プログラム • glTranslated:平行移動 • glRotated:回転 • glScaled :拡大・縮小 で座標系を変更し、 • glPushMatrix • glPopMatrix でその座標系をスタックに保存・呼出
draw関数:sample.cppのもの void BoxModel::draw() { ModelerView::draw(); // draw the floor (省略) // draw the box setAmbientColor(.1f,.1f,.1f); setDiffuseColor(0,1,.5f); glPushMatrix(); glTranslated(VAL(XPOS), VAL(YPOS), VAL(ZPOS)); glTranslated(-.5,0,-.5); glScaled(1, VAL(HEIGHT), 1); drawBox(1,1,1); glPopMatrix(); } ここで立方体を描く関数を呼び出し
プリミティブ関数の使用 スケルトンで用意されているプリミティブ • drawBox(double x, double y, double z) 原点を一端とした、大きさがそれぞれx, y, zの直方体を描く • drawSphere(double r) 原点中心の、半径rの球体を描く • drawCylinder(double h, double r1, doubler2) 原点を上底の中心として、高さがh,上底の半径がr1,下底の半径がr2の円柱を描く • drawTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) 頂点がそれぞれ(x1, y1, z1), (x2, y2, z2), (x3, y3, z3)の三角形を描く
自分でプリミティブ関数を作ろう • 三角錐や台形などを自分で追加する • Modelerdraw.cppのdrawBox関数を参考に ① Modelerdraw.hに宣言を追加する ② Modelerdraw.cppの最後に書き足す
drawBox関数 void drawBox( double x, double y, double z ) { ModelerDrawState *mds = ModelerDrawState::Instance(); _setupOpenGl(); if (mds->m_rayFile) { _dump_current_modelview(); fprintf(mds->m_rayFile, "scale(%f,%f,%f,translate(0.5,0.5,0.5,box {\n", x, y, z ); _dump_current_material(); fprintf(mds->m_rayFile, "})))\n" ); } else { /* remember which matrix mode OpenGL was in. */ int savemode; glGetIntegerv( GL_MATRIX_MODE, &savemode ); /* switch to the model matrix and scale by x,y,z. */
drawBox関数 glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glScaled( x, y, z ); glBegin( GL_QUADS ); glNormal3d( 0.0, 0.0, -1.0 ); glVertex3d( 0.0, 0.0, 0.0 ); glVertex3d( 0.0, 1.0, 0.0 ); glVertex3d( 1.0, 1.0, 0.0 ); glVertex3d( 1.0, 0.0, 0.0 ); (中略) glEnd(); /* restore the model matrix stack, and switch back to the matrix mode we were in. */ glPopMatrix(); glMatrixMode( savemode ); } } ここを書き換える
自分でプリミティブ関数を作ろう • glBeginで描く図形の種類を選ぶ • glNormal3dで法線方向(面の向き)を指定 • glVertex3dで頂点を指定していく • glEndで完了 頂点の指定は、面の表側から見て反時計回りに指定しよう
プリミティブの例:drawTriPole void drawTriPole( double h, double r ) { _setupOpenGl(); /* remember which matrix mode OpenGL was in. */ int savemode; glGetIntegerv( GL_MATRIX_MODE, &savemode ); /* switch to the model matrix and scale by x,y,z. */ glMatrixMode( GL_MODELVIEW ); glPushMatrix(); double pi = 3.1415926535; // 上底と下底を描く glBegin( GL_TRIANGLES ); glNormal3d( 0.0, 1.0, 0.0 ); glVertex3d( r*sin( 0 * 2*pi/360.0), h , r*cos( 0 * 2*pi/360.0) ); glVertex3d( r*sin(120 * 2*pi/360.0), h , r*cos(120 * 2*pi/360.0) ); glVertex3d( r*sin(240 * 2*pi/360.0), h , r*cos(240 * 2*pi/360.0) );
プリミティブの例:drawTriPole glNormal3d( 0.0,-1.0, 0.0 ); glVertex3d( r*sin( 0 * 2*pi/360.0), 0.0, r*cos( 0 * 2*pi/360.0) ); glVertex3d( r*sin(240 * 2*pi/360.0), 0.0, r*cos(240 * 2*pi/360.0) ); glVertex3d( r*sin(120 * 2*pi/360.0), 0.0, r*cos(120 * 2*pi/360.0) ); glEnd(); glBegin( GL_QUADS ); // 側面を描く for (int i = 0; i < 360; i += 120) { glNormal3d(sin((i+60)* 2*pi/360.0), 0.0, cos((i+60)* 2*pi/360.0)); glVertex3d( r*sin( i * 2*pi/360.0), h , r*cos( i * 2*pi/360.0) ); glVertex3d( r*sin( i * 2*pi/360.0), 0.0, r*cos( i * 2*pi/360.0) ); glVertex3d( r*sin((i+120) * 2*pi/360.0), 0.0, r*cos((i+120) * 2*pi/360.0) ); glVertex3d( r*sin((i+120) * 2*pi/360.0), h , r*cos((i+120) * 2*pi/360.0) ); } glEnd(); glPopMatrix(); glMatrixMode( savemode ); }
オリジナルプリミティブを作ろう • どんなモデルを作りたいか考えたら、それに用いるオリジナルのプリミティブを作ろう • 法線方向に注意! • (平面の法線方向は外積を用いると求められます。次回以降に説明します) • (同一平面状でも、頂点ごとに法線方向を指定することで、擬似的な曲面が描けます) • これらを念頭に、どんなプリミティブを作るか考えておこう