如何在OpenGL中绕局部轴旋转对象? [英] How to rotate object around local axis in OpenGL?

查看:90
本文介绍了如何在OpenGL中绕局部轴旋转对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在一个正在进行的项目中,我想对齐链的链接,以使其遵循贝塞尔曲线的轮廓.我目前正在按照以下步骤操作.

I am working on an ongoing project where I want to align the links of a chain so that it follows the contours of a Bezier curve. I am currently following the steps below.

  1. 绘制曲线.
  2. 使用显示列表创建链中的一个链接.
  3. 使用FOR循环重复调用一个函数,该函数计算曲线上两点之间的角度,返回角度和链接应该绕其旋转的轴.
  4. 旋转角度"a"并平移到新位置,将链接放置在新位置.

我还应该说,两个半环面的中心必须位于贝塞尔曲线上. 另外,我知道我用来绘制繁琐的圆环的方法,稍后我将使用TRIANGLE_FAN或QUAD_STRIP来更有效地绘制圆环.

I should also say that the centres of the two half torus must lie on the Bezier curve. Also I am aware that the method I use to draw the torus I tedious, I will use TRIANGLE_FAN or QUAD_STRIP later on to draw the torus in a more efficient way.

乍一看,这种逻辑看起来像是可以正确渲染链条,但最终结果却不是我想象的那样.这是连锁店的样子.

While at first glance this logic looks like it would render the chain properly, the end result is not what I had imagined it to be. Here is a picture of what the chain looks like.

我读到您必须在旋转之前将对象平移到原点?我可以先调用glTranslate(0,0,0),然后从上面执行第4步吗?

I read that you have to translate the object to the origin before rotation? Would I just call glTranslate(0,0,0) and then follow step 4 from above?

到目前为止,我已经包括了相关的代码,希望能使我的代码正常工作,我将不胜感激.

I have included the relevant code from what I have done so far, I would appreciate any suggestions to get me code work properly.

/* this function calculates the angle between two vectors oldPoint and new point contain the x,y,z coordinates of the two points,axisOfRot is used to return the x,y,z coordinates of the rotation axis*/
double getAxisAngle(pointType oldPoint[],
pointType newPoint[],pointType axisOfRot[]){

float tmpPoint[3];   

float normA = 0.0,normB = 0.0,AB = 0.0,angle=0.0;
int i;

axisOfRot->x= oldPoint->y * newPoint->z - oldPoint->z * newPoint->y;
axisOfRot->y= oldPoint->z * newPoint->x - oldPoint->x * newPoint->z;
axisOfRot->z= oldPoint->x * newPoint->y - oldPoint->y * newPoint->x; 


normA=sqrt(oldPoint->x * oldPoint->x + oldPoint->y * oldPoint->y + oldPoint->z * 
oldPoint->z);
normB=sqrt(newPoint->x * newPoint->x + newPoint->y * newPoint->y + newPoint->z *    
newPoint->z);

tmpPoint[0] =  oldPoint->x * newPoint->x;
tmpPoint[1] =  oldPoint->y * newPoint->y;
tmpPoint[2] =  oldPoint->z * newPoint->z;   

for(i=0;i<=2;i++)
 AB+=tmpPoint[i];  

AB /= (normA * normB);  


    return angle = (180/PI)*acos(AB);  
 }

 /* this function calculates and returns the next point on the curve give the 4 initial points for the curve, t is the tension of the curve */
    void bezierInterpolation(float t,pointType cPoints[],
    pointType newPoint[]){

newPoint->x = pow(1 - t, 3) * cPoints[0].x +3 * pow(1 - t , 2) * t * cPoints[1].x + 3 
* pow(1 - t, 1) * pow(t, 2) * cPoints[2].x + pow(t, 3) * cPoints[3].x;

newPoint->y = pow(1 - t, 3) * cPoints[0].y +3 * pow(1 - t , 2) * t * cPoints[1].y + 3 
* pow(1 - t, 1) * pow(t, 2) * cPoints[2].y + pow(t, 3) * cPoints[3].y;

newPoint->z = pow(1 - t, 3) * cPoints[0].z +3 * pow(1 - t , 2) * t * cPoints[1].z + 3 
* pow(1 - t, 1) * pow(t, 2) * cPoints[2].z + pow(t, 3) * cPoints[3].z;

}

