接着 [demo2].进阶啦,来一个可以移动的多边形吧 的代码继续

用线性代数的思维来构建多边形

1. 删掉不再需要的代码

  1. // //v0, v1, v2, v3, v4 相对于v0的相对位置
  2. // GLfloat relate_tops[15] = { }; //删掉
  3. // //v0, v1, v2, v3, v4 的新位置
  4. // GLfloat movie_tops[15] = { }; //删掉
  5. // GLfloat blockX = movie_tops[0]; //删掉
  6. // GLfloat blockY = movie_tops[1]; //删掉
  7. // blockY = blockY + stepSize;//这一系列的全部删掉
  8. // for (int i = 0 ; i < 15; i++) { // 从这里开始删掉
  9. // if (i % 3 == 0) {
  10. // movie_tops[i] = relate_tops[i] + blockX;
  11. // } else if (i % 3 == 1) {
  12. // movie_tops[i] = relate_tops[i] + blockY;
  13. // } else {
  14. // movie_tops[i] = 0;
  15. // }
  16. // // printf("%.01f", movie_tops[i]);
  17. // } // 到这里结束 全部删掉
  18. //for (int i = 0 ; i < 15; i++) {
  19. // movie_tops[i] = vTops[i];
  20. // relate_tops[i] = vTops[i] - vTops[i % 3];
  21. // printf("%.01f - %0.1f\n", movie_tops[i], relate_tops[i]);
  22. // }

2. 将vTops设置为全局变量(放到triangleBatch下面)

2. 将SpecialKeys函数中的movie_tops修改为vTops

  1. //triangleBatch.CopyVertexData3f(movie_tops);
  2. triangleBatch.CopyVertexData3f(vTops);
  1. Run一下,五边形正常,按键全部无效

4. 接着开始准备矩阵算法,我们需要设置一个全局的x和y的向量参数

  1. GLfloat xPos = 0.0f;
  2. GLfloat yPos = 0.0f;

5. 在SpecialKeys中,根据移动的方向去改变这个向量的大小

  1. switch (key) {
  2. //方向键 上
  3. case GLUT_KEY_UP:
  4. yPos += stepSize;
  5. break;
  6. //方向键 下
  7. case GLUT_KEY_DOWN:
  8. yPos -= stepSize;
  9. break;
  10. //方向键 左
  11. case GLUT_KEY_LEFT:
  12. xPos -= stepSize;
  13. break;
  14. //方向键 右
  15. case GLUT_KEY_RIGHT:
  16. xPos += stepSize;
  17. break;
  18. //键盘 i 上
  19. case 105:
  20. yPos += stepSize;
  21. break;
  22. //键盘 k 下
  23. case 107:
  24. yPos -= stepSize;
  25. break;
  26. //键盘 < 下
  27. case 44:
  28. yPos -= stepSize;
  29. break;
  30. //键盘 j 左
  31. case 106:
  32. xPos -= stepSize;
  33. break;
  34. //键盘 l 右
  35. case 108:
  36. xPos += stepSize;
  37. break;
  38. //键盘 u 左上
  39. case 117:
  40. yPos += stepSize;
  41. xPos -= stepSize;
  42. break;
  43. //键盘 o 右上
  44. case 111:
  45. yPos += stepSize;
  46. xPos += stepSize;
  47. break;
  48. //键盘 m 左下
  49. case 109:
  50. yPos -= stepSize;
  51. xPos -= stepSize;
  52. break;
  53. //键盘 > 右下
  54. case 46:
  55. yPos -= stepSize;
  56. xPos += stepSize;
  57. break;
  58. default:
  59. printf("Unwork Key %d\n", key);
  60. break;
  61. }
  1. 这样,对键盘的响应时间就完成了,当然,这个时候Run还是无法操作的,因为vTops并没用发生任何变化,我们只是对向量xPosyPos进行了操作,因此,我们需要将向量应用到vTops中,这个时候就轮到矩阵登场了(线性代数)锵~锵~锵~

6. 在RenderScene中,新建一个局部变量,它是一个4*4的矩阵

  1. M3DMatrix44f mFinalTransform;

7. 这个值用于存放最终的结果(使用方法类似于NSError,用的时候千万别加上&,会报错的 T.T)

  1. M3DMatrix44f mTransfromMatrix;

8. 这个值用于存放每次变化后相对于原点的向量结果,使用方式同上然后把向量代入平移的矩阵算法中

  1. m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0f);

9. 这样就能在每次刷新的时候得到相对于原点的向量结果,然后将这个结果提交给固定着色器,先试下会发生什么

  1. //单元着色器, 并设置着色器的颜色
  2. // shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vPencil); //改成下面的样子
  3. shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransfromMatrix, vPencil);

