OpenGL EXC_BAD_ACCESS al llamar a glDrawElements en Swift pero no en Objective-C

Estoy trabajando en el tutorial OpenGL for iOS de Ray Wenderlich en un bash de convertir su código de Objective-C a Swift.

Soy muy nuevo en OpenGL y Swift y creo que mi problema tiene que ver con cómo traduje Objective-C. Este es el por qué:

En mi file rápido para configurar mi vista que contiene contenido OpenGL, en el último paso lógico (llamando glDrawElements), la aplicación se bloqueará con una alerta EXC_BAD_ACCESS. Sin embargo, si muevo esta parte del código a un file Objective-C , la aplicación funcionará como se esperaba.

Versión rápida de este código:

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) 

Y aquí está la versión 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); 

Como puede ver, el Swift es mucho más detallado … Soy nuevo en esto como todos los demás. 🙂

Otra nota: en la versión Swift, verás varias llamadas a methods de class en la class VertexDataSource . Básicamente, no pude por su vida determinar cómo convertir algunas partes de Objective-C a Swift, por lo que decidí crear una class pequeña en Objective-C que podría proporcionar el código Swift con esos attributes. Estos son los methods en 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); } 

Cualquier ayuda para traducir esas líneas a Swift sería increíble.

EDITAR # 1

Como señaló Reto Koradi, el código Swift de arriba hace reference a self.positionSlot dos veces en lugar de usar el colorSlot. Este fue un error que cometí al publicar el código aquí y no en realidad un error en mi código.

Entonces, el problema aún existe.

Swift actualizado:

 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) 

EDITAR # 2: resuelto

Terminé resolviendo esto. El problema en mi caso fue que mi conversión de Objective-C a Swift fue incorrecta en varios casos. Por razones de brevedad, publicaré la versión final del código Swift para la parte en la que originalmente estaba interesado, pero puede ver el código fuente completo del resultado operativo aquí en este ejemplo del repository GitHub .

El código Swift final:

 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) 

Voy a seguir adelante y aceptar la respuesta de Reto Koradi, ya que ciertamente me llevó por el buen path.

No conozco realmente los idiomas, pero una diferencia obvia es que la versión Objective-C establece dos attributes de vértices diferentes, mientras que la versión Swift configura el mismo atributo dos veces:

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

El primer argumento, que determina la location del atributo, es el mismo en ambos casos.

También me parece un poco extraño que estés pasando lo que parece ser la dirección de una variable como el último argumento de glVertexAttribPointer() en la segunda llamada, y como el último argumento de glDrawElements() . Pero tal vez el operador & significa algo diferente en Swift que en los idiomas a los que estoy acostumbrado.

Para las personas que usan swift 2.1.1 con Xcode 7.2 como yo, la syntax del puntero ha cambiado. Aquí hay un ejemplo sobre cómo usarlo.

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

El código relacionado se cita a continuación:

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

Espero que esto ayude. También reparé el proyecto de ejemplo de OP de github en mi tenedor aquí: https://github.com/zwang/iOSSwiftOpenGL