2014-06-28 4 views
5

Ich arbeite über das OpenGL for iOS Tutorial von Ray Wenderlich in dem Versuch, seinen Code von Objective-C nach Swift zu konvertieren.OpenGL EXC_BAD_ACCESS beim Aufruf von glDrawElements in Swift, aber nicht in Objective-C

Ich bin sehr neu zu OpenGL und zu Swift und glaube, dass mein Problem damit zu tun hat, wie ich das Objective-C übersetzt habe. Hier ist warum:

In meiner schnellen Datei zum Einrichten meiner Ansicht, die OpenGL-Inhalt enthält, stürzt die App im letzten logischen Schritt (Aufruf von glDrawElements) mit einer EXC_BAD_ACCESS-Warnung ab. Wenn ich jedoch diesen Teil des Codes in eine Objective-C-Datei verschiebe, funktioniert die App wie erwartet.

Swift-Version dieser Code:

var positionDataOffset: Int = 0 
glVertexAttribPointer(self.positionSlot, 3 as GLint, GL_FLOAT.asUnsigned(), 
    GLboolean.convertFromIntegerLiteral(UInt8(GL_FALSE)), 
    VertexDataSource.sizeOfVertex(), &positionDataOffset) 

var colorDataOffset = (sizeof(Float) * 3) as AnyObject 
glVertexAttribPointer(self.positionSlot, 4 as GLint, GL_FLOAT.asUnsigned(), 
    GLboolean.convertFromIntegerLiteral(UInt8(GL_FALSE)), 
    VertexDataSource.sizeOfVertex(), VertexDataSource.vertexBufferOffset()) 

var vertexOffset: Int = 0 
glDrawElements(GL_TRIANGLES.asUnsigned(), VertexDataSource.vertexCount(), 
    GL_UNSIGNED_BYTE.asUnsigned(), &vertexOffset) 

Und hier ist die Objective-C-Version:

glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
glVertexAttribPointer(color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 
    (GLvoid*) (sizeof(float) * 3)); 

glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0); 

Wie Sie sehen können, die Swift ist viel ausführlicher ... Ich bin neu dazu wie alle anderen auch. :)

Noch eine Anmerkung: In der Swift-Version werden mehrere Aufrufe von Klassenmethoden in der Klasse VertexDataSource angezeigt. Im Wesentlichen konnte ich nicht für das Leben von mir bestimmen, wie einige Teile des Objective-C in swift umgewandelt werden, so dass (FOR NOW) eine kleine Klasse in Objective-C erstellt wurde, die den Swift-Code mit diesen Attributen versehen könnte. Hier sind die Methoden in Objective-C:

+ (GLint)sizeOfVertex { 
    return sizeof(Vertex); 
} 

+ (GLint)sizeOfIndices { 
    return sizeof(Indices); 
} 

+ (GLint)sizeOfIndicesAtPositionZero { 
    return sizeof(Indices[0]); 
} 

+ (GLint)sizeOfVertices { 
    return sizeof(Vertices); 
} 

+ (GLvoid *)vertexBufferOffset { 
    return (GLvoid *)(sizeof(float) * 3); 
} 

+ (GLint)vertexCount { 
    return self.sizeOfIndices/sizeof(GLubyte); 
} 

Jegliche Hilfe, diese Zeilen zu Swift zu übersetzen wäre erstaunlich.

EDIT # 1

Wie Reto Koradi wies darauf hin, self.positionSlot der Swift-Code über Referenzen zweimal anstatt die colorSlot verwenden. Das war ein Fehler, den ich gemacht habe, als ich den Code hier postete und nicht wirklich einen Fehler in meinem Code.

Also das Problem besteht immer noch.

Aktualisiert Swift:

var positionDataOffset: Int = 0 
glVertexAttribPointer(self.positionSlot, 3 as GLint, GL_FLOAT.asUnsigned(), 
    GLboolean.convertFromIntegerLiteral(UInt8(GL_FALSE)), 
    VertexDataSource.sizeOfVertex(), &positionDataOffset) 
var colorDataOffset = (sizeof(Float) * 3) as AnyObject 
glVertexAttribPointer(self.colorSlot, 4 as GLint, GL_FLOAT.asUnsigned(), 
    GLboolean.convertFromIntegerLiteral(UInt8(GL_FALSE)), 
    VertexDataSource.sizeOfVertex(), VertexDataSource.vertexBufferOffset()) 

var vertexOffset: Int = 0 
glDrawElements(GL_TRIANGLES.asUnsigned(), VertexDataSource.vertexCount(), 
    GL_UNSIGNED_BYTE.asUnsigned(), &vertexOffset) 

EDIT # 2: Gelöst

