blog

VII.OpenGL統合アプリケーション:大きなボールの回転、小さなボールの回転、オブザーバーの移動

緑色の正方形の床を描く;赤いボールの中心を描き、その回転を実現する;赤いボールの回転の周りに50個の静的なボールと青いボールのランダムな位置を描く;赤いボールの回転の周りに動的な青いボールを実現する;...

Sep 9, 2020 · 4 min. read
シェア

これが実現すること

これを分析すると、次のようなステップで達成する必要があります。

  • 緑の市松模様の床を描いてください;
  • 中心に大きな赤いボールを描き、その回転を実現します;
  • ランダムな位置にある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);
 }
 }
Read next

クールだ!チャン・サンは「プロセス間通信」にうまく答えられず、オフィシャルに電話を切られてしまった・・・。

前書き\n冒頭の短編\n\n\n\n\n\n\n\n真面目な話、今回は張本サンが一緒に復習し、プロセス間コミュニケーションの理解を深めることで、次回はより長い時間エアコンを吹かせることができるようにします。\n\n\n主な記事\n各プロセスのユーザーアドレス空間は分離されており、一般的には互いにアクセスできませんが、内部的な

Sep 8, 2020 · 18 min read