这两节,透明度和物体的3D运动,主要集中在第9讲,因为第9讲也用到了通过Alpha值来调整透明度的地方。
因为要模拟星星,所以要创建的四边形需要很多,例子中创建了50个正方形。因为每个星星的属性都差不多,所以选择了用结构体来循环创建。(感觉有点像面向对象的思路。)为了让星星在翻转的时候不至于由面变成一条线,通过自己数次的测试,我理解为X,Y,Z坐标轴始终是固定在所创建的对象上的,举个例子,想像一个正方形正对着自己,然后Z轴箭头向内,尾巴朝着自己,假如让此正方形向左(你自己的左边)转90度,那么坐标轴的Z轴箭头就像固定在正方形上那样,变成了箭头指向右边,尾巴朝向自己的左边。恩,(记住坐标轴就跟长在要创建的对象上就对了,之前绕死我了,以为坐标轴轴心不动,怎么都想不明白,一步一步变换观察才发现自己理解错了)。
所以,操作顺序是:(假设有个定点,所有的星星都围绕着这个定点运动)先在定点通过翻转,朝向星星所在点的方向,然后向星星的位置出发(代码是沿X轴移动,也就是通过两次翻转说把X轴的箭头指向了星星的位置),到达星星位置,然后再逆序两次翻转复位(最开始正对观察者,到达指定位置后仍然要正对观察者,这样才不会在翻转的时候出现一条线的情形)。
接着就是通过改变每次循环的距离和角度变化来造就各种神奇的轨迹啦。还有,修改透明度要在创建四边形之前的位置修改,就是这里:
修改位置1的值,范围0~255,值越大越透明(看起来会很亮)对比一下,左边255,右边50(用了次10,快看不见了):
还有教程里说把深度测试关了,我试着没关也没看出什么区别。。带过吧。
还有报各种重定义之类的问题,试着添加或者去掉外部依赖项glu.lib之类的(我之前加进去也没报错)。
之前说过的用鼠标左右键以及滚轮控制的方法,我找到啦,因为例子代码用了windows自己的这个函数:
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window UINT uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam) // Additional Message Information { switch (uMsg) // Check For Windows Messages { case WM_ACTIVATE: // Watch For Window Activate Message { if (!HIWORD(wParam)) // Check Minimization State { active=TRUE; // Program Is Active } else { active=FALSE; // Program Is No Longer Active } return 0; // Return To The Message Loop } case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } case WM_CLOSE: // Did We Receive A Close Message? { PostQuitMessage(0); // Send A Quit Message return 0; // Jump Back } case WM_KEYDOWN: // Is A Key Being Held Down? { keys[wParam] = TRUE; // If So, Mark It As TRUE return 0; // Jump Back } case WM_KEYUP: // Has A Key Been Released? { keys[wParam] = FALSE; // If So, Mark It As FALSE return 0; // Jump Back } case WM_SIZE: // Resize The OpenGL Window { ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height return 0; // Jump Back } case WM_MBUTTONDOWN: { keys[wParam] = TRUE; // If So, Mark It As TRUE return 0; } case WM_LBUTTONDOWN: //左键按下 { MouseLB=TRUE; return 0; } case WM_LBUTTONUP: //左键释放 { MouseLB=FALSE; return 0; } case WM_RBUTTONDOWN: //右键按下 { MouseRB=TRUE; return 0; } case WM_RBUTTONUP: //右键释放 { MouseRB=FALSE; return 0; } case WM_MOUSEWHEEL: //滚轮 { //keys[wParam] = FALSE;前滚:7864320 int zDelta = GET_WHEEL_DELTA_WPARAM(wParam); if (zDelta<0) //后滚 { zoom-=1.2f; }else{ zoom+=1.2f; } //MessageBox(NULL,"you","",MB_OK|MB_ICONEXCLAMATION); return 0; } } // Pass All Unhandled Messages To DefWindowProc return DefWindowProc(hWnd,uMsg,wParam,lParam); }
而我再使用glut自己的这个函数就报内存冲突的错误:
glutMouseFunc(mouse);
所以要么只用这个,要么就像我一样用上面的代码。其中
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
这个是当滚轮事件触发时,用于判断是向前滚还是向后混的变量,zDelta会相应的呈正或负。我参考这个作的修改。
哎,一弄大半天都快过去了,不过弄清楚了很多问题,也蛮值得的啦。