OpenGL ES对象绕Z轴旋转

3
我在屏幕上有一个物体,它被旋转和平移呈现, 但是关于z轴旋转有两个问题。这有点棘手,所以我上传了两个视频以描述每个问题。
1) 反向旋转: 绕x轴旋转物体后,z轴旋转会反向旋转,如应该一样。
2) 错误的Z轴旋转: 同样,在绕x轴旋转物体后,我试图绕z轴旋转物体,结果旋转成不同的轴旋转。
我确信视频很好地描述了问题。
编辑: 更新 #1

好的,我认为我找到了解决方案,就是只围绕Z轴旋转相机,并对模型本身执行X和Y旋转。这似乎很好,但当然它导致了一个新问题,如VIDEO所述(在第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个回答

3

简单旋转。

这是根据触摸移动旋转对象的最简单方法。以下是示例:

pseudocode:

Matrix.setIdentity(modelMatrix);

... do other translations here ...

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

这是每帧都要执行的操作。

要使物体向上或向下旋转,我们将其围绕X轴旋转;要使物体向左或向右旋转,我们将其围绕Y轴旋转。如果我们希望物体旋转,则可以将其围绕Z轴旋转。

这里有一个教程


1
你的错误是因为你同时绕x、y和z旋转。问题在于,当模型矩阵为单位矩阵时,你的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];

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


1

看起来你正在尝试实现一个gimbal

虽然你似乎只使用Cocos3D进行基本数据数学结构,但是请查看this post,其中描述了如何在Cocos3D中创建一个万向节,并且可能会帮助你指明正确的方向。

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

请记住,成功的万向节需要按正确顺序执行旋转。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接