首先,来绘制一个多边形

  1. [demo1].来一个最简单的三角形吧 的demo的基础上,将vTops里的顶点改成5个(或者6个7个8个…),并将全局容器内的绘制方式改为GL_POLYGON(或者改成其他的方式,见下图),并修改顶点个数
  1. GLfloat vTops[] = {
  2. -0.4, -0.3, 0, //v0
  3. 0.1, -0.7, 0, //v1
  4. 0.6, -0.1, 0, //v2
  5. 0.4, 0.5, 0, //v3
  6. -0.2, 0.4, 0 // v4
  7. };
  8. /**
  9. * GL_TRIANGLES 三角形
  10. */
  11. triangleBatch.Begin(GL_POLYGON, 5);

[demo2].进阶啦,来一个可以移动的多边形吧 - 图1

从上图可以看到有很多种绘图方式,可以根据需要选择自己需要的方式,这里是5个顶点,所以选择了GL_POLYGON(8个也可以选择POLYGON,会按照顺序依次连接并绘制封闭图形)。

  1. 直接运行,就可以看到一个5变形成功的绘制在窗口内了 👏👏👏
    [demo2].进阶啦,来一个可以移动的多边形吧 - 图2

接下来,让多边形动起来

  1. 设置一个全局变量,用于存放v0, v1, v2, v3, v4相对于v0的位置
    同时设置一个全局变量,用于存放v0,v1,v2,v3,v4的初始位置和新位置

    1. //v0, v1, v2, v3, v4 相对于v0的相对位置
    2. GLfloat relate_tops[15] = { };
    3. //v0, v1, v2, v3, v4 的新位置
    4. GLfloat movie_tops[15] = { };
  2. 在准备时计算相对位置

    1. for (int i = 0 ; i < 15; i++) {
    2. movie_tops[i] = vTops[i];
    3. relate_tops[i] = vTops[i] - vTops[i % 3];
    4. printf("%.01f - %0.1f\n", movie_tops[i], relate_tops[i]);
    5. }
  3. 这里是5个点,所以要循环3_5=15次,如果是n个点,则需要循环 3 _n次

  4. 注册一个新的函数,用于捕获键盘的输入 ```c /**
    • @param key 键盘输入的键 */ void SpecialKeys(int key, int x, int y) {

}

glutSpecialFunc(SpecialKeys);

  1. 4. 设置步长stepSize,用作每次移动时的移动距离,以此来控制移动速度
  2. ```c
  3. GLfloat stepSize = 0.01;
  1. 这里设置为0.01,每次会移动屏幕0.5%的距离(屏幕总长度为 1 - (-1) = 2)
  2. 确定一个参考点,根据参考点与其他点的相对位置关系,得到其他点的位置

    1. GLfloat blockX = movie_tops[0];
    2. GLfloat blockY = movie_tops[1];
  3. 这里将v0作为参考点,所有点会随着v0的移动而移动,之前设置相对点的时候也是以v0作为参考点的

  4. 检测键盘的输入,确认参考点的移动位置,向上移动,y增大,向下移动,y减小,向左移动,x减小,向右移动,x增大

    1. //向上移动
    2. switch (key) {
    3. //方向键 上
    4. case GLUT_KEY_UP:
    5. blockY = blockY + stepSize;
    6. break;
    7. //方向键 下
    8. case GLUT_KEY_DOWN:
    9. blockY = blockY - stepSize;
    10. break;
    11. //方向键 左
    12. case GLUT_KEY_LEFT:
    13. blockX = blockX - stepSize;
    14. break;
    15. //方向键 右
    16. case GLUT_KEY_RIGHT:
    17. blockX = blockX + stepSize;
    18. break;
    19. //键盘 i 上
    20. case 105:
    21. blockY = blockY + stepSize;
    22. break;
    23. //键盘 k 下
    24. case 107:
    25. blockY = blockY - stepSize;
    26. break;
    27. //键盘 < 下
    28. case 44:
    29. blockY = blockY - stepSize;
    30. break;
    31. //键盘 j 左
    32. case 106:
    33. blockX = blockX - stepSize;
    34. break;
    35. //键盘 l 右
    36. case 108:
    37. blockX = blockX + stepSize;
    38. break;
    39. //键盘 u 左上
    40. case 117:
    41. blockX = blockX - stepSize;
    42. blockY = blockY + stepSize;
    43. break;
    44. //键盘 o 右上
    45. case 111:
    46. blockX = blockX + stepSize;
    47. blockY = blockY + stepSize;
    48. break;
    49. //键盘 m 左下
    50. case 109:
    51. blockX = blockX - stepSize;
    52. blockY = blockY - stepSize;
    53. break;
    54. //键盘 > 右下
    55. case 46:
    56. blockX = blockX + stepSize;
    57. blockY = blockY - stepSize;
    58. break;
    59. default:
    60. printf("Unwork Key %d\n", key);
    61. break;
    62. }
  5. 在这里,我额外根据按键时打印的信号另外增加了9个键,遗憾的是,E和D不知为何无法响应(就是按了没反应),所以并没用WSAD

  6. 再根据相对位置,将移动后的点和v0的关系求出 ```c for (int i = 0 ; i < 15; i++) { if (i % 3 == 0) {
    1. movie_tops[i] = relate_tops[i] + blockX;
    } else if (i % 3 == 1) {
    1. movie_tops[i] = relate_tops[i] + blockY;
    } else {
    1. movie_tops[i] = 0;
    }

// printf(“%.01f”, movie_tops[i]); }

  1. 8. 在将移动后新的位置复制进容器内,提交渲染<br />这个时候已经有了一支画笔,所以只需要强制重新渲染就OK
  2. ```c
  3. triangleBatch.CopyVertexData3f(movie_tops);
  4. glutPostRedisplay();
  1. 运行一下,5边形显示正常,按一下键盘,都正常,太棒了~
    但是!但是!奇怪的事情发生了,我再按E和D键,他们的功能和I和J的一模一样,E向上移动,D向左移动,真的神奇 =。=(有小伙伴知道吗?求解答)
  2. 到这里,可移动的多边形就搞定了,但是并不完善,还有边界的检测没做。
    为了做边界检测,我们需要设置一组临时数据,如果临时数据超出边界,就让这一次的移动无效

    1. GLfloat tem_point[15] = { };
    2. for (int i = 0 ; i < 15; i++) {
    3. if (i % 3 == 0) {
    4. tem_point[i] = relate_tops[i] + blockX;
    5. } else if (i % 3 == 1) {
    6. tem_point[i] = relate_tops[i] + blockY;
    7. } else {
    8. tem_point[i] = 0;
    9. }
    10. if (tem_point[i] > 1 || tem_point[i] < -1) {
    11. return;
    12. }
    13. }
  3. 经测试,完美~👏 (也可以考虑将tem_point设置为全局变量)
    点我下载这个demo


但是,当点特别多的时候,循环上千次,上万次的时候,这种方式未免有些无用(一个精细的2d模型上万的点正常吧),该怎么办呢?这时候就要用上线性代数了。具体怎么用?看下一篇