OpenGL 02案例 ---- 正方形移動

正方形移動f

繪制流程

正方形繪制.png

案例01---- 三角形案例相比,除了繪制的圖形換成正方形之外,這邊我增加了移動代碼。

代碼實現(xiàn)

正方形圖形繪制

// blockSize 邊長
GLfloat blockSize = 0.1f;

//正方形的4個坐標點
GLfloat vVerts[] = {
    -blockSize,-blockSize,0.0f,
    blockSize,-blockSize,0.0f,
    blockSize,blockSize,0.0f,
    -blockSize,blockSize,0.0f
};
  • 準備好正方形的4個頂點,邊長數(shù)據(jù)。
  • 就下來就到 SetupRC 函數(shù)中,存儲頂點數(shù)據(jù)、設置圖元連接方式
    // 修改為GL_TRIANGLE_FAN,4個頂點
    triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();

接著就是command + R 一個正方形的圖形出來了。但是這時候的正方形就如同木頭樁子是的不會動,那怎么才能讓它動起來呢?關鍵地方到了,請往下看。

移動正方形

注冊特殊函數(shù)
glutSpecialFunc(SpecialKeys);

通過特殊函數(shù),我們可以獲得它鍵盤4個方向的按鍵響應

具體實現(xiàn)
void SpecialKeys(int key, int x, int y) {
    GLfloat stepSize = 0.025f;
    GLfloat blockX = vVerts[0];
    GLfloat blockY = vVerts[10];
    printf("v[0] = %f\n",blockX);
    printf("v[10] = %f\n",blockY);
    
    if (key == GLUT_KEY_UP) {
        blockY += stepSize;
    }
    if (key == GLUT_KEY_DOWN) {
        blockY -= stepSize;
    }
    if (key == GLUT_KEY_LEFT) {
        blockX -= stepSize;
    }
    if (key == GLUT_KEY_RIGHT) {
        blockX += stepSize;
    }
    
//    // 觸碰四個邊界的處理
//    // 當正方形移動超過最左邊的時候
//    if (blockX < -1.0f) {
//        blockX = -1.0f;
//    }
//    // 當正方形移動到最右邊的時候
//    if (blockX > 1.0f - blockSize * 2) {
//        blockX = 1.0f - blockSize * 2;
//    }
//    // 當正方形移動到最下面的時候
//    if (blockY < -1.0f + blockSize * 2) {
//        blockY = -1.0f + blockSize * 2;
//    }
//    // 當正方形移動到最上面的時候
//    if (blockY > 1.0f) {
//        blockY = 1.0f;
//    }
    // Recalculate vertex positions
    vVerts[0] = blockX;
    vVerts[1] = blockY - blockSize * 2;
    
    vVerts[3] = blockX + blockSize * 2;
    vVerts[4] = blockY - blockSize * 2;
    
    vVerts[6] = blockX + blockSize * 2;
    vVerts[7] = blockY;
    
    vVerts[9] = blockX;
    vVerts[10] = blockY;
    
    triangleBatch.CopyVertexData3f(vVerts);
    glutPostRedisplay();
}
  • 其中key對應4個方向按鍵,上下左右按鍵分別對應于GLUT_KEY_UP、GLUT_KEY_DOWN、GLUT_KEY_LEFT和GLUT_KEY_RIGHT;
  • x和y是捕捉的當按鍵事件發(fā)生時顯示窗口上鼠標點所處的位置,需要注意的是x和y是以左上角為起點(0,0),右下角為終點(windowWidth,windowHeight)。

這下算是大功告成了,但是當我們一直往右滑動,發(fā)現(xiàn)正方形不見了?

進行圖形到邊界處理

正方形超邊界

如圖 正方形往右滑動消失了一小塊了。這時候我們要打開SpecialKeys里面注釋的代碼,來處理正方形超出邊界的時候的情況。

// 觸碰四個邊界的處理
    // 當正方形移動超過最左邊的時候
    if (blockX < -1.0f) {
        blockX = -1.0f;
    }
    // 當正方形移動到最右邊的時候
    if (blockX > 1.0f - blockSize * 2) {
        blockX = 1.0f - blockSize * 2;
    }
    // 當正方形移動到最下面的時候
    if (blockY < -1.0f + blockSize * 2) {
        blockY = -1.0f + blockSize * 2;
    }
    // 當正方形移動到最上面的時候
    if (blockY > 1.0f) {
        blockY = 1.0f;
    }
正方形移動簡圖.png

通過代碼我們可以發(fā)現(xiàn),我們移動圖形主要是對他的每個頂點做了變動然后

矩陣代替頂點計算

