2014-06-28 9 views
5

Sto lavorando attraverso il tutorial OpenGL for iOS di Ray Wenderlich nel tentativo di convertire il suo codice da Objective-C a Swift.OpenGL EXC_BAD_ACCESS quando si chiama glDrawElements in Swift ma non in Objective-C

Sono molto nuovo a OpenGL e a Swift e credo che il mio problema abbia a che fare con il modo in cui ho tradotto l'Objective-C. Ecco perché:

Nel mio file rapido per impostare la mia vista che contiene contenuto OpenGL, sul passo logico finale (chiamando glDrawElements) l'applicazione si bloccherà con un avviso EXC_BAD_ACCESS. Se, tuttavia, sposto questa parte del codice in un file Objective-C, l'app funziona come previsto.

versione Swift di questo codice:

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) 

Ed ecco la versione Objective-C:

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); 

Come si può vedere, la Swift è molto più verboso ... Sono nuovo a questo come tutti gli altri. :)

Un'altra nota: nella versione Swift, vedrete diverse chiamate ai metodi di classe sulla classe VertexDataSource. Essenzialmente, non potevo per la vita di me determinare come convertire alcune parti dell'Obiettivo-C in modo rapido, così ho deciso di (PER ORA) creare una piccola classe in Objective-C che potesse fornire il codice Swift con quegli attributi. Ecco quei metodi 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); 
} 

Qualsiasi aiuto nella traduzione di queste righe in Swift sarebbe sorprendente.

EDIT # 1

Come Reto Koradi ha sottolineato, il codice Swift sopra riferimenti self.positionSlot due volte, piuttosto che utilizzare il colorSlot. Questo è stato un errore che ho fatto durante la pubblicazione del codice qui e non in realtà un errore nel mio codice.

Quindi il problema esiste ancora.

Aggiornato 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: Risolto

ho finito per la soluzione di questo. Il problema nel mio caso era che la mia conversione da Objective-C a Swift era errata in molti casi. Per brevità pubblicherò la versione finale del codice Swift per la parte di cui ero originariamente interessato, ma è possibile visualizzare il codice sorgente completo del risultato di lavoro qui in this example GitHub repo.

Il codice Swift finale:

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) 

ho intenzione di andare avanti e accettare la risposta di Reto Koradi, come certamente mi ha fatto sulla strada giusta.

+0

Ciao, 'let vertextBufferOffset: CConstVoidPointer = COpaquePointer (UnsafePointer (0)') non sembra funzionare più. Ti piacerebbe conoscere altre alternative? Grazie in anticipo. – Unheilig

+0

invece di quelle lunghe funzioni 'convertFrom ...', prova solo 'GLboolean (GL_FALSE)' – Jarsen

+0

anche 'GLenum (GL_TRIANGLES)' – Jarsen

risposta

1

io non so davvero le lingue, ma una differenza evidente è che la versione Objective-C imposta due attributi diversi vertici, mentre la versione Swift imposta lo stesso attributo due volte:

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

Il il primo argomento, che determina la posizione dell'attributo, è lo stesso in entrambi i casi.

Sembra anche strano per me passare l'aspetto di una variabile come ultimo argomento di glVertexAttribPointer() nella seconda chiamata e come ultimo argomento di glDrawElements(). Ma forse l'operatore & significa qualcosa di diverso in Swift rispetto alle lingue a cui sono abituato.

+0

Sei corretto su positionSlot, ma questo è stato un errore che ho fatto durante la pubblicazione in SO e non un errore che è effettivamente nel mio codice (quindi questo non risolve il problema). Buona cattura però :). – bradleygriffith

2

Per chi utilizza la versione 2.1.1 con Xcode 7.2 come me, la sintassi del puntatore è cambiata. Ecco un esempio su come usarlo.

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

codice relativo è citato qui di seguito:

// 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)) 

Spero che questo aiuti. Ho anche risolto il progetto github di OP nel mio fork qui: https://github.com/zwang/iOSSwiftOpenGL

Problemi correlati