0

Objective-C は C のスーパーセットであり、2 つの間で簡単に変更できるため、通常は配列を持つ関数を C で渡します。行列計算を行う関数に GLfloats (はい、OpenGL を使用しています) の配列を渡す特定の関数を Objective-C で書きたかったのです。私はこれをやってみました:

- (void)setIdentity:(GLfloat *)target
{
    target[0] = 1;
    target[1] = 0;
    target[2] = 0;
    target[3] = 0;
    target[4] = 0;
    target[5] = 1;
    target[6] = 0;
    target[7] = 0;
    target[8] = 0;
    target[9] = 0;
    target[10] = 1;
    target[11] = 0;
    target[12] = 0;
    target[13] = 0;
    target[14] = 0;
    target[15] = 1;
}

そして、これを使用して、行列を 16 エントリの長さの GLfloat 配列として関数に渡そうとしました。

[matrix setIdentity:ModelMat];
//Log the result
NSLog(@"ModelMat:\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f", 
      ModelMat[0], ModelMat[1], ModelMat[2], ModelMat[3], ModelMat[4], ModelMat[5], 
      ModelMat[6], ModelMat[7], ModelMat[8], ModelMat[9], ModelMat[10], ModelMat[11],
      ModelMat[12], ModelMat[13], ModelMat[14], ModelMat[15]);

適切な値を返していることを確認するためだけに、出力は単に 0 のマトリックスでした。ここで何が間違っていますか?

  • 編集

他の人が私の問題をよりよく理解できるようにするために、ID を設定しようとしている Scene クラスと ID を持つ Matrix クラスのソース コードを追加し、さらに多くのマトリックス関連アイテムを追加します。

Matrix.h

@interface Matrix : NSObject

- (void)copyMatrix:(GLfloat *)from to:(GLfloat *)to;
- (void)setIdentity:(GLfloat *)target;
- (void)multiplyMatrix:(GLfloat *)second by:(GLfloat *)first giving:(GLfloat *)newMatrix;
- (void)applyTranslation:(GLfloat *)source x:(GLfloat)x y:(GLfloat)y z:(GLfloat)z;
- (void)applyScale:(GLfloat *)source x:(GLfloat)x y:(GLfloat)y z:(GLfloat)z;
- (void)applyRotation:(GLfloat *)source pitch:(GLfloat)pitch yaw:(GLfloat)yaw roll:(GLfloat)roll;
- (void)applyRotationWithMag:(GLfloat *)source angle:(GLfloat)angle magX:(GLfloat)magX magY:(GLfloat)magY magZ:(GLfloat)magZ
- (void)setProjection:(GLfloat *)source fov:(GLfloat)fov aspect:(GLfloat)aspect near:(GLfloat)near far:(GLfloat)far;

@end

Matrix.m

#import "Matrix.h"

#define PI 3.1415926535897932384626433832795f

@implementation Matrix

- (void)copyMatrix:(GLfloat *)from to:(GLfloat *)to
{
    for(int i = 0; i < 16; i++)
        from[i] = to[i];
}

- (void)setIdentity:(GLfloat *)target
{
    target[0] = 1;
    target[1] = 0;
    target[2] = 0;
    target[3] = 0;
    target[4] = 0;
    target[5] = 1;
    target[6] = 0;
    target[7] = 0;
    target[8] = 0;
    target[9] = 0;
    target[10] = 1;
    target[11] = 0;
    target[12] = 0;
    target[13] = 0;
    target[14] = 0;
    target[15] = 1;
}

