How to use GLKMatrixStack in Objective-C? (GLKit)

时间:2022-04-24 05:47:42

I'm trying to port over some OpenGL code from an Android project to iOS. I've done a little bit of iOS programming before so i'm familiar with the syntax of Objective-C but I can't seem to figure out how these GLKMatrixStacks work. Here is some Java code that I am trying to port with an example of how I need to use the stack.

我正在尝试将一些OpenGL代码从Android项目移植到iOS。之前我已经完成了一些iOS编程,因此我熟悉Objective-C的语法,但我似乎无法弄清楚这些GLKMatrixStack是如何工作的。以下是我尝试移植的一些Java代码,其中包含了如何使用堆栈的示例。

public void drawLeftHip()
{
    float[] temp = new float[16];
    System.arraycopy(mModelMatrix, 0, temp, 0, mModelMatrix.length);
    stack.push(temp);

    //Global transformations here
    Matrix.translateM(mModelMatrix, 0, -1.0f, -.75f, 0.0f);
    Matrix.rotateM(mModelMatrix, 0, lThighAngle, 1.0f, 0.0f, 0.0f);  

    //draw children
    drawLeftThigh();

    //left hip
    Matrix.scaleM(mModelMatrix, 0, .25f, .25f, .25f);
    drawPackedTriangleBuffer(mSphereData, mSphereVertexCount, mModelMatrix, mColorBlack); //draw the triangle with the given model matrix

    mModelMatrix = stack.pop();
}

I basically make a copy of mModelMatrix (a 4x4 matrix) and push it on the stack, do my global transformations, draw children, do local transformations, and finally pop the stack.

我基本上制作了一个mModelMatrix(一个4x4矩阵)的副本并将其推入堆栈,进行全局转换,绘制子项,进行局部转换,最后弹出堆栈。

I've tried using a NSMutableArray for the purpose of a stack but I can't use it because I need to use GLKMatrix4 which is not if type (id).

我已经尝试使用NSMutableArray用于堆栈但我不能使用它,因为我需要使用GLKMatrix4,而不是类型(id)。

1 个解决方案

#1


3  

GLKMatrix4 represents a 4x4 matrix. It's just a union encapsulating a 16-element float array, so it's analogous to the float[16] array in your example. If you work with GLKBaseEffect you're already using these for your ModelView and Projection matrices. (If you're rolling your own shaders, using the GLKit matrix/vector types and corresponding math utilities is a good idea anyway, since they're optimized to provide good performance on iOS devices.)

GLKMatrix4代表4x4矩阵。它只是一个封装16个元素浮点数组的联合,所以它类似于你的例子中的float [16]数组。如果您使用GLKBaseEffect,那么您已经将它们用于ModelView和Projection矩阵。 (如果您正在滚动自己的着色器,那么使用GLKit矩阵/向量类型和相应的数学实用程序无论如何都是个好主意,因为它们经过优化可以在iOS设备上提供良好的性能。)

To follow the pattern of your example:

要遵循您的示例模式:

  1. Use GLKMatrixStackCreate to create a stack, then GLKMatrixStackLoad to copy your current ModelView matrix onto the stack. This function automatically copies the matrix so you don't need to create a copy yourself as in your example.

    使用GLKMatrixStackCreate创建堆栈,然后使用GLKMatrixStackLoad将当前的ModelView矩阵复制到堆栈中。此功能会自动复制矩阵,因此您无需像示例中那样自行创建副本。

  2. Use GLKMatrix4Translate, GLKMatrix4Rotate, etc to transform your ModelView matrix before drawing with it. (Don't forget to upload the changed matrices to your shader's uniform variables, or if using GLKBaseEffect update its transform property and tell it to prepareToDraw, before drawing.)

    使用GLKMatrix4Translate,GLKMatrix4Rotate等在绘制之前转换ModelView矩阵。 (不要忘记将更改的矩阵上传到着色器的统一变量,或者如果使用GLKBaseEffect更新其transform属性并在绘制之前告诉它prepareToDraw。)

  3. Finally, use one of the GLKMatrixStackGet functions to retrieve the saved matrix from the stack.

    最后,使用GLKMatrixStackGet函数之一从堆栈中检索保存的矩阵。

This pattern doesn't actually make use of the stack, though -- it just saves and loads a single matrix. You can extend the pattern by using GLMatrixStackPush to save additional matrices and GLKMatrixStackPop to restore to a prior state. (The pop function doesn't return the top matrix before disposing of it, so use a GLKMatrixStackGet function if you want to retrieve it first.) This pattern still doesn't make optimal use of the stack, though -- a better way is to keep all your matrix operations in the stack. Here's a quick (untested) example:

但是,这种模式实际上并没有使用堆栈 - 它只是保存并加载单个矩阵。您可以使用GLMatrixStackPush扩展模式以保存其他矩阵,并使用GLKMatrixStackPop恢复到先前状态。 (pop函数在处理它之前不会返回顶部矩阵,所以如果你想先检索它,请使用GLKMatrixStackGet函数。)这种模式仍然无法最佳地使用堆栈,但更好的方法是将所有矩阵运算保留在堆栈中。这是一个快速(未经测试)的例子:

// subclass of GLKViewController as in the "OpenGL Game" Xcode template
@implementation MyViewController
{
    GLKMatrixStack mvStack;
}

- (void)setupGL
{
    // ... other setup code ...

    // set up base transform
    mvStack = GLKMatrixStackCreate(NULL);
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // save the base transform
    GLKMatrixStackPush(mvStack);

    // additional transforms for figure
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    [self drawBody];

    // restore the base transform
    GLKMatrixStackPop(mvStack);
}

