iCAx开思工具箱

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 25311|回复: 1
打印 上一主题 下一主题

一篇好文章!

[复制链接]
跳转到指定楼层
楼主
发表于 2008-4-9 22:46:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册登录,享用更多网站功能!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
看到一篇好文章,和大家一起分享!
和uf5945函数有点关系!就是变换里的函数!
大家都知道可以用下面的方法将一个物体摆放在opengl三维场景中的某个位置:   
  glPushMatrix();   
  glScalef(fZoomValue); //缩放   
  glTranslatef(xTrans,yTrans,zTrans); //平移   
  glRotatef(xRot,1,0,0   ); //绕x轴旋转   
  glRotatef(yRot,0,1,0   ); //绕y轴旋转   
  glRotatef(zRot,0,0,1   ); //绕z轴旋转   
  DrawSomeObj(**); //画物体   
  glPopMatrix();   
  如果是简单场景,即我们知道其绕三轴的夹角,那此方法是可行的,但是,如果要求在点(1,2,3)和点(7,8,9)之间绘制一个柱面,其轴线就是两点的连线,请问上面的办法如何处理。   
  有人说进行三角函数,计算出夹角,在结果上可以,但函数复杂,速度慢,还有一个变换一次后角度改变的问题,很容易就出错。建议大家不要用此方法。我推荐用点积和叉乘来一次性解决问题。   
  首先看glRotatef的定义:   
  glRotatef(Angle,vx,vy,vz);   
  Angle是一个标量,是变换前后的角度差;   
  vx,vy,vz组成一个矢量,表示旋转的轴;   
  只要可以计算出他们的值,就可以一次性将物体朝向旋转到位,而不需要进行开始时的三次旋转。   
   
  其次我们来看看点积和叉乘的数学定义:   
  点积: (x1   ,   y1   ,   z1   )   .(   x2   ,   y2   ,   z2   )   =   x1x2   +   y1y2   +   z1z2     
  叉乘: (   x1   ,   y1   ,   z1   )   X   (   x2   ,   y2   ,   z2   )   =(   y1z2   -   z1y2   ,   z1x2   -   x1z2   ,   x1y2   -   y1x2   )     
  点积可以来计算两矢量的夹角,公式如下:   
  cos   (V   ^   W)   =V.W   /   |   V   |   |   W   |   
  叉乘可以计算两矢量的垂直矢量,叉乘后的新矢量就是垂直于前两矢量的矢量.   
  这样,Angle,vx,vy,vz就都可以计算出来了,下面请看一个例子:   
  我要在x1,y1,z1--开始点,x2,y2,z2--结束点之间画一个柱面,画住的原始函数如下:   
  void   DrawPrism(float   SideLen,int   SideNum,float   Height){   
  if(SideNum<3)   return;   
  if(SideLen<0.000001   ||   Height<0.000001)   return;   
  int   i=0;   
   
  glPushMatrix();   
  for(i=0;i<SideNum;i++)   
  {   
  glBegin(GL_TRIANGLES);   
  glVertex3f(0,0,Height);   
  glVertex3f(SideLen*cos(i*2*PI/SideNum),SideLen*sin(i*2*PI/SideNum),Height);   
  glVertex3f(SideLen*cos((i+1)*2*PI/SideNum),SideLen*sin((i+1)*2*PI/SideNum),Height);   
  glEnd();   
  }   
  for(i=0;i<SideNum;i++)   
  {   
  glBegin(GL_TRIANGLES);   
  glVertex3f(0,0,0);   
  glVertex3f(SideLen*cos((i+1)*2*PI/SideNum),SideLen*sin((i+1)*2*PI/SideNum),0);   
  glVertex3f(SideLen*cos(i*2*PI/SideNum),SideLen*sin(i*2*PI/SideNum),0);   
  glEnd();   
  }   
  for(i=0;i<SideNum;i++)   
  {   
  glBegin(GL_QUADS);   
  glVertex3f(SideLen*cos((i+1)*2*PI/SideNum),SideLen*sin((i+1)*2*PI/SideNum),0);   
  glVertex3f(SideLen*cos((i+1)*2*PI/SideNum),SideLen*sin((i+1)*2*PI/SideNum),Height);   
  glVertex3f(SideLen*cos(i*2*PI/SideNum),SideLen*sin(i*2*PI/SideNum),Height);   
  glVertex3f(SideLen*cos(i*2*PI/SideNum),SideLen*sin(i*2*PI/SideNum),0);   
  glEnd();   
  }   
  glPopMatrix();   
  }   
  其默认是以(0,0,0)为起点,轴向为z正向,(0,0,Height)为终点,要把它"搬"到Point1(x1,y1,z1),Point2(x2,y2,z2)之间,用点积和叉乘就容易办到了,代码如下:   
  double   a,b,c,d,a1,b1,c1,a2,b2,c2,d1,d2;//定义矢量   
  double   alfa;//定义旋转角度   
   
  //这三步求得Point1和Point2的矢量1   
  a1   =   x2   -   x1;//   
  b1   =   y2   -   y1;//   
  c1   =   z2   -   z1;   
   
  //这是旋转前轴向代表的矢量2   
  a2   =   0;   
  b2   =   0;   
  c2   =   1;               
   
  d1   =   sqrt(a1*a1   +   b1*b1   +   c1*c1);//求矢量1的长度   
  d2   =   sqrt(a2*a2   +   b2*b2   +   c2*c2);//求矢量2的长度,其实就是1,这里为了说明没有简化   
  d   =   d1;//获得矢量1的长度   
   
  alfa   =   (GLdouble)(   acos(   abs(a1*a2   +   b1*b2   +   c1*c2)/d1/d2   )   *   180/PI   );//由点积计算旋转角度   
   
  //由叉乘计算旋转轴   
  a   =   b1*c2   -   b2*c1;   
  b   =   a2*c1   -   a1*c2;   
  c   =   a1*b2   -   a2*b1;   
   
  alfa   =     -alfa;//修正角度(也可以修改下面的glrotatef函数)   
   
  if(c1<0)   
  {   
  alfa   =   180   -   alfa;   
  }   
  glPushMatrix();   
  //glScalef(fZoomValue); //这里不用考虑缩放,所以不用   
  glTranslatef(x1,y1,z1); //平移   
  glRotatef(alfa,a,b,c   ); //旋转   
  DrawPrism(SideLen,4,d); //画柱,函数在上面   
  glPopMatrix();   
   
  自此函数完成,一般把上述过程优化后写入一个函数里,以方便使用.   
   
  如果是已知3轴旋转角,如何简化成一个glRotatef函数呢,用同样的办法就可以办到,复杂的一步是要通过这3轴旋转角计算出新矢量,这个计算过程在许多图形学的书中都有,公式是:   
  绕X轴旋转角q的矩阵   
  |   1   0   0   0   |   
  |   0   cos(q)   sin(q)   0   |   
  |   0   -sin(q)   cos(q)   0   |   
  |   0   0   0   1   |   
   
  绕Y轴旋转角q的矩阵:   
  |   cos(q)   0   -sin(q)   0   |   
  |   0   1   0   0   |   
  |   sin(q)   0   cos(q)   0   |   
  |   0   0   0   1   |   
   
  绕Z轴旋转角q的矩阵:   
  |   cos(q)   sin(q)   0   0   |   
  |-sin(q)   cos(q)   0   0   |   
  |   0   0   1   0   |   
  |   0   0   0   1   |   
   
  计算即可.
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 支持支持
沙发
发表于 2010-11-21 15:48:44 | 只看该作者

马上注册登录,享用更多网站功能!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手板模型制作,在线3D打印服务

QQ|小黑屋|手机版|开思工具箱 CAD工具箱_CAM工具箱  

GMT+8, 2024-11-14 14:38 , Processed in 0.013760 second(s), 8 queries , Gzip On, Redis On.

Powered by Discuz! X3.3

© 2002-2024 www.iCAx.org

快速回复 返回顶部 返回列表