案例 02悔橄、OpenGL入門--正方形鍵位控制

OpenGL + OpenGL ES +Metal 系列文章匯總

效果圖如下所示:


02姐帚、正方形鍵位控制.gif

整體的流程圖如下


正方形鍵位控制整體流程圖

主要需要實現(xiàn)以下兩部分:

  • 繪制正方形
  • 特殊鍵位移動函數(shù)

繪制正方形

在之前的三角形繪制中畔柔,我們已經(jīng)了解了圖形繪制的一個基本流程,那么正方形的繪制就是水到渠成的关串,只需要在三角形代碼的基礎(chǔ)上做以下修改:

  • 定義頂點到原心距離赏淌,即 正方形邊長 = blockSize * 2
GLfloat blockSize = 0.1f;
  • 修改頂點數(shù)組
//正方形四個點的坐標
GLfloat vVerts[] = {
    -blockSize, -blockSize, 0.0f,
    blockSize, -blockSize, 0.0f,
    blockSize, blockSize, 0.0f,
    -blockSize, blockSize, 0.0f,
};
  • 修改setupRC函數(shù)中圖元的連接方式
//將 GL_TRIANGLES 修改為 GL_TRIANGLE_FAN ,4個頂點
    triangleBatch.Begin(GL_TRIANGLE_FAN, 4);

到此踩寇,正方形就繪制完成了,接下來我們需要完成正方形鍵位控制效果

鍵位控制效果

主要是指正方形根據(jù)選擇鍵盤的上下左右鍵移動六水。

該效果的實現(xiàn)有兩種方式

  • 坐標更新方式
  • 矩陣方式

打個比方俺孙,有100件需要染同一種顏色的衣服,你可以選擇一件一件的染色缩擂,也可以選擇同時將100件放入染缸鼠冕,一起染色添寺,

  • 其中一件一件染色指代的就是坐標更新方式胯盯,適用于頂點較少的圖形,
  • 同時放入染色指代的就是矩陣方式计露,當圖形頂點非常多的博脑,再用坐標更新就不合適了憎乙,需要使用矩陣來同時更新。

坐標更新方式

頂點根據(jù)相對頂點逐個更新頂點坐標叉趣,在SpecialKeys函數(shù)中完成鍵位移動時坐標的更新泞边,并手動調(diào)用渲染。

三個自定義函數(shù)的流程圖如下:


坐標更新-自定義函數(shù)實現(xiàn)流程

ChangeSize和RenderScene就不做解釋了疗杉,在繪制時阵谚,這部分已經(jīng)完成了,主要說說SpecialKeys函數(shù)

  • 首先需要定義一個步長
  • 定義一個相對頂點的x和y值
    假設(shè)正方形如下圖所示烟具,以D為相對頂點


    正方形.png
  • 根據(jù)鍵位方向梢什,分別更新x 和 y
  • 邊緣碰撞處理
    如果沒有這個步驟,圖形移動到邊緣時朝聋,就會移動到屏幕不可見的區(qū)域嗡午,下圖可以說明4個方向?qū)吘壟鲎蔡幚硎侨绾斡嬎愕模@里就不做詳細說明了


    坐標更新-邊緣碰撞計算

具體的代碼實現(xiàn)如下:

//key 枚舉值冀痕,x荔睹、y是位置
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);
    
    //根據(jù)移動方向,更新相對坐標
    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;
    }
    
    //觸碰到邊界(4個邊界)的處理
    
    //當正方形移動超過最左邊的時候
    if (blockX < -1.0f) {
        blockX = -1.0f;
    }
    //當正方形移動到最右邊時
    //1.0 - blockSize * 2 = 總邊長 - 正方形的邊長 = 最左邊點的位置
    if (blockX > (1.0f - blockSize * 2)) {
        blockX = 1.0f - blockSize * 2;
    }
    //當正方形移動到最下面時
    //-1.0 - blockSize * 2 = Y(負軸邊界) - 正方形邊長 = 最下面點的位置
    if (blockY < -1.0f + blockSize * 2) {
        blockY = -1.0f + blockSize * 2;
    }
    //當正方形移動到最上面時
    if (blockY > 1.0f) {
        blockY = 1.0f;
    }
    
    printf("blockX = %f\n",blockX);
    printf("blockY = %f\n",blockY);
    
    //重新計算正方形的位置
    //一個頂點有三個數(shù) x言蛇、y僻他、z
    vVerts[0] = blockX;
    vVerts[1] = blockY - blockSize * 2;
    printf("(%f,%f)\n",vVerts[0],vVerts[1]);
    
    vVerts[3] = blockX + blockSize * 2;
    vVerts[4] = blockY - blockSize * 2;
    printf("(%f,%f)\n",vVerts[3],vVerts[4]);
    
    vVerts[6] = blockX + blockSize * 2;
    vVerts[7] = blockY;
    printf("(%f,%f)\n",vVerts[6],vVerts[7]);
    
    vVerts[9] = blockX;
    vVerts[10] = blockY;
    printf("(%f,%f)\n",vVerts[9],vVerts[10]);
    
    //更新頂點數(shù)據(jù)
    triangleBatch.CopyVertexData3f(vVerts);
    
    //重新渲染提交 --> RenderScene
    glutPostRedisplay();
    
}

