OpenGL EXC_BAD_ACCESS在Swift中调用glDrawElements时,不在Objective-C中调用

我正在通过Ray Wenderlich的OpenGL for iOS教程试图将他的代码从Objective-C转换为Swift。

我对OpenGL和Swift很陌生,相信我的问题与我如何翻译Objective-C有关。 原因如下:

在我的swift文件中设置我的视图,包含OpenGL内容,在最后的逻辑步骤(调用glDrawElements),应用程序将崩溃,EXC_BAD_ACCESS警报。 但是,如果我将这部分代码移到Objective-C文件中 ,则应用程序按预期工作。

这个代码的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.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) 

这里是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); 

正如你所看到的,Swift更加冗长…我和其他人一样,都是新手。 🙂

另一个注意事项:在Swift版本中,你会看到几个对类VertexDataSource类方法的VertexDataSource 。 从本质上说,我不能确定如何将Objective-C的某些部分转换为swift,所以决定(现在)在Objective-C中创build一个小类,以便为Swift代码提供这些属性。 以下是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); } 

任何帮助将这些行转换为Swift将是惊人的。

编辑#1

正如Reto Koradi所指出的,上面的Swift代码引用了self.positionSlot两次,而不是使用colorSlot。 这是我在发布代码时发生的一个错误,而不是代码中的错误。

所以问题依然存在。

更新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) 

编辑#2:解决

我最终解决了这个问题。 在我的情况下,问题是我的Objective-C到Swift的转换在一些情况下是不正确的。 为了简洁起见,我将发布我最初关注的部分的Swift代码的最终版本,但您可以在此示例GitHub库中查看完整的源代码。

最后的Swift代码:

 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) 

我会继续接受Reto Koradi的回答,因为这肯定让我走上正轨。

我并不了解这些语言,但是一个明显的区别是,Objective-C版本设置了两个不同的顶点属性,而Swift版本设置了两次相同的属性:

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

确定属性位置的第一个参数在两种情况下都是相同的。

对于我来说,在第二次调用中传递glVertexAttribPointer()的最后一个variables的参数,并将其作为glDrawElements()的最后一个parameter passing给variables的地址也是很奇怪的。 但是也许&运算符在Swift中的含义与我以前使用的语言不同。

对于像我这样使用Xcode 7.2的swift 2.1.1的人来说,指针的语法已经改变了。 这里是一个关于如何使用它的例子。

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

相关代码引用如下:

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

希望这可以帮助。 我也在这里修改了OP的例子github项目: https : //github.com/zwang/iOSSwiftOpenGL