当前位置: 首页 > 知识库问答 >
问题:

OpenGL ES对象绕Z轴旋转

柳杰
2023-03-14

我的屏幕上有一个旋转和平移的对象,但是我有两个关于z轴旋转的问题。解释起来有点棘手,所以我上传了两个视频来描述每个问题。

1) 反向旋转:在绕x轴旋转对象后,z轴旋转将被反向,并且应该如此。

2)错误的Z轴旋转:同样,在围绕x轴旋转物体后,我试图围绕z轴旋转物体,旋转导致不同的轴旋转。

我相信视频很好地描述了这些问题。

编辑:更新#1

好的,我想我找到了解决方案,就是只绕Z轴旋转相机,然后对模型本身执行X和Y旋转。这似乎很好,但当然它导致了本视频中描述的一个新问题(发生在第23秒,剩下的是演示如何进行)。

发生这种情况的原因是对象的轴系统正在旋转,当我在进行Z轴旋转之后再进行X轴或Y轴旋转时,结果是错误的。

我只是不知道如何从轴系统单独旋转物体,这样旋转就会正确完成。

现在,对于代码部分:

渲染功能:

- (void)render:(CADisplayLink*)displayLink {
    ...

    CC3GLMatrix *projection = [CC3GLMatrix matrix];
    float h = 4.0f * self.frame.size.height / self.frame.size.width;
    [projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:100];
    glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);

    [modelView populateFromTranslation:_currentPan];
    [modelView rotateBy:_currentRotation];
    [modelView rotateByZ:zRotationEnd];

    glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
    ...        
}

X和Y旋转:

- (void) rotateAroundX:(float) x andY:(float) y newRotate:(BOOL) isNewRotate
{
    if (isNewRotate) {
        rotationStart = CC3VectorMake(0.0, 0.0, 0.0);
    }

    int rotationDirection = ceil(zRotationEnd/90);
    if (rotationDirection % 4 == 2 || rotationDirection % 4 == 3) {
        rotationEnd.x = rotationEnd.x - (x-rotationStart.x);
        rotationEnd.y = rotationEnd.y - (y-rotationStart.y);
    } else {
        rotationEnd.x = rotationEnd.x + (x-rotationStart.x);
        rotationEnd.y = rotationEnd.y + (y-rotationStart.y);
    }

    rotationStart.x = x;
    rotationStart.y = y;

    _currentRotation = CC3VectorMake(rotationEnd.y, rotationEnd.x, 0);
    NSLog(@"Current x is: %f y is: %f z is: %f",_currentRotation.x,_currentRotation.y,zRotationEnd);
}

以及相关的调用部分:

if(sender.numberOfTouches == 1)
    {
        BOOL started = false;
        CGPoint rotation = [sender translationInView:sender.view];
        float x = rotation.x;
        float y = rotation.y;
        if (sender.state == UIGestureRecognizerStateBegan)
        {
            started = true;
        }
        [self.glView rotateAroundX:x andY:y newRotate:started];
    }

Z旋转功能:

- (void) rotateAroundZ:(float) z newRotate:(BOOL) isNewRotate
{
    if (isNewRotate) {
        zRotationStart = 0;
    }
    zRotationEnd = zRotationEnd - (z - zRotationStart);
    zRotationStart = z;
}

以及相关的调用部分:

- (IBAction)rotation:(UIRotationGestureRecognizer *)sender {
    BOOL started = false;
    float rotation = RadiansToDegrees([sender rotation]);
    if (sender.state == UIGestureRecognizerStateBegan)
    {
        started = true;
    }
    [self.glView rotateAroundZ:rotation newRotate:started];
    NSLog(@"Rotation %f", rotation);
}

着色器:

attribute vec4 Position;
attribute vec4 SourceColor;

varying vec4 DestinationColor;

uniform mat4 Projection;
uniform mat4 Modelview;

attribute vec2 TexCoordIn;
varying vec2 TexCoordOut;

void main(void) {
    DestinationColor = SourceColor;
    gl_Position = Projection * Modelview * Position;
    TexCoordOut = TexCoordIn;
}

会非常感激任何帮助。

干杯

共有3个答案

颛孙成益
2023-03-14

你的错误来了,因为你同时围绕着x,y和z旋转。问题在于,当对象的模型矩阵为identity时,z轴旋转围绕对象定义的z轴。

解决这个问题的最简单方法是使用复合矩阵乘法。基本上,通过将矩阵相乘,可以指定执行操作的顺序。

在您的情况下,您希望像以前一样应用“x-y”动画。然后,您需要执行z轴旋转。

类似于以下内容:(我从来没有写过cocos3d代码,所以这是基于对文档的快速搜索,可能会有打字错误)。