landete ich diese Lösung. Das Problem in meinem Fall war, dass meine Konvertierung von Objective-C nach Swift in mehreren Fällen falsch war. Der Kürze halber werde ich die endgültige Version des Swift-Codes für den Teil veröffentlichen, über den ich ursprünglich besorgt war, aber Sie können den vollständigen Quellcode des Arbeitsergebnisses hier in this example GitHub repo ansehen.

Der letzte Swift Code:

let positionSlotFirstComponent: CConstVoidPointer = COpaquePointer(UnsafePointer<Int>(0)) 
glVertexAttribPointer(self.positionSlot, 3 as GLint, GL_FLOAT.asUnsigned(), 
    GLboolean.convertFromIntegerLiteral(UInt8(GL_FALSE)), Int32(sizeof(Vertex)), 
    positionSlotFirstComponent) 
let colorSlotFirstComponent: CConstVoidPointer = COpaquePointer(UnsafePointer<Int>(sizeof(Float) * 3)) 
glVertexAttribPointer(self.colorSlot, 4 as GLint, GL_FLOAT.asUnsigned(), 
    GLboolean.convertFromIntegerLiteral(UInt8(GL_FALSE)), Int32(sizeof(Vertex)), 
    colorSlotFirstComponent) 


let vertextBufferOffset: CConstVoidPointer = COpaquePointer(UnsafePointer<Int>(0)) 
glDrawElements(GL_TRIANGLES.asUnsigned(), Int32(GLfloat(sizeofValue(Indices))/
    GLfloat(sizeofValue(Indices.0))), GL_UNSIGNED_BYTE.asUnsigned(), vertextBufferOffset) 

Ich werde weitermachen und Reto Koradi Antwort zu akzeptieren, wie es mir sicherlich auf dem richtigen Weg bekam.

+0

Hallo, 'lassen vertextBufferOffset: CConstVoidPointer = COpaquePointer (UnsafePointer (0)') scheint nicht mehr zu funktionieren. Würdest du zufällig andere Alternativen kennen? Danke im Voraus. – Unheilig

+0

anstelle dieser langen 'convertFrom ...' Funktionen, versuche nur 'GLboolean (GL_FALSE)' – Jarsen

+0

auch 'GLenum (GL_TRIANGLES)' – Jarsen

Antwort

1

Ich weiß nicht wirklich die Sprache, sondern ein offensichtlicher Unterschied ist, dass die Objective-C-Version richtet zwei verschiedene Vertex-Attribut, während die Swift-Version zweimal das gleiche Attribut aufstellt:

glVertexAttribPointer(self.positionSlot, 3 as GLint, GL_FLOAT.asUnsigned(), ...) 
glVertexAttribPointer(self.positionSlot, 4 as GLint, GL_FLOAT.asUnsigned(), ...) 

Die Das erste Argument, das den Standort des Attributs bestimmt, ist in beiden Fällen gleich.

Es sieht auch irgendwie seltsam für mich aus, dass Sie übergeben, was wie die letzte Adresse von einer Variable als das letzte Argument von glVertexAttribPointer() im zweiten Aufruf aussieht, und als letztes Argument von glDrawElements(). Aber vielleicht bedeutet der Operator & etwas anderes in Swift als in den Sprachen, die ich gewohnt bin.

+0

Sie haben über positionSlot Recht, aber das war ein Fehler, den ich gemacht habe, als ich auf SO postete und kein Fehler, der tatsächlich in meinem Code ist (damit löst sich das Problem nicht). Guter Fang aber :). – bradleygriffith

2

Für Leute, die swift 2.1.1 mit Xcode 7.2 wie mir verwenden, hat sich die Pointer-Syntax geändert. Hier ist ein Beispiel, wie man es benutzt.

https://github.com/asymptotik/asymptotik-rnd-scenekit-kaleidoscope/blob/master/Atk_Rnd_VisualToys/ScreenTextureQuad.swift

Verwandte Code ist unten angegeben:

// bind VBOs for vertex array and index array 
// for vertex coordinates 

let ptr = UnsafePointer<GLfloat>(bitPattern: 0) 

glBindBuffer(GLenum(GL_ARRAY_BUFFER), self.vertexBufferObject) 

glEnableVertexAttribArray(self.positionIndex) 
glVertexAttribPointer(self.positionIndex, GLint(3), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(sizeof(GLfloat) * 8), ptr) 
glEnableVertexAttribArray(self.textureCoordinateIndex) 
glVertexAttribPointer(self.textureCoordinateIndex, GLint(2), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(sizeof(GLfloat) * 8), ptr.advancedBy(6)) 

Hoffnung, das hilft. Ich reparierte auch OPs Beispiel Github-Projekt in meiner Gabel hier: https://github.com/zwang/iOSSwiftOpenGL

Verwandte Themen