- (void)drawBody
{
    self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(mvStack);
    // ... draw body ...

    // save body transform 
    GLKMatrixStackPush(mvStack);

    // transform to left leg coordinate space
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    [self drawLeg];

    // restore to body coordinates
    GLKMatrixStackPop(mvStack);

    // transform to right leg coordinate space
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    [self drawLeg];

    // restore to body coordinates
    GLKMatrixStackPop(mvStack);
}

- (void)drawLeg
{
    self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(mvStack);
    // ... draw upper leg ...

    // save upper leg transform 
    GLKMatrixStackPush(mvStack);

    // transform to lower leg coordinate space
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(mvStack);
    // ... draw lower leg ...

    // restore to upper leg coordinates
    GLKMatrixStackPop(mvStack);
}

Read the documentation on GLKMatrixStack for more info.

阅读有关GLKMatrixStack的文档以获取更多信息。

#1


3  

GLKMatrix4 represents a 4x4 matrix. It's just a union encapsulating a 16-element float array, so it's analogous to the float[16] array in your example. If you work with GLKBaseEffect you're already using these for your ModelView and Projection matrices. (If you're rolling your own shaders, using the GLKit matrix/vector types and corresponding math utilities is a good idea anyway, since they're optimized to provide good performance on iOS devices.)

GLKMatrix4代表4x4矩阵。它只是一个封装16个元素浮点数组的联合,所以它类似于你的例子中的float [16]数组。如果您使用GLKBaseEffect,那么您已经将它们用于ModelView和Projection矩阵。 (如果您正在滚动自己的着色器,那么使用GLKit矩阵/向量类型和相应的数学实用程序无论如何都是个好主意,因为它们经过优化可以在iOS设备上提供良好的性能。)

To follow the pattern of your example:

要遵循您的示例模式:

  1. Use GLKMatrixStackCreate to create a stack, then GLKMatrixStackLoad to copy your current ModelView matrix onto the stack. This function automatically copies the matrix so you don't need to create a copy yourself as in your example.

    使用GLKMatrixStackCreate创建堆栈,然后使用GLKMatrixStackLoad将当前的ModelView矩阵复制到堆栈中。此功能会自动复制矩阵,因此您无需像示例中那样自行创建副本。

  2. Use GLKMatrix4Translate, GLKMatrix4Rotate, etc to transform your ModelView matrix before drawing with it. (Don't forget to upload the changed matrices to your shader's uniform variables, or if using GLKBaseEffect update its transform property and tell it to prepareToDraw, before drawing.)

    使用GLKMatrix4Translate,GLKMatrix4Rotate等在绘制之前转换ModelView矩阵。 (不要忘记将更改的矩阵上传到着色器的统一变量,或者如果使用GLKBaseEffect更新其transform属性并在绘制之前告诉它prepareToDraw。)

  3. Finally, use one of the GLKMatrixStackGet functions to retrieve the saved matrix from the stack.

    最后,使用GLKMatrixStackGet函数之一从堆栈中检索保存的矩阵。

This pattern doesn't actually make use of the stack, though -- it just saves and loads a single matrix. You can extend the pattern by using GLMatrixStackPush to save additional matrices and GLKMatrixStackPop to restore to a prior state. (The pop function doesn't return the top matrix before disposing of it, so use a GLKMatrixStackGet function if you want to retrieve it first.) This pattern still doesn't make optimal use of the stack, though -- a better way is to keep all your matrix operations in the stack. Here's a quick (untested) example:

但是,这种模式实际上并没有使用堆栈 - 它只是保存并加载单个矩阵。您可以使用GLMatrixStackPush扩展模式以保存其他矩阵,并使用GLKMatrixStackPop恢复到先前状态。 (pop函数在处理它之前不会返回顶部矩阵,所以如果你想先检索它,请使用GLKMatrixStackGet函数。)这种模式仍然无法最佳地使用堆栈,但更好的方法是将所有矩阵运算保留在堆栈中。这是一个快速(未经测试)的例子:

// subclass of GLKViewController as in the "OpenGL Game" Xcode template
@implementation MyViewController
{
    GLKMatrixStack mvStack;
}

- (void)setupGL
{
    // ... other setup code ...

    // set up base transform
    mvStack = GLKMatrixStackCreate(NULL);
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // save the base transform
    GLKMatrixStackPush(mvStack);

    // additional transforms for figure
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    [self drawBody];

    // restore the base transform
    GLKMatrixStackPop(mvStack);
}

- (void)drawBody
{
    self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(mvStack);
    // ... draw body ...

    // save body transform 
    GLKMatrixStackPush(mvStack);

    // transform to left leg coordinate space
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    [self drawLeg];

    // restore to body coordinates
    GLKMatrixStackPop(mvStack);

    // transform to right leg coordinate space
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    [self drawLeg];

    // restore to body coordinates
    GLKMatrixStackPop(mvStack);
}

- (void)drawLeg
{
    self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(mvStack);
    // ... draw upper leg ...

    // save upper leg transform 
    GLKMatrixStackPush(mvStack);

    // transform to lower leg coordinate space
    GLKMatrixStackTranslate(mvStack, /* ... coords ... */);
    GLKMatrixStackScale(mvStack, /* ... coords ... */);
    GLKMatrixStackRotate(mvStack, /* ... coords ... */);

    self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(mvStack);
    // ... draw lower leg ...

    // restore to upper leg coordinates
    GLKMatrixStackPop(mvStack);
}

Read the documentation on GLKMatrixStack for more info.

阅读有关GLKMatrixStack的文档以获取更多信息。