10. Run一下,发现图形已经可以正常移动了,但是边界检测器却失效了,无法检测边界,这时候我们就需要修改边界条件了[demo3].再进阶一次,数学与代码的完美碰撞 - 图2
根据这张图,我们可以看到,向左最多可以移动0.6的距离,向上最多可以移动0.5的距离,向右最多可以移动0.4的距离,向下最多只能移动0.3的距离,那么换成向量则是

  1. // for (int i = 0; i < 15; i++) {
  2. // if (tem_point[i] > 1 || tem_point[i] < -1) {
  3. // return;
  4. // }
  5. // } 替换成下面的
  6. if (xPos <= -0.6) {
  7. xPos = -0.6;
  8. } else if (xPos >= 0.4) {
  9. xPos = 0.4;
  10. }
  11. if (yPos >= 0.5) {
  12. yPos = 0.5;
  13. } else if (yPos <= -0.3) {
  14. yPos = -0.3;
  15. }

11. 再Run一遍,然后移动,边界碰撞就出现了,完美! 👏👏👏👏

12. 但是每次都要这样手动去算,我不要!所以我们先创建4个全局变量,用于保存4个极值(就是到四条边的距离了)

  1. GLfloat distanceRight = 1.0f;
  2. GLfloat distanceLeft = -1.0f;
  3. GLfloat distanceTop = 1.0f;
  4. GLfloat distanceBottom = -1.0f;

13. 为什么要这样设置初始值呢?因为如果是0的话,就会卡在原点不动了,这个和下面的边界条件的判断相关然后在SetupRC中将它们计算出来

  1. for (int i = 0; i < 15; i++) {
  2. if (i % 3 == 0) {
  3. if (-1 - vTops[i] > distanceLeft) {
  4. distanceLeft = -1 - vTops[i];
  5. }
  6. if (1 - vTops[i] < distanceRight) {
  7. distanceRight = 1 - vTops[i];
  8. }
  9. } else if (i % 3 == 1) {
  10. if (1 - vTops[i] < distanceTop) {
  11. distanceTop = 1 - vTops[i];
  12. }
  13. if (-1 - vTops[i] > distanceBottom) {
  14. distanceBottom = -1 - vTops[i];
  15. }
  16. }
  17. }

14. 然后再将碰撞的条件改为

  1. // if (xPos <= -0.6) {
  2. // xPos = -0.6;
  3. // } else if (xPos >= 0.4) {
  4. // xPos = 0.4;
  5. // }
  6. //
  7. // if (yPos >= 0.5) {
  8. // yPos = 0.5;
  9. // } else if (yPos <= -0.3) {
  10. // yPos = -0.3;
  11. // }
  12. //
  13. if (xPos <= distanceLeft) {
  14. xPos = distanceLeft;
  15. } else if (xPos >= distanceRight) {
  16. xPos = distanceRight;
  17. }
  18. if (yPos >= distanceTop) {
  19. yPos = distanceTop;
  20. } else if (yPos <= distanceBottom) {
  21. yPos = distanceBottom;
  22. }

15. 然后Run起来,完美!!!!demo点这里下载啦


让图像拥有旋转的能力吧

问题又双叒叕来了,如果我想让它旋转呢?

1. 设置一个全局变量,用来记录当前的旋转角度(0 ~ 360)再设置一个全局变量用来设置每次旋转角度(旋转的步长?旋长?旋度?)

  1. GLFloat angel = 0.0f;
  2. GLfloat stepAngel = 10.0f;

2. 在SpecialKeys中新监测两个Key,用于设置左旋右旋,就 “{“和”}”吧

  1. //左旋
  2. case 91:
  3. angel = angel + stepAngel;
  4. if (angel < 0) {
  5. angel = angel - 360;
  6. }
  7. break;
  8. //右旋
  9. case 93:
  10. angel = angel - stepAngel;
  11. if (angel > 360) {
  12. angel = angel + 360;
  13. }
  14. break;

要注意,OpenGL的角度是逆时针旋转的,所以右旋得减,左旋得加

3. 然后在RenderScene中,新建一个旋转的矩阵,将当前旋转的角度放入矩阵中进行运算

  1. M3DMatrix44f mRotationMartix;
  2. // mRotationMartix 矩阵计算结果
  3. // m3dDegToRad(angel) 当前旋转的角度
  4. // 0, 0, 1 绕 (0,0,0) -> (0, 0, 1) 这条射线旋转,也就是绕Z轴旋转, 如果想绕x轴旋转就传 1, 0, 0
  5. m3dRotationMatrix44(mRotationMartix, m3dDegToRad(angel), 0, 0, 1);

4. 然后将前面的平移矩阵和旋转矩阵合并起来,并将结果存入上面设置了完全没用过的mFinalTransform中,就得到最终的矩阵了

  1. m3dMatrixMultiply44(mFinalTransform, mTransfromMatrix, mRotationMartix);

5. 最后,将着色器的绘制矩阵替换为最终矩阵

  1. // shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransfromMatrix, vPencil);
  2. shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vPencil);
  1. run一下,棒~ 👏👏👏👏👏👏👏

5. 然后将旋转的轴更换下试试

  1. //m3dRotationMatrix44(mRotationMartix, m3dDegToRad(angel), 0, 0, 1);
  2. m3dRotationMatrix44(mRotationMartix, m3dDegToRad(angel), 1, 0, 0);
  1. Run,成功绕着x轴旋转,棒~ 👏👏👏👏👏👏👏
    点这里下Demo啦