- (void)multiplyMatrix:(GLfloat *)second by:(GLfloat *)first giving:(GLfloat *)newMatrix
{
    GLfloat tempMatrix[16];

    //Column 1
    tempMatrix[0] = (second[0] * first[0]) +
                            (second[4] * first[1]) +
                            (second[8] * first[2]) +
                            (second[12] * first[3]);

    tempMatrix[1] = (second[1] * first[0]) +
                            (second[5] * first[1]) +
                            (second[9] * first[2]) +
                            (second[13] * first[3]);

    tempMatrix[2] = (second[2] * first[0]) +
                            (second[6] * first[1]) +
                            (second[10] * first[2]) +
                            (second[14] * first[3]);

    tempMatrix[3] = (second[3] * first[0]) +
                            (second[7] * first[1]) +
                            (second[11] * first[2]) +
                            (second[15] * first[3]);

    //Column 2
    tempMatrix[4] = (second[0] * first[4]) +
                            (second[4] * first[5]) +
                            (second[8] * first[6]) +
                            (second[12] * first[7]);

    tempMatrix[5] = (second[1] * first[4]) +
                            (second[5] * first[5]) +
                            (second[9] * first[6]) +
                            (second[13] * first[7]);

    tempMatrix[6] = (second[2] * first[4]) +
                            (second[6] * first[5]) +
                            (second[10] * first[6]) +
                            (second[14] * first[7]);

    tempMatrix[7] = (second[3] * first[4]) +
                            (second[7] * first[5]) +
                            (second[11] * first[6]) +
                            (second[15] * first[7]);

    //Column 3
    tempMatrix[8] = (second[0] * first[8]) +
                            (second[4] * first[9]) +
                            (second[8] * first[10]) +
                            (second[12] * first[11]);

    tempMatrix[9] = (second[1] * first[8]) +
                            (second[5] * first[9]) +
                            (second[9] * first[10]) +
                            (second[13] * first[11]);

    tempMatrix[10] = (second[2] * first[8]) +
                             (second[6] * first[9]) +
                             (second[10] * first[10]) +
                             (second[14] * first[11]);

    tempMatrix[11] = (second[3] * first[8]) +
                             (second[7] * first[9]) +
                             (second[11] * first[10]) +
                             (second[15] * first[11]);

    //Column 4
    tempMatrix[12] = (second[0] * first[12]) +
                             (second[4] * first[13]) +
                             (second[8] * first[14]) +
                             (second[12] * first[15]);

    tempMatrix[13] = (second[1] * first[12]) +
                             (second[5] * first[13]) +
                             (second[9] * first[14]) +
                             (second[13] * first[15]);

    tempMatrix[14] = (second[2] * first[12]) +
                             (second[6] * first[13]) +
                             (second[10] * first[14]) +
                             (second[14] * first[15]);

    tempMatrix[15] = (second[3] * first[12]) +
                             (second[7] * first[13]) +
                             (second[11] * first[14]) +
                             (second[15] * first[15]);

    [self copyMatrix:tempMatrix to:newMatrix];
}

- (void)applyTranslation:(GLfloat *)source x:(GLfloat)x y:(GLfloat)y z:(GLfloat)z
{
    GLfloat tempMatrix[16];

    [self setIdentity:tempMatrix];

    tempMatrix[12] = x;
    tempMatrix[13] = y;
    tempMatrix[14] = z;

    [self multiplyMatrix:tempMatrix by:source giving:source];

}

- (void)applyScale:(GLfloat *)source x:(GLfloat)x y:(GLfloat)y z:(GLfloat)z
{
    GLfloat tempMatrix[16];

    [self setIdentity:tempMatrix];

    tempMatrix[0] = x;
    tempMatrix[5] = y;
    tempMatrix[10] = z;

    [self multiplyMatrix:tempMatrix by:source giving:source];
}

- (void)applyRotation:(GLfloat *)source pitch:(GLfloat)pitch yaw:(GLfloat)yaw roll:(GLfloat)roll
{
    GLfloat tempMatrix[16];

    if (pitch != 0) {
        GLfloat c = cosf(pitch);
        GLfloat s = sinf(pitch);

        [self setIdentity:tempMatrix];

        tempMatrix[5] = c;
        tempMatrix[6] = -s;
        tempMatrix[9] = s;
        tempMatrix[10] = c;

        [self multiplyMatrix:tempMatrix by:source giving:source];
    }

    if (yaw != 0) {
        GLfloat c = cosf(yaw);
        GLfloat s = sinf(yaw);

        [self setIdentity:tempMatrix];

        tempMatrix[0] = c;
        tempMatrix[2] = s;
        tempMatrix[8] = -s;
        tempMatrix[10] = c;

        [self multiplyMatrix:tempMatrix by:source giving:source];
    }

    if (roll != 0) {
        GLfloat c = cosf(roll);
        GLfloat s = sinf(roll);

        [self setIdentity:tempMatrix];

        tempMatrix[0] = c;
        tempMatrix[1] = -s;
        tempMatrix[4] = s;
        tempMatrix[5] = c;

        [self multiplyMatrix:tempMatrix by:source giving:source];
    }
}

