2015-02-08 27 views
8

我正在嘗試使用SpriteKit的SKMutableTexture類,但我不知道如何使用UnsafeMutablePointer<Void>。我有一個模糊的想法,它是一個指向內存中連續字節數據的指針。但我如何更新它?這在代碼中實際上會是什麼樣子?什麼是UnsafeMutablePointer <Void>?如何修改底層內存?

編輯

下面是一個基本的代碼示例的工作。我怎樣才能做到這一點,就像在屏幕上創建紅色方塊一樣簡單?

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10)) 
    tex.modifyPixelDataWithBlock { (ptr:UnsafeMutablePointer<Void>, n:UInt) -> Void in 

     /* ??? */ 

    } 

回答

12

從文檔爲SKMutableTexture.modifyPixelDataWithBlock

紋理被假定字節將被存儲爲緊密包裝32 BPP,8bpc(無符號整數)RGBA像素數據。您提供的顏色成分應該已經乘以alpha值。

所以,雖然你給了void*,底層數據的形式是一個4x8位流。

你可以操縱這樣的結構,像這樣:

// struct of 4 bytes 
struct RGBA { 
    var r: UInt8 
    var g: UInt8 
    var b: UInt8 
    var a: UInt8 
} 

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10)) 
tex.modifyPixelDataWithBlock { voidptr, len in 
    // convert the void pointer into a pointer to your struct 
    let rgbaptr = UnsafeMutablePointer<RGBA>(voidptr) 

    // next, create a collection-like structure from that pointer 
    // (this second part isn’t necessary but can be nicer to work with) 
    // note the length you supply to create the buffer is the number of 
    // RGBA structs, so you need to convert the supplied length accordingly... 
    let pixels = UnsafeMutableBufferPointer(start: rgbaptr, count: Int(len/sizeof(RGBA)) 

    // now, you can manipulate the pixels buffer like any other mutable collection type 
    for i in indices(pixels) { 
     pixels[i].r = 0x00 
     pixels[i].g = 0xff 
     pixels[i].b = 0x00 
     pixels[i].a = 0x20 
    } 
} 
+0

剛剛在Xcode中嘗試過使用SpriteKit示例項目,似乎做了正確的事情 - 但我知道_nothing_關於SpriteKit,因此無法保證這是做到這一點的「方式」。 – 2015-02-08 20:42:43

+0

謝謝,這是工作。我現在在屏幕上看到了一個方塊,但我期待每幀調用一次modifyPixelDataWithBlock方法 - 就像片段着色器的一種替代方法,但塊只調用一次。更多挖掘... – Bret 2015-02-08 20:45:51

+0

請注意,您需要傳入RGB部分的預乘alpha值。從[文檔](https://developer.apple。com/library/ios/documentation/SpriteKit/Reference/SKMutableTexture_Ref /#// apple_ref/occ/instm/SKMutableTexture/modifyPixelDataWithBlock :)'假設紋理字節存儲爲緊密堆棧32 bpp,8bpc(無符號整數)RGBA像素數據。您提供的顏色成分應該已經乘以alpha值 – Benzi 2016-05-03 19:45:27

7

UnsafeMutablePointer<Void>是斯威夫特相當於void* - 一個指向任何東西。您可以訪問底層內存作爲其memory屬性。通常,如果您知道底層類型是什麼,那麼首先會強制指向該類型的指針。然後,您可以使用下標來訪問內存中的特定「插槽」。

例如,如果數據真的是UINT8值的序列,你可以說:

let buffer = UnsafeMutablePointer<UInt8>(ptr) 

您現在可以訪問個人UIInt8值buffer[0]buffer[1],等等。

+0

,看到我的雨燕教程的詳細信息:http://www.apeth.com/swiftBook/apa.html#_c_pointers – matt 2015-02-08 20:10:27

+0

通過該方法判斷[modifyPixelDataWithBlock]的簽名(https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKMutableTexture_Ref/index.html#//apple_ref/occ/instm/SKMutableTexture/modifyPixelDataWithBlock :),我認爲底層類型是一個8位整數。演員在代碼中看起來會是什麼樣子?我真的很希望得到一些代碼示例如何做到這一點 – Bret 2015-02-08 20:12:05

+0

如果它是一個8位整數,那將是一個Int8或UInt8。因此,如果您投射到不安全的可變指數或UnsafeMutablePointer (無論哪一個),都可以使用下標來逐個獲取單個字節。 – matt 2015-02-08 20:14:43

相關問題