到此移動正方形的功能已經(jīng)都已經(jīng)實現(xiàn)了。細心的我們可以看看能不能優(yōu)化一下。
上面SpecialKeys函數(shù)中我們可以發(fā)現(xiàn),我們每移動一下都得需要將每個頂點x,y值重新設一遍,這樣的話非常麻煩。要是我們一百頂點呢?估計我們得設置瘋了。
這時候我們就引入矩陣的概念。

增設 x,y變量

GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;

此用來記錄x,y軸 的變量。這時候是xPos,yPos以原點(0,0)(也是正方形中心點,此時正方形處在x,y軸的中心位置)為起始值。

void SpecialKeys(int key, int x, int y) {
    GLfloat stepSize = 0.025f;
    if (key == GLUT_KEY_UP) {
        yPos += stepSize;
    }
    if (key == GLUT_KEY_DOWN) {
        yPos -= stepSize;
    }
    if (key == GLUT_KEY_LEFT) {
        xPos -= stepSize;
    }
    if (key == GLUT_KEY_RIGHT) {
        xPos += stepSize;
    }
    
    // 觸碰四個邊界的處理
    // 當正方形移動超過最左邊的時候
    if (xPos < -1.0f + blockSize) {
        xPos = -1.0f + blockSize;
    }
    // 當正方形移動到最右邊的時候
    if (xPos > 1.0f - blockSize) {
        xPos = 1.0f - blockSize;
    }
    // 當正方形移動到最下面的時候
    if (yPos < -1.0f + blockSize) {
        yPos = -1.0f + blockSize;
    }
    // 當正方形移動到最上面的時候
    if (yPos > 1.0f - blockSize) {
        yPos = 1.0f - blockSize;
    }
    glutPostRedisplay();
}

其次SpecialKeys函數(shù)里面我們不需要再對頂點重新設置。我們只需要計算xPos,yPos的變化值。再調用glutPostRedisplay通知openGL調用RenderScene重新繪制。接下來就是關鍵,仔細往下瞧。

// 開始渲染
void RenderScene(void) {
    // 1.清除一個或一組特定的緩存區(qū)
    /*
     緩沖區(qū)是一塊存在圖像信息的存儲控件,紅色、綠色、藍色和alpha分量通常一起作為顏色緩存區(qū)或像素緩存區(qū)引用
     OpenGL 中不止一種緩沖區(qū)(顏色緩存區(qū)、深度緩存區(qū)和模板緩存區(qū))
     清除緩存區(qū)對數(shù)值進行預置
     參數(shù):指定將要對數(shù)值進行緩存
     GL_COLOR_BUFFER_BIT:指示當前激活的用來進行顏色寫入緩沖區(qū)
     GL_DEPTH_BUFFER_BIT:指示深度緩存區(qū)
     GL_STENCIL_BUFFER_BIT:指示模板緩沖區(qū)
     */
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    
    //2.設置一組浮點數(shù)來表示紅色
    GLfloat vRed[] = {1.0,0.0,0.9,1.0f};
    
    // 新增代碼 定義一個矩陣變量
    M3DMatrix44f mTransformMatrix;
    
    // 使用3d數(shù)學庫中的平移函數(shù) 獲取矩陣的值
    m3dTranslationMatrix44(mTransformMatrix, xPos, yPos, 0.0f);
    
    // 將矩陣結果交給著色器 進行繪制
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,mTransformMatrix,vRed);
    
    // 提交著色器
    triangleBatch.Draw();
    
    // 在開始的設置openGL                                                                                         窗口的時候,我們指定要一個雙緩沖區(qū)渲染環(huán)境。這就意味著將后臺緩沖區(qū)進行渲染,渲染結束后交換給前臺。這種方式可以防止觀察者看到可能伴隨著動畫幀與動畫幀之間的閃爍的渲染過程。緩沖區(qū)交換平臺將平臺特定的方式進行
    // 將后臺緩沖區(qū)進行渲染,然后結束后家還給前臺
    glutSwapBuffers();
}

這部分代碼重要之處就是使用了矩陣。

  • 首先創(chuàng)建了一個M3DMatrix44f變量,此變量通過m3dTranslationMatrix44函數(shù)根據(jù)xPos,yPos獲取變換矩陣。
  • 然后使用存儲著色器的時候將此變換矩陣傳遞給著色器,內部再跟顯存上的頂點做運算,計算出每個頂點實際的位置(這里還需要驗證)。

好了,到此我們已經(jīng)用矩陣代替了頂點計算完成正方形移動的代碼改動了。

這里還有一點強調,就是使用存儲著色器的時候一定要注意。有些著色器傳入矩陣沒有效果。所以這邊我們用的平面著色器。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容