CC3GLMatrix* rotationXY = [CC3GLMatrix identity];
[rotationXY rotateBy: _currentRotation];

CC3GLMatrix* rotationZ  = [CC3GLMatrix rotateByZ: zRotationEnd];

[rotationXY multiplyByMatrix: rotationZ];

这应该给你正确的模型矩阵。最后,您需要乘以您的视图(相机)矩阵:

[rotationXY multiplyByMatrix: view];
[CC3GLMatrix copyMatrix: rotationXY into: modelView];

你现在应该看到你期望的行为。

谷梁永年
2023-03-14

看起来您正在尝试实现一个万向节。

虽然您似乎只使用Cocos3D作为基本的数据数学结构,但请看看这篇文章,它描述了在Cocos3D中创建万向节,这可能有助于为您指明正确的方向。

使用与万向节结构相匹配的嵌套结构对象(Cocos3D中的CC3Node)创建万向节更容易实现,而不是尝试将连续旋转应用于单个矩阵。但是,通过一些算法分析和实验,您可能能够提取所得的矩阵数学并在单个矩阵上实现它。

记住,一个成功的万向节需要以正确的顺序进行旋转。

宋望
2023-03-14

简单的旋转。

这是基于触摸移动旋转对象的最简单方法。下面是一个例子

pseudocode:

Matrix.setIdentity(modelMatrix);

... do other translations here ...

Matrix.rotateX(totalYMovement);
Matrix.rotateY(totalXMovement);

这是做每一帧。

要向上或向下旋转物体,我们绕X轴旋转,要向左或向右旋转物体,我们绕Y轴旋转。如果我们想让一个物体旋转,我们也可以绕着Z轴旋转它。

这里有个教程

 类似资料:
  • 我是XNA的新手。我只是陷入了某种困境——我必须在游戏中倾斜/翻转角色,这意味着围绕X轴和Z轴旋转(不是同时旋转!)我可以做旋转-这意味着绕Y轴旋转。我有旋转矩阵,角色的当前位置向量(也是可以从旋转矩阵中获得的朝向/方向向量)我通过将朝向向量围绕Y轴旋转R弧度来实现旋转,即围绕Y轴旋转。比如说,如果我现在绕X轴旋转,那么方法是什么?例如,从站立姿势改为“超人飞行”姿势需要角色倾斜。。。y旋转不涉及

  • 我尝试绕全局y轴旋转对象(基本上,无论当前方向如何,都围绕0,1,0偏航)。我想给你看一张照片,但是声誉。。。我想绕全局轴而不是对象的局部轴旋转偏航。例如,如果我通过俯仰稍微倾斜一个长方体,然后尝试旋转偏航,它将以倾斜的角度而不是直线旋转长方体,就好像长方体根本没有倾斜一样。 每个对象将其位置和旋转存储在矩阵中,每个更新调用都会更新该矩阵。旋转的代码看起来是这样的: 其中,位置是每次更新都会平移和

  • 我想知道如何围绕它的Y轴旋转一个物体。 例如,我想旋转谷歌示例应用程序hello\u ar\u java的droid机器人https://github.com/google-ar/arcore-android-sdk/tree/master/samples/hello_ar_java围绕其Y轴,角度为alpha。

  • 我有一个球员(绿色),我想让他左右旋转。 这可以通过在其局部Y轴上旋转来轻松实现。然而,问题是播放器可能会沿其局部X轴旋转。这是一张草图: 以下是从顶部看到的视图: 我需要沿红线旋转播放器。我需要这样做,不管他现在在X轴上有什么旋转。(玩家像超人一样飞行,见第一张图片) 通过使用父对象可以很容易地解决此问题,但这在我当前的设置中是不可能的。我当前使用的代码在局部旋转时会出现奇怪的旋转: 如何在全局

  • 我试图旋转一个立方体,这样向下拖动总是绕着世界X轴旋转对象,而向一侧拖动总是绕着世界Y轴旋转对象,无论对象如何旋转。我看到了这个例子,它实现了我想要的准确行为:https://jsfiddle.net/MadLittleMods/n6u6asza/ 这是我遇到麻烦的jsFiddle代码:http://jsfiddle.net/9sqvp52u/ 我看到了这个stackoverflow答案:Open

  • 我正在创建一个外部欧拉角旋转的可视化,我想要一个立方体根据用户输入绕世界轴旋转的动画。我有一个dat。具有x、y和z旋转角度控件的GUI控件。看到这个截图。 到目前为止,我已经能够实现内部旋转,只需使用(和,)并设置多维数据集旋转。我的GUI代码看起来像这样: 当用户移动x旋转控件时,立方体将围绕其局部x轴旋转指定角度。然后,当用户移动y旋转控件时,已旋转的立方体将围绕其局部y轴旋转。 然而,我在