opengl:世界(openGL篇)来源: 发布时间:星期四, 2009年2月12日 浏览:236次 评论:0
记得在97年我用FoxPro编程完成了中国象棋这个游戏后(现在看来非常幼稚、呆板)指导导师对我大加赞赏他对我说你可不可以用c改写这个c对我来说简直无所知我直用FP在编程我几乎用了 3个月时间才完成了界面设置不过我很快发现用c可以很方便实现很多新东西例如棋子可以成为圆形了不象以前是方形而且速度可以更快些从此我爱上了c并用它做了很多有趣东西古墓丽影这个游戏改变我编程生涯我开始接触3D编程不过3D编程技术在国内非常落后从D3D使用开始我查阅了大量资料后来我发现运用GL比D3D更轻松我建议初学者都应从GL开始入手先了解构建客观世界基本思路方法然后用D3D改写当然并不是说GL实现不够好只是在图形特殊处理上GL比D3D要略差些我很高兴GL这个论坛为国内3D爱好者无私交流提供了平台我也想认实些忠实于3D朋友并和你们分享快乐我也很乐意把我心得体会和你们分享如果你们愿意我也会无私地提供给你们所耍要帮助我也正在写本书名叫世界它有你们所耍要东西它能够帮助你如何去实现个真实生动世界当然不会出版它是公司要我编内部学习教材但我会把它在适当时候和你分享如果你有什么困惑联系我吧:QQ89322712 <<世界>>摘录部分(动力学篇的运动学1): 运用计算机摸拟客观世界中物体运动可以看成是物体空间坐标和时间对应关系物体空间位置变化根据运动学公式:Vt=V0+at和S=Vtt+at2/2来进行计算其中Vt为末速度V0为初速度a为加速度,t为运动时间在时间很短情况下位移公式可以写成:S=Vtt特别当a=0时物体做匀速直线运动运动学公式变为:Vt=V0和S=Vtt在计算机摸拟通过计算物体下时刻空间位置然后不断更新物体位置坐标来达到动画摸拟目如下图物体位置从初位置A点沿直线匀速运动到下位置B点: 设两点坐标为A(x0,y0,z0),B(x1,y1,z1)从A点到B点计算公式为: PositionB=PositionA+DirectionA_B*Speed*Time;  (1) 公式中DirectionA_B为运动方向单位向量Speed为运动速度大小Time为运动时间 如果物体以定加速度从A点沿直线运动到B点则计算公式为: PositiomB=PositionA+DirectionA_B*Speed*Time+DirectionA_B*Acceleration*Time*Time*0.5   (2) 公式中Acceleration为物体沿A-B方向加速大小; 当然对于般曲线运动如平抛运动等只需要定义加速度方向单位向量和加速度数值大小对公式2进行修正如下: PositiomB=PositionA+Direction_Speed*Speed*Time+Direction_ Acceleration*  Acceleration*Time*Time*0.5 (3) 公式中Direction_Speed为速度方向单位向量Speed为速度大小Direction_ Acceleration为加速度方向单位向量Acceleration为加速度大小 C语言Opengl  API例程:摸拟平抛运动 GLUquadricObj *ball;//定义 2次几何体 float time1;//时间变量在化数据中赋值为0; //定义坐标结构 struct vector {   float  x;//向量方向坐标   float  y;   float  z; float  value;//向量大小值 } //定义单位向量 vector unitVector(vector vectorDirection) { float unit_length; unit_length=sqrt(vectorDirection.x*vectorDirection.x+vectorDirection.y*  vectorDirection.y+ vectorDirection.z* vectorDirection.z); vectorDirection.x/= unit_length; vectorDirection.y/= unit_length; vectorDirection.z/= unit_length;  vectorDirection; } vector  positionB;//下位置坐标 void DrawBall; {    vector positionA={-4,4,0}; vector Direction_Speed={1,0,0};//速度方向沿X轴正方向    vector Direction_Acceleration={0,-1,0};//加速度方向沿Y轴负方向 float  Speed=2.0f;//初速度大小 float  Acceleration=0.68f;//加速度大小    Direction_Speed= unitVector (Direction_Speed);//速度矢量单位化    Direction_Acceleration= unitVector (Direction_Acceleration);//加速度矢量单位化 positionB.x=positionA.x+Direction_Speed.x*Speed*time1+0.5* Direction_Acceleration.x*Acceleration*time1*time1; positionB.y=positionA.y+Direction_Speed.y*Speed*time1+0.5* Direction_Acceleration.y*Acceleration*time1*time1; positionB.z=positionA.z+Direction_Speed.z*Speed*time1+0.5* Direction_Acceleration.z*Acceleration*time1*time1;    glTranslatef(positionB.x,positionB.y,positionB.z);//更新到下个位置    ball=gluNewQuadric;//得到 2次物体 gluQuadricDrawStyle(ball,GLU_LINE);//采用线框方式画物体 gluSphere(ball,0.3f,20,20);//画球体    time10.02f;//时间累记 } 在上面例程中可以更改速度和加速度方向坐标,得到各种直线或曲线运动当然在实际生活中物体受力情况相当复杂现在对这情况作个简单分析: 假设物体受到n个恒定不变力F1、F2、….Fn当然还有变化力存在如:空气阻力等我们先不讨论变力存在按照牛顿第 2定律:F=ma先计算出合力大小和方向矢量就可以得到加速度大小和方向矢量实现思路方法如下:  n;//力个数 vector Force_F[n];//定义n个力 vector ResultantForce;//定义合力 for( i=0;i<n;i) {    ResultantForce= ResultantForce+Force_F[n]; } 如果存在变力可按照运动独立性原理把力按照时间片段进行处理 2、物体碰撞摸拟 客观世界中物体碰撞是相当复杂首先第步就是要判断物体间是否会发生碰撞如果发生则进步分析碰撞点再根据能量损失情况作出碰撞后物体运动处理现实生活中光线反射给和了我们很好启示:(如下图) 1表示入射光线2表示反射光线 N表示平面法线 按照反射定律:入射光和反射光有关 平面法线对称 现在我们判断入射光和平面是否存在交点 假定入射光方向向量为N0光路上点坐标为P0平面法线向量为N平面上点坐标为P因此: 入射光线方程为:P(t)=P0+N0*t  (1) 平面方程为:p*N=D (2) 光线和平面不相交无处乎存在两种情况: 是入射向量和平面相平行即:N0*N=0; 是入射向量和平面法线向量方向相反即:N0*N<0; 如果上述两种情况均不存在则入射光线必和平面有交点现在来求交点坐标: 把(1)式代入(2)式可得到:(P0+N0*t)*N=D   (3) 解出时间t=(D-P0*N)/N0*N (4) 把(4)式代入(1)式可得到交点坐标: P(t)=P0+(P*N-P0*N)*N0/N0*N             (5) C语言实现算法如下: vector RayVectorN0;//入射光线方向向量 vector RayPositionP0;//入射光初位置坐标 vector PlanNormalN;//平面法线向量 vector PlanPoP;//平面上点坐标 //计算交点坐标并反回交点坐标 vector GetIntersectionPo(vector P0,vector N0,vector P,vector N) {    vector Pt;    float  PdotN_P0dotN;    float  N0_dot_N;    PdotN_P0dotN =(P.x*N.x+P.y*N.y+P.z*N.z)-(P0.x*N.x+P0.y*N.y+P0.z*N.z);    N0_dot_N=N0.x*N.x+N0.y*N.y+N0.z*N.z;    Pt.x=P0.x+ PdotN_P0dotN / N0_Dot_N*N0.x;    Pt.y=P0.y+ PdotN_P0dotN / N0_Dot_N*N0.y;    Pt.z=P0.z+ PdotN_P0dotN / N0_Dot_N*N0.z;     Pt; } 现在已计算出入射光线和平面交点根据反射定律我们知道反射光线和入射光线有关平面交点法线对称现在我们来计算反射光线向量方向由下图我们可以看到把入射光线向量分解到平面方向为N1,法线反方向为N2 现在反射光线向量就等于N1和N2反向向 量矢量和:P2=N1+(-N2); N2= (N0*N)*N   N1=N0-N2; 所以:P2= N0-2(N0*N)*N; 根据上面经验如果个球体以定速度碰到平面并发生完全弹性碰撞则该球体反弹 速度方向满足光线反射定律如果碰撞中有能损失则在N1、N2方向速度分量乘上衰 减系数 现在我们来讨论刚性球体和平面发生完全弹性碰撞情况 球体沿N0方向运动当球体运动到P1位置时球体和平面刚好发生接触设接触点为Q1 球体从P0到P1时间和球体上点Q0到Q1位置时间是相等现在我们来计算点Q0到Q1位置时间: 沿速度方向运动方程:Q(t)=Q0+N0*t; 平面方程:Q*N=D 由上面两个方程可知: (Q0+N0*t)*N=D 解得时间t=(D-Q0*N)/N0*N; P0坐标是已知,可以解出Q0坐标:Q0=P0-r*N;代入上式得到 t=(D-(P0-r*N)*N)/N0*N=(D-P0*N+r)/N0*N; 现在就已得到了球体和平面在Q1点发生碰撞时间根据计算时间我们可以预计球体和平面是否发生碰撞当然要注意如果速度方向和平面平行碰撞是不会发生同时如果解出时间为负值表明球体远离平面也不会发生碰撞下面我们来分析实现这种检测思路方法步骤:(略) 碰撞例子3: 0
相关文章读者评论发表评论 |