2013-08-16 51 views
0

由於Objective-C是C的超集,所以我通常會傳遞C中具有數組的數組,因爲Objective-C是C的超集,可以很容易地在兩者之間進行切換。我想在Objective-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的矩陣。我在這裏做錯了什麼?

  • 編輯

爲了更好地幫助別人明白我的問題,我加入了,我想設置的身份和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(使用來自蘋果的全屏演示一些代碼)

#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 
+0

是的,我知道有一個更簡單的方法來記錄它,我很急 – SonarSoundProgramming

+1

告訴我們'ModelMat'的聲明。 –

+2

你確定'矩陣'是一個實例嗎?由於您可以在Objective-C中將消息發送到'nil',您的呼叫可能未被執行。 – Macmade

回答

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對象。

+0

但現在我遇到了同樣的問題,因爲當我的矩陣功能作爲全局函數。我收到一個鏈接器錯誤,說 「_OBJC_CLASS _ $ _ Matrix」,引用來自: – SonarSoundProgramming

+0

Nevermind,我清理了項目,它工作。謝謝您的幫助 – SonarSoundProgramming

0

在評論你寫:

讓我澄清一下。 ModelMat被創建在它被調用的文件頭部。它是這樣創建的:GLfloat ModelMat [16];

但這建立一個數組ModelMat和作爲GLFloat類型它可直接使用。然而,你繼續:

矩陣部分只是一個指向我的矩陣類的指針,它持有身份函數。我也在標題中創建它。矩陣*矩陣;它們都在插頭接口

創建雖然這創建可變matrix,與上述類似,它的類型Matrix *參考類型。創建參考類型的變量而不是也會創建一個對象並將該對象的引用存儲在該變量中。使用matrix之前,你必須創建一個對象,使用如下語句:

matrix = [Matrix new]; 

至於傳遞數組,你可以做到這一點恰好與C - 記住他們是參照到函數/方法通過。 HTH。