矩陣方式

主要是根據(jù)x軸、y軸移動的距離猜极,生成一個平移矩陣中姜,通過圖形*平移矩陣 = 移動后的圖形,得到最終效果

涉及兩個函數(shù):RenderScene跟伏、SpecialKeys

矩陣方式中自定義函數(shù)的流程如下:


矩陣-自定義函數(shù)

SpecialKeys 函數(shù)

  • 定義步長及兩個全局變量(相對于x軸和y軸的平移距離)
//記錄移動圖形時丢胚,在x軸上平移的距離
GLfloat xPos = 0.0f;
//記錄移動圖形時,在y軸上平移的距離
GLfloat yPos = 0.0f;

GLfloat stepSize = 0.025f;
  • 根據(jù)移動方向受扳,計算移動距離
  • 邊緣碰撞處理
    其移動距離計算的理解如圖所示
    ==> 可以將初始化的平移距離理解為正方形的中心携龟,即原點,在圖形移動時勘高,其中心點也發(fā)生了移動峡蟋,所以我們要計算的邊緣的移動距離就是兩個中心店之間的平移距離


    矩陣-邊緣碰撞處理邏輯
  • 手動觸發(fā)重新渲染

具體實現(xiàn)如下:

//使用矩陣方式(一起搞定),不需要修改每個頂點华望,只需要記錄移動步長蕊蝗,碰撞檢測
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;
    }
    
    //碰撞檢測 xPos是平移距離,即移動量
    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();
    
}

RenderScene 函數(shù)
主要步驟如下:

  • 清理特定緩存區(qū)
  • 根據(jù)平移距離計算平移矩陣
  • 將矩陣結(jié)果交給存儲著色器(平面著色器)中繪制
    在位置更新方式中赖舟,使用的是單元著色器蓬戚,而矩陣方式中,涉及的矩陣是4*4的宾抓,單元著色器不夠用子漩,所以使用平面著色器

具體的代碼實現(xiàn)如下

//開始渲染
void RenderScene(void)

{
    //1.清除一個或者一組特定的緩存區(qū)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    //1.設(shè)置顏色RGBA
    GLfloat vRed[] = {1.0f, 0.5f, 0.0f, 1.0f};
    
    
    //定義矩陣
    M3DMatrix44f mTransformMatrix;
    
    //平移矩陣
    m3dTranslationMatrix44(mTransformMatrix, xPos, yPos, 0.0f);
    
    //當單元著色器不夠用時豫喧,使用平面著色器
    //參數(shù)1:存儲著色器類型
    //參數(shù)2:使用什么矩陣變換
    //參數(shù)3:顏色
    shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransformMatrix, vRed);
    
    //提交著色器
    triangleBatch.Draw();
    glutSwapBuffers();
}

完整代碼見Github -02_正方形鍵位控制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市幢泼,隨后出現(xiàn)的幾起案子紧显,更是在濱河造成了極大的恐慌,老刑警劉巖缕棵,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孵班,死亡現(xiàn)場離奇詭異,居然都是意外死亡招驴,警方通過查閱死者的電腦和手機重父,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忽匈,“玉大人房午,你說我怎么就攤上這事〉ぴ剩” “怎么了郭厌?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長雕蔽。 經(jīng)常有香客問我折柠,道長,這世上最難降的妖魔是什么批狐? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任扇售,我火速辦了婚禮,結(jié)果婚禮上嚣艇,老公的妹妹穿的比我還像新娘承冰。我一直安慰自己,他們只是感情好食零,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布困乒。 她就那樣靜靜地躺著,像睡著了一般贰谣。 火紅的嫁衣襯著肌膚如雪娜搂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天吱抚,我揣著相機與錄音百宇,去河邊找鬼。 笑死秘豹,一個胖子當著我的面吹牛携御,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼因痛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了岸更?” 一聲冷哼從身側(cè)響起鸵膏,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怎炊,沒想到半個月后谭企,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡评肆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年债查,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瓜挽。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盹廷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出久橙,到底是詐尸還是另有隱情俄占,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布淆衷,位于F島的核電站缸榄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏祝拯。R本人自食惡果不足惜甚带,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望佳头。 院中可真熱鬧鹰贵,春花似錦、人聲如沸康嘉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凄鼻。三九已至腊瑟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間块蚌,已是汗流浹背闰非。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留峭范,地道東北人财松。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辆毡。 傳聞我的和親對象是個殘疾皇子菜秦,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353