Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS上Swift中的自定义SceneKit几何体不起作用,但等效的目标C代码起作用_Ios_Objective C_Xcode_Swift_Scenekit - Fatal编程技术网

iOS上Swift中的自定义SceneKit几何体不起作用,但等效的目标C代码起作用

iOS上Swift中的自定义SceneKit几何体不起作用,但等效的目标C代码起作用,ios,objective-c,xcode,swift,scenekit,Ios,Objective C,Xcode,Swift,Scenekit,我渴望采用新的Swift语言,因为这似乎是苹果发展的方向。iOS 8中新的SceneKit支持也给我留下了深刻的印象。我希望在运行时以编程方式创建自定义几何体,但我正在努力使Swift代码正常工作。然而,Objective C中的等效代码工作正常 这可能是一个错误,或者我做错了什么 我只是尝试创建和渲染一个三角形。为了简单起见,我将忽略法线和纹理等。所以我只希望看到一个黑色三角形 Swift代码(不工作) 目标C代码(该代码有效) 任何指针都将不胜感激。好吧,这两段代码不能准确地相互转换。C中的

我渴望采用新的Swift语言,因为这似乎是苹果发展的方向。iOS 8中新的SceneKit支持也给我留下了深刻的印象。我希望在运行时以编程方式创建自定义几何体,但我正在努力使Swift代码正常工作。然而,Objective C中的等效代码工作正常

这可能是一个错误,或者我做错了什么

我只是尝试创建和渲染一个三角形。为了简单起见,我将忽略法线和纹理等。所以我只希望看到一个黑色三角形

Swift代码(不工作)

目标C代码(该代码有效)


任何指针都将不胜感激。

好吧,这两段代码不能准确地相互转换。C中的
int
与Swift中的
int
不同。在Swift中,它实际上被称为
CInt

/// The C 'int' type.
typealias CInt = Int32
如果您将这两个事件都更改为使用
CInt
,则您以前收到的错误消息将消失(至少对我在OS X游乐场中是这样)。但是,它仍然不会为我呈现任何内容

我不认为
sizeofValue
用于返回数组的大小。在我看来,它似乎在返回指针的大小:

let indexes: CInt[] = [0, 1, 2]
sizeofValue(indexes)                   // is 8
sizeof(CInt)                           // is 4
sizeof(CInt) * countElements(indexes)  // is 12

