これが実現すること
これを分析すると、次のようなステップで達成する必要があります。
- 緑の市松模様の床を描いてください;
- 中心に大きな赤いボールを描き、その回転を実現します;
- ランダムな位置にある50個の小さな静止球と、大きな赤い球の周りを回転する青い球を描きます;
- 大きな赤いボールの周りをダイナミックな青いボールが回転する様子;
- 大きな赤いボールの回転と青いボールの回転を観測するために観測者を移動させる効果を実装します;
I. フロアのドローイング
ChangeSize ビューポートと投影方法の設定:投影投影行列と行列スタックを設定します;
glViewport(0, 0, w, h);
// 投影行列を作る
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.f);
// viewFrustum投影行列を取得し、投影行列スタックにロードする。
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
/* 2つの行列スタックを使うように変換パイプラインをセットアップする
* GLGeometryTransformのインスタンスtransformPipelineを初期化し、その内部ポインタをモデルビュー行列スタックと投影行列スタックのインスタンスに設定する。
* この操作はSetupRC関数でも行うことができる。SetupRC関数はウィンドウサイズを変更したときやウィンドウを作成したときに設定され、マトリックスやパイプラインの設定を一度に行うことができる。
*/
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
SetupRC():床を描画するための頂点データを準備します;
//
glClearColor(0.f, 0.f, 0.f, 1.f);
shaderManager.InitializeStockShaders();
// 深度テストをオンにする
glEnable(GL_DEPTH_TEST);
// 324個の行列からなる床の頂点データをセットする
floorBatch.Begin(GL_LINES, 324);
for (GLfloat x = -20.f; x <= 20.f; x += 0.5f) {
floorBatch.Vertex3f(x, -0.55f, 20.f);
floorBatch.Vertex3f(x, -0.55f, -20.f);
floorBatch.Vertex3f(20.f, -0.55f, x);
floorBatch.Vertex3f(-20.f, -0.55f, x);
}
floorBatch.End();
RenderScence():緑の床を描画します。
// カラーバッファと深度バッファをクリアする
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 床の色
static GLfloat vFloorColor[] = {0.f, 1.f, 0.f, 1.f};
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor);
floorBatch.Draw();
// キャッシュスワップを行う
glutSwapBuffers();
II.大きな赤いボールを描く
// カラーバッファと深度バッファをクリアする
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// // 床の色
// static GLfloat vFloorColor[] = {0.f, 1.f, 0.f, 1.f};
// 大きな赤いボールの色
static GLfloat vTorusColor[] = {1.f, 0.f, 0.f, 1.f};
// アニメーション・タイマー
static CStopWatch rotTimer;
float yPot = rotTimer.GetElapsedSeconds() * 60.f;
//
modelViewMatrix.PushMatrix();
// // 床を描く
// shaderManager.UseStockShader(GLT_SHADER_FLAT,
// transformPipeline.GetModelViewProjectionMatrix(),
// vFloorColor);
// floorBatch.Draw();
// 光源の位置を知る
M3DVector4f vLightPods = {0.f, 10.f, 5.f, 1.f};
// 大きな赤いボールが画面内を移動するように配置する(3).0)
modelViewMatrix.Translate(0.f, 0.f, -3.f);
// スタックを押す
modelViewMatrix.PushMatrix();
// 大きな赤いボールが回転する
modelViewMatrix.Rotate(yPot, 0.f, 1.f, 0.f);
// シェーダーを指定する
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,
transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPods,
vTorusColor);
torusBatch.Draw();
// 抽選後、スタックから飛び出す
modelViewMatrix.PopMatrix();
modelViewMatrix.PopMatrix();
// キャッシュスワップを行う
glutSwapBuffers();
glutPostRedisplay();
III.グリーンボールの抽選
無作為に50個のボールを抽選
// 50個の小さなボールをランダムに描く
for (int i = 0; i < NUM_SPHERES; i++) {
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[i]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,
transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPods,
vSphereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
大きな青いボールを描き、赤いボールの周りを回転させます。
//静的な小球を描く
for (int i = 0; i < NUM_SPHERES; i++) {
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[i]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
// 行列スタックに回転、平行移動の操作を記録する
modelViewMatrix.Rotate(yRot * -1.0f, 0, 1, 0);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
sphereBatch.Draw();
IV.動くオブザーバー
void SpeacialKeys(int key,int x,int y){
float linear = 0.1f;
float angular = float(m3dDegToRad(5.0f));
if (key == GLUT_KEY_UP) {
cameraFrame.MoveForward(linear);
}
if (key == GLUT_KEY_DOWN) {
cameraFrame.MoveForward(-linear);
}
if (key == GLUT_KEY_LEFT) {
cameraFrame.RotateWorld(angular, 0, 1, 0);
}
if (key == GLUT_KEY_RIGHT) {
cameraFrame.RotateWorld(-angular, 0, 1, 0);
}
}





