2014-06-28 14 views
5

Tôi đang làm việc qua hướng dẫn OpenGL for iOS của Ray Wenderlich trong một nỗ lực để chuyển đổi mã của mình từ Objective-C sang Swift.OpenGL EXC_BAD_ACCESS khi gọi glDrawElements trong Swift nhưng không phải trong Objective-C

Tôi rất mới đối với OpenGL và Swift và tin rằng vấn đề của tôi liên quan đến cách tôi đã dịch Mục tiêu-C. Dưới đây là lý do:

Trong tệp nhanh chóng của tôi để thiết lập chế độ xem có chứa nội dung OpenGL, trên bước logic cuối cùng (gọi glDrawElements), ứng dụng sẽ gặp sự cố với cảnh báo EXC_BAD_ACCESS. Nếu, tuy nhiên, tôi di chuyển phần mã này vào một tệp Mục tiêu-C, ứng dụng hoạt động như mong đợi.

phiên bản Swift của mã này:

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) 

Và đây là phiên bả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); 

Như bạn có thể thấy, Swift là nhiều hơn nữa tiết ... Tôi mới với điều này giống như mọi người khác. :)

Một lưu ý khác: Trong phiên bản Swift, bạn sẽ thấy một số cuộc gọi đến các phương thức lớp trên lớp VertexDataSource. Về cơ bản, tôi không thể cho cuộc sống của tôi xác định làm thế nào để chuyển đổi một số phần của Objective-C sang nhanh chóng, vì vậy quyết định (FOR NOW) tạo một lớp nhỏ trong Objective-C có thể cung cấp mã Swift với các thuộc tính đó. Dưới đây là các phương pháp trong Mục tiêu-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); 
} 

Bất kỳ trợ giúp nào chuyển những dòng này sang Swift sẽ thật tuyệt vời.

EDIT # 1

Như Reto Koradi chỉ ra, các mã Swift trên tài liệu tham khảo self.positionSlot hai lần thay vì sử dụng colorSlot. Đây là một sai lầm tôi đã thực hiện khi đăng mã ở đây và không thực sự là một sai lầm trong mã của tôi.

Vì vậy, vấn đề vẫn tồn tại.

Cập nhật 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: Solved

tôi đã kết thúc giải quyết này. Vấn đề trong trường hợp của tôi là việc chuyển đổi Objective-C thành Swift không chính xác trong một vài trường hợp. Đối với ngắn gọn, tôi sẽ đăng phiên bản cuối cùng của mã Swift cho phần tôi đã quan tâm ban đầu, nhưng bạn có thể xem mã nguồn đầy đủ của kết quả làm việc tại đây trong this example GitHub repo.

Mã Swift thức:

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) 

Tôi sẽ đi trước và chấp nhận câu trả lời Reto Koradi, như chắc chắn nó đã cho tôi đi đúng hướng.

+0

Xin chào, 'let vertextBufferOffset: CConstVoidPointer = COpaquePointer (UnsafePointer (0)') dường như không hoạt động nữa. Bạn có muốn biết bất kỳ lựa chọn thay thế nào khác không? Cảm ơn trước. – Unheilig

+0

thay vì các hàm 'convertFrom ...' dài này, hãy thử chỉ 'GLboolean (GL_FALSE)' – Jarsen

+0

cũng 'GLenum (GL_TRIANGLES)' – Jarsen

Trả lời

1

tôi không thực sự biết những ngôn ngữ, nhưng có một sự khác biệt rõ ràng là phiên bản Objective-C lập hai đỉnh khác nhau thuộc tính, trong khi phiên bản Swift thiết lập các thuộc tính tương tự hai lần:

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

Các đối số đầu tiên, xác định vị trí thuộc tính, là giống nhau trong cả hai trường hợp.

Nó cũng có vẻ kỳ lạ với tôi khi bạn chuyển những gì trông giống như địa chỉ của một biến làm đối số cuối cùng của số glVertexAttribPointer() trong cuộc gọi thứ hai và làm đối số cuối cùng của glDrawElements(). Nhưng có lẽ toán tử & có nghĩa là một cái gì đó khác trong Swift so với các ngôn ngữ tôi thường sử dụng.

+0

Bạn chính xác về vị tríSlot, nhưng đây là một sai lầm mà tôi đã thực hiện khi đăng lên SO và không phải là một sai lầm thực sự trong mã của tôi (vì vậy điều này không giải quyết được vấn đề). Tốt bắt mặc dù :). – bradleygriffith

2

Đối với những người đang sử dụng nhanh 2.1.1 với Xcode 7.2 như tôi, cú pháp con trỏ đã thay đổi. Đây là một ví dụ về cách sử dụng nó.

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

đang liên quan được trích dẫn dưới đây:

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

Hope this helps. Tôi cũng đã sửa dự án github ví dụ của OP trong ngã ba của tôi ở đây: https://github.com/zwang/iOSSwiftOpenGL

Các vấn đề liên quan