代码之家  ›  专栏  ›  技术社区  ›  Dave Hirsch

无法将OpenGL中的圆柱体正确旋转到所需位置

  •  0
  • Dave Hirsch  · 技术社区  · 14 年前

    我有一个客观的C实用程序,它呈现了一个凸面外壳。(这是为了排除另一个程序中的错误,该程序计算凸面外壳,为空间统计分析做准备)。我尝试渲染一组三角形,每个三角形都有一个向外指向的向量。我可以毫无问题地得到三角形,但向量让我抓狂。

    我希望向量是简单的圆柱。问题是,我不能只以三维形式声明圆柱体顶部和底部所属位置的坐标(例如,我可以为三角形声明坐标)。我必须制作它们,然后沿着Z轴旋转并从它们的默认位置平移它们。我读过很多关于欧拉角,角轴旋转,和四元数的书,其中大部分都是相关的,但并不是针对我需要的:大多数人都有一组对象,然后需要根据一些输入来旋转对象。我需要在3D“场景”中正确放置对象。

    我正在使用 cocoa3dtutorial 类来帮助我,它们的工作效果非常好,据我所知,但是旋转位正在杀死我。

    这是我目前的努力。它提供了正确定位的圆柱体,但所有点都沿着z轴(如图所示): 。我们正朝-z方向看。后面伸出的三角形不是船体的一部分;用于测试/调试。正交圆柱体或多或少是坐标轴,球体是为了确保轴的位置正确,因为我必须使用旋转来正确放置这些圆柱体。顺便说一句,当我使用该算法时,输出向量也会失败,尽管以不同的方式,垂直于平面,但都指向+z而不是某些in-z)。

    来自render3ddocument.m:

    //make the out pointing vector
    c3dtcylinder*排气管;
    c3dtentity*输出向量性;
    point3float*sidectr=[此侧质量中心];
    outvecttube=[c3dtcylinder cylinderwithbase:tuberadius top:tuberadius height:tuberadius*10 slices:16 stacks:16];
    outvectentity=[c3dtEntity EntityWithStyle:三色
    几何:outvecttube];
    point3float*outvect=[[thisside invect]相反];
    point3float*unitz=[point3float pointwithx:0 y:0 z:1.0f];
    点3Float*Rottaxis=[Outvect CrossWith:UnitZ];
    双旋转角度=[outvect anglewith:unitz];
    [outvectentity setrotationx:旋转轴.x
    Y:轮叶菌Y
    Z:轮叶菌属
    旋转角;
    [输出向量设置转换x:sidectr.x-ctrx
    Y:侧中心Y-中心
    z:sidectr.z-ctrz];
    [上升加子:出向性];
    < /代码> 
    
    

    (请注意,point3float基本上是一个向量类,一个边(如thisside)是一组四个point3float,每个顶点一个,指向外壳中心的向量一个)。

    来自c3dtentity.m:

    if(_hasttransform){
    GLPASTIMEXRY();
    
    /翻译
    如果(\u translation.x!=0.0)(翻译.y!=0.0)(_translation.z!= 0){
    gltranslatef(_translation.x,_translation.y,_translation.z);
    }
    
    /缩放
    如果(\scaling.x!=1.0)(缩放.y!=1.0)(scaling.z!= 1){
    glscalef(_scaling.x,_scaling.y,_scaling.z);
    }
    
    /旋转
    gltranslatef(—“旋转中心.x,—“旋转中心.y,—“旋转中心.z”);
    
    如果(旋转.w!= 0){
    glrotatef(_rotation.w,_rotation.x,_rotation.y,_rotation.z);
    }否则{
    如果(Rotation.x!= 0)
    glrotatef(_rotation.x,1.0f,0.0f,0.0f);
    如果(旋转,Y!= 0)
    glrotatef(_rotation.y,0.0f,1.0f,0.0f);
    如果(\u rotation.z!= 0)
    glrotatef(_rotation.z,0.0f,0.0f,1.0f);
    }
    
    gltranslatef(_rotationcenter.x,_rotationcenter.y,_rotationcenter.z);
    }
    < /代码> 
    
    

    我在上面的代码中添加了一个位,它围绕一个轴使用一个旋转(if(_rotation.w!=0.0)“位),而不是一组三个旋转。我的代码可能有问题,但我看不到如何解决。

    我希望向量是简单的圆柱。问题是,我不能只以三维形式声明圆柱体顶部和底部所属位置的坐标(例如,我可以为三角形声明坐标)。我必须制作它们,然后沿着Z轴旋转并从它们的默认位置平移它们。我读过很多关于欧拉角,角轴旋转,和四元数的书,其中大部分都是相关的,但并不是针对我需要的:大多数人都有一组对象,然后需要根据一些输入来旋转对象。我需要在3D“场景”中正确放置对象。

    我正在使用Cocoa3DTutorial课程帮助我,据我所知,他们工作得很好,但是轮班让我很难受。

    这是我目前的努力。它提供了正确定位的圆柱体,但所有点都沿着z轴(如图所示:alt text. 我们正朝-z方向看。后面伸出的三角形不是船体的一部分;用于测试/调试。正交圆柱体或多或少是坐标轴,球体是为了确保轴的位置正确,因为我必须使用旋转来正确放置这些圆柱体。顺便说一句,当我使用该算法时,输出向量也会失败,尽管以不同的方式,垂直于平面,但都指向+z而不是某些in-z)

    从render3ddocument.m:

    // Make the out-pointing vector
    C3DTCylinder  *outVectTube;
    C3DTEntity    *outVectEntity;
    Point3DFloat  *sideCtr = [thisSide centerOfMass];
    outVectTube = [C3DTCylinder cylinderWithBase: tubeRadius top: tubeRadius height: tubeRadius*10 slices: 16 stacks: 16];
    outVectEntity = [C3DTEntity entityWithStyle:triColor
                       geometry:outVectTube];
    Point3DFloat *outVect = [[thisSide inVect] opposite];
    Point3DFloat *unitZ = [Point3DFloat pointWithX:0 Y:0 Z:1.0f];
    Point3DFloat *rotAxis = [outVect crossWith:unitZ];
    double rotAngle = [outVect angleWith:unitZ];
    [outVectEntity setRotationX: rotAxis.x
                  Y: rotAxis.y
                  Z: rotAxis.z
                  W: rotAngle];
    [outVectEntity setTranslationX:sideCtr.x - ctrX  
                  Y:sideCtr.y - ctrY
                  Z:sideCtr.z - ctrZ];
    [aScene addChild:outVectEntity];
    

    (请注意,point3float基本上是一个向量类,一个边(如thisside)是一组四个point3float,每个顶点一个,指向外壳中心的向量一个)。

    来自c3dtentity.m:

    if (_hasTransform) {
        glPushMatrix();
    
        // Translation
        if ((_translation.x != 0.0) || (_translation.y != 0.0) || (_translation.z != 0.0)) {
            glTranslatef(_translation.x, _translation.y, _translation.z);
        }
    
        // Scaling
        if ((_scaling.x != 1.0) || (_scaling.y != 1.0) || (_scaling.z != 1.0)) {
            glScalef(_scaling.x, _scaling.y, _scaling.z);
        }
    
        // Rotation
        glTranslatef(-_rotationCenter.x, -_rotationCenter.y, -_rotationCenter.z);
    
        if (_rotation.w != 0.0) {
            glRotatef(_rotation.w, _rotation.x, _rotation.y, _rotation.z);
        } else {
            if (_rotation.x != 0.0)
                glRotatef(_rotation.x, 1.0f, 0.0f, 0.0f);
            if (_rotation.y != 0.0)
                glRotatef(_rotation.y, 0.0f, 1.0f, 0.0f);
            if (_rotation.z != 0.0)
                glRotatef(_rotation.z, 0.0f, 0.0f, 1.0f);
        }
    
        glTranslatef(_rotationCenter.x, _rotationCenter.y, _rotationCenter.z);
    }
    

    我在上面的代码中添加了一个位,它围绕一个轴使用一个旋转(if(_rotation.w!=0.0)“位),而不是一组三个旋转。我的代码可能是问题所在,但我不知道如何解决。

    2 回复  |  直到 14 年前
        1
  •  0
  •   sum1stolemyname    14 年前

    如果你的输出向量不是都指向正确的方向,你可能需要检查三角形的缠绕-它们都是以相同的方式定向的吗?

    此外,为每个outvec绘制一条线(使用三角形的三个顶点的平均值作为原点,并向outvect的方向绘制一条几单位长度的线(取决于场景的比例)。这样,您就可以确保所有向量的方向都是正确的。

    你如何计算你的输出向量?

        2
  •  0
  •   Dave Hirsch    14 年前

    问题似乎是glrotatef()需要度数,而我给了它弧度。另外,顺时针旋转被认为是正的,所以旋转的符号是错误的。这是正确的代码:

    double rottangle=-[outvect anglewith:unitz];/弧度
    [outvectentity setrotationx:旋转轴.x
    Y:轮叶菌Y
    Z:轮叶菌属
    W:旋转角度*180.0/m_pi];
    < /代码> 
    
    

    我现在可以看到我的另一个程序有错误的反演(下面的outvects是通过船体而不是从每个面都指出),我现在可以在另一个程序中跟踪那个bug…明天:

    格里斯和我给了它光辉。另外,顺时针旋转被认为是正的,所以旋转的符号是错误的。这是正确的代码:

    double rotAngle = -[outVect angleWith:unitZ];   // radians
    [outVectEntity setRotationX: rotAxis.x
                              Y: rotAxis.y
                              Z: rotAxis.z
                              W: rotAngle * 180.0 / M_PI ];
    

    我现在可以看到我的另一个程序有错误的反演(下面的outvects是通过船体而不是从每个面都指出),我现在可以在另一个程序中跟踪那个bug…明天: alt text