- (void)applyRotationWithMag:(GLfloat *)source angle:(GLfloat)angle magX:(GLfloat)magX magY:(GLfloat)magY magZ:(GLfloat)magZ
{
    GLfloat tempMatrix[16];

    GLfloat sinAngle, cosAngle;
    GLfloat magnitude;

    magnitude = sqrtf((magX * magX) + (magY * magY) + (magZ * magZ));

    sinAngle = sinf(angle * PI / 180.0f);
    cosAngle = cosf(angle * PI / 180.0f);

    if (magnitude > 0) {
        GLfloat xx, yy, zz, xy, xz, yz, xs, ys, zs;
        GLfloat oneMinusCos;

        magX /= magnitude;
        magY /= magnitude;
        magZ /= magnitude;

        xx = magX * magX;
        yy = magY * magY;
        zz = magZ * magZ;
        xy = magX * magY;
        xz = magX * magZ;
        yz = magY * magZ;
        xs = magX * sinAngle;
        ys = magY * sinAngle;
        zs = magZ * sinAngle;

        oneMinusCos = 1 - cosAngle;

        tempMatrix[0] = (oneMinusCos * xx) + cosAngle;
        tempMatrix[1] = (oneMinusCos * xy) - zs;
        tempMatrix[2] = (oneMinusCos * xz) + ys;
        tempMatrix[3] = 0;

        tempMatrix[4] = (oneMinusCos * xy) + zs;
        tempMatrix[5] = (oneMinusCos * yy) + cosAngle;
        tempMatrix[6] = (oneMinusCos * yz) - xs;
        tempMatrix[7] = 0;

        tempMatrix[8] = (oneMinusCos * xz) - ys;
        tempMatrix[9] = (oneMinusCos * yz) + xs;
        tempMatrix[10] = (oneMinusCos * zz) + cosAngle;
        tempMatrix[11] = 0;

        tempMatrix[12] = 0;
        tempMatrix[13] = 0;
        tempMatrix[14] = 0;
        tempMatrix[15] = 1;

        [self multiplyMatrix:tempMatrix by:source giving:source];

    }
}

- (void)setProjection:(GLfloat *)source fov:(GLfloat)fov aspect:(GLfloat)aspect near:(GLfloat)near far:(GLfloat)far
{
    GLfloat tempMatrix[16];

    [self setIdentity:tempMatrix];

    GLfloat r = fov * M_PI / 180.0f;
    GLfloat f = 1.0f / tanf(r / 2.0f);

    tempMatrix[0] = f;
    tempMatrix[5] = f / aspect;
    tempMatrix[10] = -(far + near) / (far - near);
    tempMatrix[11] = -1;
    tempMatrix[14] = -(2 * far * near) / (far - near);
    tempMatrix[15] = 0;

    [self multiplyMatrix:tempMatrix by:source giving:source];
}

@end

Scene.h

#import "Shader.h"
#import "Matrix.h"

@class Texture;

@interface Scene : NSObject {

    Texture *texture;
    GLuint textureName;

    float animationPhase;
    BOOL didShowInfo;
    BOOL wireframe;

    GLuint vaoID[1];
    GLuint vboID[2];
    GLuint programHandle;
    GLuint shaderHandle[2];
    GLuint ProjectionMatrixHandle, ViewMatrixHandle, ModelMatrixHandle;
    GLfloat PerspectiveMat[16], ViewMat[16], ModelMat[16];
    GLfloat updateValue;

    Matrix *matrix;

    Shader *shader;
}

- (id)init;

- (void)setViewportRect:(NSRect)bounds;
- (void)render;

- (void)advanceTimeBy:(float)seconds;
- (void)setAnimationPhase:(float)newAnimationPhase;

- (void)toggleWireframe;

@end

Scene.m (Apple フルスクリーン デモのコードを使用)

#import "Scene.h"

static double dtor( double degrees )
{
    return degrees * M_PI / 180.0;
}

@implementation Scene

- (id) init
{
    self = [super init];
    if (self) {
        wireframe = NO;
        didShowInfo = NO;

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);

        glDisable(GL_CULL_FACE);

        glFrontFace(GL_CW);

        GLfloat verts[32] =
        {
            -0.5, -0.5, -1.0, 1.0, 1.0f, 1.0f, 1.0f, 1.0f,
            -0.5, 0.5, -1.0, 1.0, 1.0f, 1.0f, 1.0f, 1.0f,
            0.5, 0.5, -1.0, 1.0, 1.0f, 1.0f, 1.0f, 1.0f,
            0.5, -0.5, -1.0, 1.0, 1.0f, 1.0f, 1.0f, 1.0f
        };

        GLfloat indices[6] =
        {
            0, 1, 2,
            0, 2, 3
        };

        [matrix setIdentity:ModelMat];
        [matrix setIdentity:ViewMat];

        NSLog(@"ModelMat:\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f", ModelMat[0], ModelMat[1], ModelMat[2], ModelMat[3], ModelMat[4], ModelMat[5], ModelMat[6], ModelMat[7], ModelMat[8], ModelMat[9], ModelMat[10], ModelMat[11], ModelMat[12], ModelMat[13], ModelMat[14], ModelMat[15]);

        [matrix applyTranslation:ViewMat x:0 y:0 z:-2];

        NSLog(@"ViewMat:\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f", ViewMat[0], ViewMat[1], ViewMat[2], ViewMat[3], ViewMat[4], ViewMat[5], ViewMat[6], ViewMat[7], ViewMat[8], ViewMat[9], ViewMat[10], ViewMat[11], ViewMat[12], ViewMat[13], ViewMat[14], ViewMat[15]);

        programHandle = glCreateProgram();

        shaderHandle[0] = [shader compileShader:@"shader.vert" ofType:GL_VERTEX_SHADER];
        shaderHandle[1] = [shader compileShader:@"shader.frag" ofType:GL_FRAGMENT_SHADER];
        glAttachShader(programHandle, shaderHandle[0]);
        glAttachShader(programHandle, shaderHandle[1]);

        glLinkProgram(programHandle);

        ModelMatrixHandle = glGetUniformLocation(programHandle, "ModelMatrix");
        ViewMatrixHandle = glGetUniformLocation(programHandle, "ViewMatrix");
        ProjectionMatrixHandle = glGetUniformLocation(programHandle, "ProjectionMatrix");

        glGenVertexArrays(1, &vaoID[0]);
        glBindVertexArray(vaoID[0]);

        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        glGenBuffers(2, &vboID[0]);

        glBindBuffer(GL_ARRAY_BUFFER, vboID[0]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

        glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, sizeof(verts[0]), 0);
        glVertexAttribPointer((GLuint)1, 4, GL_FLOAT, GL_FALSE, sizeof(verts[0]), (GLvoid*)4);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[1]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        glBindVertexArray(0);

    } 
    return self;
}