/* the two lists below are used to create a single link in a chain, I realize that creating a half torus using cylinders is a bad idea, I will use GL_STRIP or TRIANGLE_FAN once I get the alignment right 
*/
torusList=glGenLists(1);   

glNewList(torusList,GL_COMPILE);
for (i=0; i<=180; i++)
{
  degInRad = i*DEG2RAD;
  glPushMatrix();
  glTranslatef(cos(degInRad)*radius,sin(degInRad)*radius,0);
  glRotated(90,1,0,0);
  gluCylinder(quadric,Diameter/2,Diameter/2,Height/5,10,10);
  glPopMatrix();      
}

 glEndList();

    /*! create a list for the link , 2 half torus and 2 columns */

 linkList = glGenLists(1);

 glNewList(linkList, GL_COMPILE); 
 glPushMatrix();
 glCallList(torusList); 
 glRotatef(90,1,0,0);
 glTranslatef(radius,0,0);
 gluCylinder(quadric, Diameter/2, Diameter/2, Height,10,10); 
 glTranslatef(-(radius*2),0,0);
 gluCylinder(quadric, Diameter/2, Diameter/2, Height,10,10); 
 glTranslatef(radius,0, Height);
 glRotatef(90,1,0,0);
 glCallList(torusList); 
 glPopMatrix();
 glEndList();

最后是用于创建链中三个链接的代码

Finally here is the code for creating the three links in the chain

t=0.031; 
bezierInterpolation(t,cPoints,newPoint);  
a=getAxisAngle(oldPoint,newPoint,axisOfRot);
 glTranslatef(newPoint->x,newPoint->y,newPoint->z); 
   glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z);     
    glCallList(DLid);
   glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z); 
 glTranslatef(-newPoint->x,-newPoint->y,-newPoint->z);  

oldPoint[0]=newPoint[0];
bezierInterpolation(t+=GAP,cPoints,newPoint);  
a=getAxisAngle(oldPoint,newPoint,axisOfRot);
 glTranslatef(newPoint->x,newPoint->y,newPoint->z); 
  glRotatef(90,0,1,0);
   glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z);     
    glCallList(DLid);
   glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z); 
  glRotatef(90,0,1,0);  
 glTranslatef(-newPoint->x,-newPoint->y,-newPoint->z);  

 oldPoint[0]=newPoint[0];
 bezierInterpolation(t+=GAP,cPoints,newPoint);    
  a=getAxisAngle(oldPoint,newPoint,axisOfRot); 
   glTranslatef(newPoint->x,newPoint->y,newPoint->z);       
    glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z); 
     glCallList(DLid);
    glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z); 
   glTranslatef(-newPoint->x,-newPoint->y,newPoint->z); 

推荐答案

要注意的一件事是glTranslate函数建立在先前的翻译之上. IE. glTranslatef(0.0,0.0,0.0);不会到达原点,它只会将笔"移动到任何地方.幸运的是,笔"从原点开始.如果您转换为1.0,1.0,1.0,请尝试glTranslatef(0.0,0.0,0.0);您仍将以1.0、1.0、1.0进行绘制;

One thing to note is that glTranslate function builds on previous translations. I.E. a glTranslatef(0.0,0.0,0.0); won't go to the origin, it will just move the "pen" nowhere. Luckily, the "pen" starts at the origin. if you translate out to 1.0,1.0,1.0 then try a glTranslatef(0.0,0.0,0.0); you will still be drawing at 1.0,1.0,1.0;

此外,您似乎也掌握了openGL后乘矩阵的事实.为此,绘制后您可以正确地撤消"矩阵运算.我只看到一个地方,您可能会在这里离开,那就是此语句:

Also, you seem to grasp the fact that openGL post-multiplies matricies. To that end, you are correctly "undoing" your matrix operations after a draw. I only see one spot where you could potentially be off here and that is in this statement:

glRotatef(90,0,1,0);
   glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z);     
    glCallList(DLid);
   glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z); 
  glRotatef(90,0,1,0);  

在这里,您正确撤消了第二次旋转,但是第一次旋转似乎绕着y轴旋转得更多.最后的glRotatef需要读取glRotatef(-90,0,1,0);如果您想取消该轮换.

Here you correctly undo the second rotation, but the first one you seem to rotate even more around the y axis. the very last glRotatef needs to read glRotatef(-90,0,1,0); if you want to be undoing that rotation.

这篇关于如何在OpenGL中绕局部轴旋转对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