swift - How to build data for a SCNGeometrySource in Swift
问题描述
I try to build a SCNGeometrySource in swift.
I want to use the SCNGeometrySource(data: Data, semantic: SCNGeometrySource.Semantic, vectorCount: Int, usesFloatComponents: Bool, componentsPerVector: Int, bytesPerComponent: Int, dataOffset: Int, dataStride: Int)
initializer, because I have already a buffer giving vertex position, normal and colors - or at least, I can build it.
But how do I transform my buffer into a Data type (for the data parameter) ?
Using Data(bytesNoCopy: buffer as! UnsafeMutableRawPointer ...)
gives me a warning that the cast will fail (and I believed it).
I have also tried with no success to use Data.append(xxx)
functions, but there is no way I could find to just cast the address of my larger buffer into an UnsafePointer of any kind (and it also implies an additional copy of the large buffer).
So what's the way ?
Edit: the "large buffer" is a concatenation of
struct VertexInfo {
var x: Float
var y: Float
var z: Float
var nx: Float
var ny: Float
var nz: Float
var a: Float
var r: Float
var g: Float
var b: Float
}
I can provide it under any type, but for the time being, I build it with a UnsafeMutableBufferPointer<VertexInfo>
解决方案
这就是我解决问题的方法:我使用 anUnsafeMutableRawPointer
直接使用分配“大缓冲区”malloc()
并构建Data
使用Data(bytesNoCopy:length:freeWhenDone:)
,这并不意味着数据的另一个副本。
现在,为了填充“大缓冲区”,我使用了 aUnsafeMutablePointer<VertexInfo>
来简化操作,但秘诀是使用bindMemory(to:capacity:)
.
这样, UnsafeMutableRawPointer 和 UnsafeMutablePointer 实际指向同一个缓冲区。UnsafeMutablePointer 可用于轻松地用数据填充缓冲区,UnsafeMutableRawPointer 可轻松用于创建数据。
// Assuming VertexInfo type holds the information for a vertex
// Assuming we have vectorMaxCount as the number of vertices we want
// Compute the size of the buffer to allocate
var size = vectorMaxCount * MemoryLayout<VertexInfo>.stride
// Allocate the buffer as a UnsafeMutableRawPointer
var buffer = malloc(size)
// Create a UnsafeMutablePointer<VertexInfo> that points to the allocated buffer
var vertexList = buffer!.bindMemory(to: VertexInfo.self, capacity: vectorMaxCount)
// Fill the buffer with the needed data
for index in 0..< vectorMaxCount {
let vertex = // Compute here your vertex info as a VertexInfo
// Easily fill the buffer thanks to the UnsafeMutablePointer<VertexInfo>
vertexList[index] = vertex
}
// Create the Data thanks to the UnsafeMutableRawPointer
let data = NSData(bytesNoCopy: buffer, length: size, freeWhenDone: true) as Data
请注意,缓冲区的所有权是通过参数赋予数据的freeWhenDone: true
。
这是非常通用的,可用于构建任何压缩的数据缓冲区,不仅适用于 SceneKit。
推荐阅读
- java - 在 OjAlgo 的 Primitive64Store 中的特定列和行处插入 Access2D 元素
- html - Fullcalendar 一半时间GridWeek 像一天一样查看GridWeek
- python - 如何在 Python 中打印字符串中的内容?
- python - 如何在python中导出虚拟环境设置
- mysql - MYSQL UPDATE 表上 INSERT 到同一个表
- angular - 在 Typescript 项目之间共享接口
- django - 为什么我们首先在 Django 表单中使用实例作为第二个参数而不是现有数据库条目
- node.js - 如何从 express +Node.js 中的 url 获取 {{id}}
- java - java.lang 的正式规范在哪里?
- c - 如何扫描文本文件并将字符输入到数组中?