- (void)dealloc
{
    [texture release];
    [super dealloc];
}

- (void)advanceTimeBy:(float)seconds
{
    float phaseDelta = seconds - floor(seconds);
    float newAnimationPhase = animationPhase + 0.015625 * phaseDelta;
    newAnimationPhase = newAnimationPhase - floor(newAnimationPhase);
    [self setAnimationPhase:newAnimationPhase];
}

- (void)setAnimationPhase:(float)newAnimationPhase
{
    animationPhase = newAnimationPhase;
}

- (void)toggleWireframe
{
    wireframe = !wireframe;
}

- (void)setViewportRect:(NSRect)bounds
{
    [matrix setIdentity:PerspectiveMat];

    glViewport(0, 0, bounds.size.width, bounds.size.height);

    [matrix setProjection:PerspectiveMat fov:60
                   aspect:(GLfloat)bounds.size.width / (GLfloat)bounds.size.height
                     near:1.0f far:100.0f];
}


- (void)render
{

    updateValue += 0.015;

    if (updateValue > 1)
        updateValue = 0;

    glClearColor(updateValue, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(programHandle);

    glUniformMatrix4fv(ModelMatrixHandle, 1, GL_FALSE, ModelMat);
    glUniformMatrix4fv(ViewMatrixHandle, 1, GL_FALSE, ViewMat);
    glUniformMatrix4fv(ProjectionMatrixHandle, 1, GL_FALSE, PerspectiveMat);

    glBindVertexArray(vaoID[0]);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (GLvoid*)0);
    glBindVertexArray(0);

    glUseProgram(0);
}

@end
4

2 に答える 2

1

Matrixどこにもインスタンスを作成していません。では、次のように-[Scene init]のインスタンスを作成する行を追加する必要があります。Matrix

    ...
    GLfloat indices[6] =
    {
        0, 1, 2,
        0, 2, 3
    };

    // Add the following line
    matrix = [[Matrix alloc] init];

    [matrix setIdentity:ModelMat];
    [matrix setIdentity:ViewMat];
    ...

これで問題は解決しますが、率直に言って、Matrixインスタンス メソッドはすべてクラス メソッドに変換できます。クラスMatrixにはインスタンス変数がなく、メソッドはスタンドアロン関数に似ています。Matrixそうすれば、オブジェクトを追跡する必要はまったくありません。

于 2013-08-16T18:04:14.997 に答える
0

コメントに次のように記述します。

明確にさせてください。ModelMat は、呼び出されたファイルのヘッダーに作成されます。次のように単純に作成されます。GLfloat ModelMat[16];

それは配列ModelMatを作成し、直接使用できる値の型です。ただし、次のように続けます。GLFloat

行列部分は、恒等関数を保持する私の Matrix クラスへの単なるポインタです。ヘッダーにも作成します。行列 *行列; どちらもヘッダー インターフェイスで作成されます

上記と同様に変数 が作成されますが、その型は参照型です。参照型の変数を作成してもオブジェクトは作成され、そのオブジェクトへの参照が変数に格納されます。使用する前に、次のようなステートメントを使用してオブジェクトを作成する必要があります。matrixMatrix *matrix

matrix = [Matrix new];

配列の受け渡しに関しては、C とまったく同じように行うことができます。関数/メソッドへの参照によって渡されることを思い出してください。HTH。

于 2013-08-16T18:13:53.647 に答える