- 用线性代数的思维来构建多边形
- 1. 删掉不再需要的代码
- 2. 将vTops设置为全局变量(放到triangleBatch下面)
- 2. 将SpecialKeys函数中的movie_tops修改为vTops
- 4. 接着开始准备矩阵算法,我们需要设置一个全局的x和y的向量参数
- 5. 在SpecialKeys中,根据移动的方向去改变这个向量的大小
- 6. 在RenderScene中,新建一个局部变量,它是一个4*4的矩阵
- 7. 这个值用于存放最终的结果(使用方法类似于NSError,用的时候千万别加上&,会报错的 T.T)
- 8. 这个值用于存放每次变化后相对于原点的向量结果,使用方式同上然后把向量代入平移的矩阵算法中
- 9. 这样就能在每次刷新的时候得到相对于原点的向量结果,然后将这个结果提交给固定着色器,先试下会发生什么
根据这张图,我们可以看到,向左最多可以移动0.6的距离,向上最多可以移动0.5的距离,向右最多可以移动0.4的距离,向下最多只能移动0.3的距离,那么换成向量则是">10. Run一下,发现图形已经可以正常移动了,但是边界检测器却失效了,无法检测边界,这时候我们就需要修改边界条件了![[demo3].再进阶一次,数学与代码的完美碰撞 - 图1](/uploads/projects/nanziyaonulibenpao@uyzg7e/ab00330a983f3c3a3efc116e41a110a1.jpeg)
根据这张图,我们可以看到,向左最多可以移动0.6的距离,向上最多可以移动0.5的距离,向右最多可以移动0.4的距离,向下最多只能移动0.3的距离,那么换成向量则是- 11. 再Run一遍,然后移动,边界碰撞就出现了,完美! 👏👏👏👏
- 12. 但是每次都要这样手动去算,我不要!所以我们先创建4个全局变量,用于保存4个极值(就是到四条边的距离了)
- 13. 为什么要这样设置初始值呢?因为如果是0的话,就会卡在原点不动了,这个和下面的边界条件的判断相关然后在SetupRC中将它们计算出来
- 14. 然后再将碰撞的条件改为
- demo点这里下载啦">15. 然后Run起来,完美!!!!demo点这里下载啦
- 让图像拥有旋转的能力吧
接着 [demo2].进阶啦,来一个可以移动的多边形吧 的代码继续
用线性代数的思维来构建多边形
1. 删掉不再需要的代码
// //v0, v1, v2, v3, v4 相对于v0的相对位置// GLfloat relate_tops[15] = { }; //删掉// //v0, v1, v2, v3, v4 的新位置// GLfloat movie_tops[15] = { }; //删掉// GLfloat blockX = movie_tops[0]; //删掉// GLfloat blockY = movie_tops[1]; //删掉// blockY = blockY + stepSize;//这一系列的全部删掉// for (int i = 0 ; i < 15; i++) { // 从这里开始删掉// if (i % 3 == 0) {// movie_tops[i] = relate_tops[i] + blockX;// } else if (i % 3 == 1) {// movie_tops[i] = relate_tops[i] + blockY;// } else {// movie_tops[i] = 0;// }// // printf("%.01f", movie_tops[i]);// } // 到这里结束 全部删掉//for (int i = 0 ; i < 15; i++) {// movie_tops[i] = vTops[i];// relate_tops[i] = vTops[i] - vTops[i % 3];// printf("%.01f - %0.1f\n", movie_tops[i], relate_tops[i]);// }
2. 将vTops设置为全局变量(放到triangleBatch下面)
2. 将SpecialKeys函数中的movie_tops修改为vTops
//triangleBatch.CopyVertexData3f(movie_tops);triangleBatch.CopyVertexData3f(vTops);
Run一下,五边形正常,按键全部无效
4. 接着开始准备矩阵算法,我们需要设置一个全局的x和y的向量参数
GLfloat xPos = 0.0f;GLfloat yPos = 0.0f;
5. 在SpecialKeys中,根据移动的方向去改变这个向量的大小
switch (key) {//方向键 上case GLUT_KEY_UP:yPos += stepSize;break;//方向键 下case GLUT_KEY_DOWN:yPos -= stepSize;break;//方向键 左case GLUT_KEY_LEFT:xPos -= stepSize;break;//方向键 右case GLUT_KEY_RIGHT:xPos += stepSize;break;//键盘 i 上case 105:yPos += stepSize;break;//键盘 k 下case 107:yPos -= stepSize;break;//键盘 < 下case 44:yPos -= stepSize;break;//键盘 j 左case 106:xPos -= stepSize;break;//键盘 l 右case 108:xPos += stepSize;break;//键盘 u 左上case 117:yPos += stepSize;xPos -= stepSize;break;//键盘 o 右上case 111:yPos += stepSize;xPos += stepSize;break;//键盘 m 左下case 109:yPos -= stepSize;xPos -= stepSize;break;//键盘 > 右下case 46:yPos -= stepSize;xPos += stepSize;break;default:printf("Unwork Key %d\n", key);break;}
这样,对键盘的响应时间就完成了,当然,这个时候Run还是无法操作的,因为vTops并没用发生任何变化,我们只是对向量xPos,yPos进行了操作,因此,我们需要将向量应用到vTops中,这个时候就轮到矩阵登场了(线性代数)锵~锵~锵~
6. 在RenderScene中,新建一个局部变量,它是一个4*4的矩阵
M3DMatrix44f mFinalTransform;
7. 这个值用于存放最终的结果(使用方法类似于NSError,用的时候千万别加上&,会报错的 T.T)
M3DMatrix44f mTransfromMatrix;
8. 这个值用于存放每次变化后相对于原点的向量结果,使用方式同上然后把向量代入平移的矩阵算法中
m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0f);
9. 这样就能在每次刷新的时候得到相对于原点的向量结果,然后将这个结果提交给固定着色器,先试下会发生什么
//单元着色器, 并设置着色器的颜色// shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vPencil); //改成下面的样子shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransfromMatrix, vPencil);
10. Run一下,发现图形已经可以正常移动了,但是边界检测器却失效了,无法检测边界,这时候我们就需要修改边界条件了![[demo3].再进阶一次,数学与代码的完美碰撞 - 图2](/uploads/projects/nanziyaonulibenpao@uyzg7e/ab00330a983f3c3a3efc116e41a110a1.jpeg)
根据这张图,我们可以看到,向左最多可以移动0.6的距离,向上最多可以移动0.5的距离,向右最多可以移动0.4的距离,向下最多只能移动0.3的距离,那么换成向量则是
// for (int i = 0; i < 15; i++) {// if (tem_point[i] > 1 || tem_point[i] < -1) {// return;// }// } 替换成下面的if (xPos <= -0.6) {xPos = -0.6;} else if (xPos >= 0.4) {xPos = 0.4;}if (yPos >= 0.5) {yPos = 0.5;} else if (yPos <= -0.3) {yPos = -0.3;}
11. 再Run一遍,然后移动,边界碰撞就出现了,完美! 👏👏👏👏
12. 但是每次都要这样手动去算,我不要!所以我们先创建4个全局变量,用于保存4个极值(就是到四条边的距离了)
GLfloat distanceRight = 1.0f;GLfloat distanceLeft = -1.0f;GLfloat distanceTop = 1.0f;GLfloat distanceBottom = -1.0f;
13. 为什么要这样设置初始值呢?因为如果是0的话,就会卡在原点不动了,这个和下面的边界条件的判断相关然后在SetupRC中将它们计算出来
for (int i = 0; i < 15; i++) {if (i % 3 == 0) {if (-1 - vTops[i] > distanceLeft) {distanceLeft = -1 - vTops[i];}if (1 - vTops[i] < distanceRight) {distanceRight = 1 - vTops[i];}} else if (i % 3 == 1) {if (1 - vTops[i] < distanceTop) {distanceTop = 1 - vTops[i];}if (-1 - vTops[i] > distanceBottom) {distanceBottom = -1 - vTops[i];}}}
14. 然后再将碰撞的条件改为
// if (xPos <= -0.6) {// xPos = -0.6;// } else if (xPos >= 0.4) {// xPos = 0.4;// }//// if (yPos >= 0.5) {// yPos = 0.5;// } else if (yPos <= -0.3) {// yPos = -0.3;// }//if (xPos <= distanceLeft) {xPos = distanceLeft;} else if (xPos >= distanceRight) {xPos = distanceRight;}if (yPos >= distanceTop) {yPos = distanceTop;} else if (yPos <= distanceBottom) {yPos = distanceBottom;}
15. 然后Run起来,完美!!!!demo点这里下载啦
让图像拥有旋转的能力吧
问题又双叒叕来了,如果我想让它旋转呢?
1. 设置一个全局变量,用来记录当前的旋转角度(0 ~ 360)再设置一个全局变量用来设置每次旋转角度(旋转的步长?旋长?旋度?)
GLFloat angel = 0.0f;GLfloat stepAngel = 10.0f;
2. 在SpecialKeys中新监测两个Key,用于设置左旋右旋,就 “{“和”}”吧
//左旋case 91:angel = angel + stepAngel;if (angel < 0) {angel = angel - 360;}break;//右旋case 93:angel = angel - stepAngel;if (angel > 360) {angel = angel + 360;}break;
要注意,OpenGL的角度是逆时针旋转的,所以右旋得减,左旋得加
3. 然后在RenderScene中,新建一个旋转的矩阵,将当前旋转的角度放入矩阵中进行运算
M3DMatrix44f mRotationMartix;// mRotationMartix 矩阵计算结果// m3dDegToRad(angel) 当前旋转的角度// 0, 0, 1 绕 (0,0,0) -> (0, 0, 1) 这条射线旋转,也就是绕Z轴旋转, 如果想绕x轴旋转就传 1, 0, 0m3dRotationMatrix44(mRotationMartix, m3dDegToRad(angel), 0, 0, 1);
4. 然后将前面的平移矩阵和旋转矩阵合并起来,并将结果存入上面设置了完全没用过的mFinalTransform中,就得到最终的矩阵了
m3dMatrixMultiply44(mFinalTransform, mTransfromMatrix, mRotationMartix);
5. 最后,将着色器的绘制矩阵替换为最终矩阵
// shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransfromMatrix, vPencil);shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vPencil);
run一下,棒~ 👏👏👏👏👏👏👏
5. 然后将旋转的轴更换下试试
//m3dRotationMatrix44(mRotationMartix, m3dDegToRad(angel), 0, 0, 1);m3dRotationMatrix44(mRotationMartix, m3dDegToRad(angel), 1, 0, 0);
- Run,成功绕着x轴旋转,棒~ 👏👏👏👏👏👏👏
点这里下Demo啦
