OpenGL ES对象绕Z轴旋转



我的屏幕上有一个对象,它是旋转和平移的,但是我有两个关于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;
}

非常感谢您的帮助。

干杯!

简单旋转。

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

pseudocode:
Matrix.setIdentity(modelMatrix);
... do other translations here ...
Matrix.rotateX(totalYMovement);
Matrix.rotateY(totalXMovement);

这是每帧都要做的。

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

这是教程

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

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

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

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

您的错误即将到来,因为您同时围绕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];

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

最新更新