CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
【经验总结】不能实施并行处理的情况 浅谈并行编程中的任务分解模式
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  专题开发/技术/项目 >  游戏开发

用点积和叉乘解决空间中固定朝向物体的摆放问题,欢迎批评指正。

楼主junglesong(除了代码,一无所有。)2002-12-26 15:18:20 在 专题开发/技术/项目 / 游戏开发 提问

等会就贴。 问题点数:1、回复次数:6Top

1 楼junglesong(除了代码,一无所有。)回复于 2002-12-26 16:13:32 得分 0

大家都知道可以用下面的方法将一个物体摆放在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   |  
   
  计算即可.Top

2 楼junglesong(除了代码,一无所有。)回复于 2002-12-26 16:18:15 得分 0

写完了,欢迎批评指正。Top

3 楼junglesong(除了代码,一无所有。)回复于 2002-12-27 08:44:32 得分 0

upTop

4 楼noslopforever(天堂里的死神)回复于 2002-12-27 16:39:21 得分 1

……没有,只感觉到改回去学校学数学了……Top

5 楼junglesong(除了代码,一无所有。)回复于 2002-12-27 17:07:08 得分 0

失望,撤贴。Top

6 楼icansaymyabc(学习与进步)回复于 2002-12-30 08:26:16 得分 0

好啊,辛苦你了!  
  Top

相关问题

  • 三维物体
  • 固定IP
  • 网页摆放flash
  • 物体阴影检测
  • 怎么固定层?
  • DataGrid固定表头
  • 控件位置的摆放
  • 窗体固定大小
  • 如何固定datagrid宽度?
  • 如何固定列宽?

关键词

  • 物体
  • 矢量
  • 叉乘
  • glrotatef
  • 旋转
  • 夹角
  • vz
  • 计算
  • vy
  • vx

得分解答快速导航

  • 帖主:junglesong
  • noslopforever

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
惹火投票。。火热进行中...
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
CSDN网站24小时值班电话:13552009689
Copyright © 2000-2009, CSDN.NET, All Rights Reserved
GongshangLogo