// compare to other CInt[]
let empty: CInt[] = []
let large: CInt[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

sizeofValue(indexes)                   // is 8 (your array of indices again)
sizeofValue(empty)                     // is 8
sizeofValue(large)                     // is 8
因此,对我来说,以下代码是有效的(我将参数放在不同的行上,以便更容易指出我的更改):

因此:


我对swift了解不多,但我希望您的“verts”和“INDEX”版本在swift和ObjC(实际上是C)中完全不同

在你的C版本中,你会得到一个C结构的C数组。在swift中,我假设你会得到一个swift“数组”(相当于NSArray)的SCNVector3,它被包装到NSValues中。因此,你用“索引”字节构建的NSData不会像C中那样包含浮点值的平面缓冲区。对于“verts”数组也是如此


看起来这里讨论了这样的C和swift互操作性问题:

David的回答很好,但要呈现一个更完整的画面

  • Swift结构数组像C结构数组一样将其数据打包在一起,而不是由NSValue包装的结构的ObjC
    NSArray
    。因此,从Swift数组构造NSData是完全酷的

  • 结构的/structs数组也是如此,只要它们最终都是标量类型

  • 即使在ObjC中,生成一个
    SCInvector3
    数组也会有问题,因为该结构的元素类型在32/64位体系结构之间发生变化

  • sizeOfValue
    对于Beta 2中的阵列来说似乎没有达到预期的效果,所以我建议使用它

  • 如果在自定义结构中实现了
    ArrayTerralConvertible
    协议,则可以简洁地声明嵌套结构值的数组

如果您意识到这些问题,您可以在Swift中使用(Obj)C中使用的顶点/索引缓冲区管理的大部分相同技巧,但也有一些变化。例如,下面是一个片段,它使用交错的顶点和法线数据构建自定义几何体(这有利于iOS设备GPU的性能):

struct Float3:arraylteralconvertible{
typealias元素=GLfloat
变量x,y,z:GLfloat
init(阵列并行元素:元素…){
self.x=元素[0]
self.y=元素[1]
self.z=元素[2]
}
}
结构顶点:ArrayTerralConvertible{
typealias元素=Float3
var位置,正常:浮动3
init(阵列并行元素:元素…){
self.position=元素[0]
self.normal=元素[1]
}
}
//这必须是一个var,而不是let,因为它被传递给CMutablePointer
变量顶点:顶点[]=[
[ [+0.5, -0.5, -0.5],      [+1.0, +0.0, +0.0] ],
[ [+0.5, +0.5, -0.5],      [+1.0, +0.0, +0.0] ],
//…这里有更多的顶点!
]
let data=NSData(字节:顶点,长度:顶点。计数*大小(顶点))
设vertexSource=SCNGeometrySource(数据:数据,
语义:SCNGeometrySourceSemanticVertex,
vectorCount:vertices.count,
对,,
成分研究者:3,
bytesPerComponent:sizeof(GLfloat),
数据偏移量:0,
数据列:sizeof(顶点))
设normalSource=SCNGeometrySource(数据:数据,
语义:scngemetrysourcesemanticnormal,
vectorCount:vertices.count,
对,,
成分研究者:3,
bytesPerComponent:sizeof(GLfloat),
//Swift中没有offsetof(),但顶点在法线之前有一个Float3
数据偏移量:sizeof(Float3),
数据列:sizeof(顶点))
//使用Swift范围快速构造顺序索引缓冲区

让indexData=NSData(字节:数组(0..Swift代码以何种方式不起作用?不编译?运行时错误?抱歉,没有编译或运行时错误。它只是没有像Objective cHi David那样呈现黑色的脸,感谢“Swift”的响应。你是绝对正确的,奇怪的是,我曾经使用CShort并将NSData长度硬编码为6。但即使是帽子现在似乎起作用了。我想我可能已经把唯一的灯光从泛光灯改成了环境灯,但没有用。嘿,大卫,我发布了一个有趣的问题(带着赏金)关于顶点和ARKit。你介意看一下吗?我们似乎找不到解决方案。iOS 8 beta 3中的sizeofvalue已经固定。而且数组语法和语义也发生了一些变化——当我有时间检查代码时,我会更新这个答案。对于
let element=SCNGeometryElement(数据:indexData,…
,如果索引数据只是[0,1,2,3,4等],你可以说
let element=SCNGeometryElement(数据:nil,…
。我不得不假设
bytesPerIndex
在这种用法中被忽略。@rickster但是你怎么做才能使I
/// The C 'int' type.
typealias CInt = Int32
let indexes: CInt[] = [0, 1, 2]
sizeofValue(indexes)                   // is 8
sizeof(CInt)                           // is 4
sizeof(CInt) * countElements(indexes)  // is 12

// compare to other CInt[]
let empty: CInt[] = []
let large: CInt[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

sizeofValue(indexes)                   // is 8 (your array of indices again)
sizeofValue(empty)                     // is 8
sizeofValue(large)                     // is 8
let src = SCNGeometrySource(vertices: &verts, count: 3)
let indexes: CInt[] = [0, 1, 2] // Changed to CInt

let dat  = NSData(
    bytes: indexes,
    length: sizeof(CInt) * countElements(indexes) // Changed to size of CInt * count
)
let ele = SCNGeometryElement(
    data: dat,
    primitiveType: .Triangles,
    primitiveCount: 1,
    bytesPerIndex: sizeof(CInt) // Changed to CInt
)
let geo = SCNGeometry(sources: [src], elements: [ele])

let nd = SCNNode(geometry: geo)
scene.rootNode.addChildNode(nd)
struct Float3 : ArrayLiteralConvertible {
    typealias Element = GLfloat
    var x, y, z: GLfloat
    init(arrayLiteral elements: Element...) {
        self.x = elements[0]
        self.y = elements[1]
        self.z = elements[2]
    }
}

struct Vertex: ArrayLiteralConvertible {
    typealias Element = Float3
    var position, normal: Float3
    init(arrayLiteral elements: Element...) {
        self.position = elements[0]
        self.normal = elements[1]
    }
}

// This must be a var, not a let, because it gets passed to a CMutablePointer
var vertices: Vertex[] = [
    [ [+0.5, -0.5, -0.5],      [+1.0, +0.0, +0.0] ],
    [ [+0.5, +0.5, -0.5],      [+1.0, +0.0, +0.0] ],
    // ... lots more vertices here!
]

let data = NSData(bytes: vertices, length: vertices.count * sizeof(Vertex))

let vertexSource = SCNGeometrySource(data: data,
               semantic: SCNGeometrySourceSemanticVertex,
            vectorCount: vertices.count,
        floatComponents: true,
    componentsPerVector: 3,
      bytesPerComponent: sizeof(GLfloat),
             dataOffset: 0,
             dataStride: sizeof(Vertex))

let normalSource = SCNGeometrySource(data: data,
               semantic: SCNGeometrySourceSemanticNormal,
            vectorCount: vertices.count,
        floatComponents: true,
    componentsPerVector: 3,
      bytesPerComponent: sizeof(GLfloat),
// no offsetof() in Swift, but Vertex has one Float3 before normal
             dataOffset: sizeof(Float3), 
             dataStride: sizeof(Vertex))

// use a Swift Range to quickly construct a sequential index buffer
let indexData = NSData(bytes: Array<UInt8>(0..<UInt8(vertices.count)), 
             length: vertices.count * sizeof(UInt8))

let element = SCNGeometryElement(data: indexData, 
              primitiveType: .Triangles, 
             primitiveCount: vertices.count / 3,
              bytesPerIndex: sizeof(UInt8))

let cube = SCNGeometry(sources: [vertexSource, normalSource], elements: [element])