2014-06-28 47 views
5

我正在通过Ray Wenderlich的OpenGL for iOS教程尝试将其代码从Objective-C转换为Swift。当在Swift中调用glDrawElements但不在Objective-C中时OpenGL EXC_BAD_ACCESS

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

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

这段代码的斯威夫特版本:

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版本中,你会看到类VertexDataSource上的类方法的几个调用。从本质上讲,我无法决定如何将Objective-C的某些部分转换为swift,因此决定(现在)在Objective-C中创建一个小类,以便为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都会很棒。

EDIT#1

作为雷托Koradi指出的那样,上述参考文献的SWIFT代码self.positionSlot而两次不是使用colorSlot。这是我在发布代码时发生的一个错误,而不是我的代码中的错误。

所以问题依然存在。

更新斯威夫特:

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代码的最终版本,但您可以在此查看this example GitHub repo中的工作结果的完整源代码。

最终斯威夫特代码:

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) 

我要继续前进,接受雷托Koradi的答案,因为它确实让我在正确的轨道上。

+0

嗨,'let vertextBufferOffset:CConstVoidPointer = COpaquePointer(UnsafePointer (0)')似乎不再有效。你会碰巧知道其他的选择吗?提前致谢。 – Unheilig

+0

而不是那些长'convertFrom ...'函数,试试'GLboolean(GL_FALSE)' – Jarsen

+0

也'GLenum(GL_TRIANGLES)' – Jarsen

回答

1

我真的不知道的语言,但一个明显的区别是Objective-C的版本设置了两个不同的顶点属性,而斯威夫特版本设置相同的属性两次:

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

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

对于我来说,在第二个调用中传递的变量的地址是glVertexAttribPointer(),最后一个参数是glDrawElements()。但是,也许&运算符意味着Swift与我习惯的语言不同。

+0

您对positionSlot是正确的,但这是我在发布到SO时发生的错误,而不是实际在我的代码中发生的错误(所以这不能解决问题)。虽然好抓到:)。 – bradleygriffith

2

对于像我这样使用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

相关问题