Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.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
Swift 如何在代码中创建SceneKit SCNSkinner对象?_Swift_Xcode_Ios8_Scenekit - Fatal编程技术网

Swift 如何在代码中创建SceneKit SCNSkinner对象?

Swift 如何在代码中创建SceneKit SCNSkinner对象?,swift,xcode,ios8,scenekit,Swift,Xcode,Ios8,Scenekit,我有一个使用SceneKit的iOS 8 Swift应用程序。我从包含由骨架控制的网格的.dae文件加载场景。 在运行时,我需要修改纹理坐标。使用变换不是一个选项——我需要为网格中的每个顶点计算一个不同的、全新的UV 我知道几何体在SceneKit中是不可变的,我读到建议的方法是手动复制。我正试图这样做,但当我试图在代码中重新创建SCNSkinner时,总是会失败。崩溃是C3DSourceAccessorGetMutableValuePtrAtIndex内部的EXC\u坏访问。不幸的是,没有这方

我有一个使用SceneKit的iOS 8 Swift应用程序。我从包含由骨架控制的网格的.dae文件加载场景。 在运行时,我需要修改纹理坐标。使用变换不是一个选项——我需要为网格中的每个顶点计算一个不同的、全新的UV

我知道几何体在SceneKit中是不可变的,我读到建议的方法是手动复制。我正试图这样做,但当我试图在代码中重新创建
SCNSkinner
时,总是会失败。崩溃是
C3DSourceAccessorGetMutableValuePtrAtIndex
内部的
EXC\u坏访问。不幸的是,没有这方面的源代码,所以我不知道为什么它会崩溃。我已经将其缩小到附加到网格节点的
SCNSkinner
对象。如果我没有设置,我就不会崩溃,事情似乎正在运行

编辑:以下是更完整的崩溃调用堆栈:

C3DSourceAccessorGetMutableValuePtrAtIndex
C3DSkinPrepareMeshForGPUIfNeeded
C3DSkinnerMakeCurrentMesh
C3DSkinnerUpdateCurrentMesh
__CFSetApplyFunction_block_invoke
CFBasicHashApply
CFSetApplyFunction
C3DAppleEngineRenderScene
...
我还没有找到任何关于如何手动创建
SCNSkinner
对象的文档或示例代码。因为我只是基于以前的工作网格创建它,所以应该不会太难。我正在根据Swift文档创建
SCNSkinner
,将所有正确的内容传递到init中。但是,
SCNSkinner
中有一个骨架属性,我不知道如何设置。我将其设置为我复制的网格的原始
SCNSkinner
上的骨架,我认为 应该有用。。。但事实并非如此。设置骨架特性时,该特性似乎未指定。在赋值后立即检查它,它仍然为零。作为测试,我尝试将原始网格的骨架属性设置为其他属性,在指定之后,它也保持不变

有人能解释发生了什么事吗?或者如何正确地手动创建和设置
SCNSkinner
对象

下面是我用来手动克隆网格并替换为新网格的代码(我没有修改这里的任何源数据——我只是想确保此时可以创建一个副本):


这三种方法可以帮助您找到解决方案:

  • 我也看到了


  • 我不知道是什么导致代码崩溃,但这里有一种生成网格、骨骼和蒙皮网格的方法——所有这些都来自代码。Swift4和iOS 12

    在该示例中,有一个网格表示两个圆柱体的连接,其中一个圆柱体以45度角分叉,如下所示:

     \
     |
    
    圆柱体只是拉伸的三角形,即,
    radialSegmentCount=3。
    (请注意,有12个顶点,而不是9个,因为两个圆柱体并非真正连接在一起。三角形的顺序如下:

          v5
          ^
    v3 /__|__\ v1
       |  |  |
       |  v4 |
    v2 |/___\| v0
    
    有3块骨头,对应于圆柱体的头和脚,中间的骨头对应于底部圆柱体的头,同时对应于顶部圆柱体的脚。例如,顶点
    v0
    v2
    ,和
    v4
    对应于
    bone0
    v1
    v3
    v5
    对应于
    bone1
    ,依此类推。这就解释了
    boneIndicates
    (见下文)为什么具有它所具有的值

    骨骼的静止位置对应于几何体中圆柱体的静止位置(
    bone2
    bone1
    呈45度角延伸,就像圆柱体几何体一样)

    将此作为上下文,以下代码将创建几何体蒙皮所需的所有内容:

    let vertices = [float3(0.17841241, 0.0, 0.0), float3(0.17841241, 1.0, 0.0), float3(-0.089206174, 0.0, 0.1545097), float3(-0.089206174, 1.0, 0.1545097), float3(-0.089206256, 0.0, -0.15450965), float3(-0.089206256, 1.0, -0.15450965), float3(0.12615661, 1.1261566, 0.0), float3(-0.58094996, 1.8332633, 0.0), float3(-0.063078284, 0.9369217, 0.1545097), float3(-0.7701849, 1.6440284, 0.1545097), float3(-0.063078344, 0.93692166, -0.15450965), float3(-0.77018493, 1.6440284, -0.15450965)]
    let indices: [UInt8] = [0, 1, 2, 3, 4, 5, 0, 1, 1, 6, 6, 7, 8, 9, 10, 11, 6, 7]
    let geometrySource = SCNGeometrySource(vertices: vertices.map { SCNVector3($0) })
    let geometryElement = SCNGeometryElement(indices: indices, primitiveType: .triangleStrip)
    let geometry = SCNGeometry(sources: [geometrySource], elements: [geometryElement])
    
    let bone0 = SCNNode()
    bone0.simdPosition = float3(0,0,0)
    let bone1 = SCNNode()
    bone1.simdPosition = float3(0,1,0)
    let bone2 = SCNNode()
    bone2.simdPosition = float3(0,1,0) + normalize(float3(-1,1,0))
    let bones = [bone0, bone1, bone2]
    
    let boneInverseBindTransforms: [NSValue]? = bones.map { NSValue(scnMatrix4: SCNMatrix4Invert($0.transform)) }
    var boneWeights: [Float] = vertices.map { _ in 1.0 }
    var boneIndices: [UInt8] = [
        0, 1, 0, 1, 0, 1,
        1, 2, 1, 2, 1, 2,
    ]
    
    let boneWeightsData = Data(bytesNoCopy: &boneWeights, count: boneWeights.count * MemoryLayout<Float>.size, deallocator: .none)
    let boneIndicesData = Data(bytesNoCopy: &boneIndices, count: boneWeights.count * MemoryLayout<UInt8>.size, deallocator: .none)
    
    let boneWeightsGeometrySource = SCNGeometrySource(data: boneWeightsData, semantic: .boneWeights, vectorCount: boneWeights.count, usesFloatComponents: true, componentsPerVector: 1, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<Float>.size)
    let boneIndicesGeometrySource = SCNGeometrySource(data: boneIndicesData, semantic: .boneIndices, vectorCount: boneIndices.count, usesFloatComponents: false, componentsPerVector: 1, bytesPerComponent: MemoryLayout<UInt8>.size, dataOffset: 0, dataStride: MemoryLayout<UInt8>.size)
    
    let skinner = SCNSkinner(baseGeometry: geometry, bones: bones, boneInverseBindTransforms: boneInverseBindTransforms, boneWeights: boneWeightsGeometrySource, boneIndices: boneIndicesGeometrySource)
    
    let node = SCNNode(geometry: geometry)
    node.skinner = skinner
    
    让顶点=[float3(0.17841241,0.0,0.0),float3(0.17841241,1.0,0.0),float3(-0.089206174,0.0,0.1545097),float3(-0.089206174,1.0,0.1545097),float3(-0.089206256,0.0,-0.15450965),float3(-0.089206206,1.0.0,-.0.15450965),float3(-0.12615661,1.1261566),float833(-0.993),float630(-0.063078284,0.9369217,0.1545097),浮动3(-0.7701849,1.6440284,0.1545097),浮动3(-0.063078344,0.93692166,-0.15450965),浮动3(-0.77018493,1.6440284,-0.15450965)]
    let索引:[UInt8]=[0,1,2,3,4,5,0,1,1,6,6,7,8,9,10,11,6,7]
    设geometrySource=SCNGeometrySource(顶点:顶点.map{SCInvector3($0)})
    设geometryElement=SCNGeometryElement(索引:索引,原语类型:.triangleStrip)
    let geometry=SCNGeometry(源:[geometrySource],元素:[geometryElement])
    设bone0=SCNNode()
    bone0.simdPosition=float3(0,0,0)
    设bone1=SCNNode()
    bone1.simdPosition=float3(0,1,0)
    让bone2=SCNNode()
    bone2.simdPosition=float3(0,1,0)+规格化(float3(-1,1,0))
    let bones=[bone0,bone1,bone2]
    让boneInverseBindTransforms:[NSValue]?=bones.map{NSValue(scnMatrix4:SCNMatrix4Invert($0.transform))}
    var boneWeights:[Float]=vertices.map{1.0}
    var boneIndices:[UInt8]=[
    0, 1, 0, 1, 0, 1,
    1, 2, 1, 2, 1, 2,
    ]
    让boneWeightsData=Data(bytesnopy:&boneWeights,count:boneWeights.count*MemoryLayout.size,deallocator:.none)
    让boneIndicesData=Data(bytesNoCopy:&boneIndices,count:boneWeights.count*MemoryLayout.size,deallocator:.none)
    让boneWeightsGeometrySource=SCNGeometrySource(数据:boneWeightsData,语义:.boneWeights,向量计数:boneWeights.count,usesFloatComponents:true,ComponentServiceComponent:1,bytesPerComponent:MemoryLayout.size,数据偏移量:0,数据列:MemoryLayout.size)
    让boneIndicesGeometrySource=SCNGeometrySource(数据:boneIndicesData,语义:。boneIndices,vectorCount:boneIndices.count,usesFloatComponents:false,ComponentServiceComponent:1,bytesPerComponent:MemoryLayout.size,dataOffset:0,dataStride:MemoryLayout.size)
    让skinner=SCNSkinner(基本几何体:几何体,骨骼:骨骼,boneInverseBindTransforms:boneInverseBindTransforms,boneWeights:boneWeightsGeometrySource,boneIndices:BoneInverseGeometrySource)
    let node=SCNNode(几何体
    
     \
     |
    
          v5
          ^
    v3 /__|__\ v1
       |  |  |
       |  v4 |
    v2 |/___\| v0
    
    let vertices = [float3(0.17841241, 0.0, 0.0), float3(0.17841241, 1.0, 0.0), float3(-0.089206174, 0.0, 0.1545097), float3(-0.089206174, 1.0, 0.1545097), float3(-0.089206256, 0.0, -0.15450965), float3(-0.089206256, 1.0, -0.15450965), float3(0.12615661, 1.1261566, 0.0), float3(-0.58094996, 1.8332633, 0.0), float3(-0.063078284, 0.9369217, 0.1545097), float3(-0.7701849, 1.6440284, 0.1545097), float3(-0.063078344, 0.93692166, -0.15450965), float3(-0.77018493, 1.6440284, -0.15450965)]
    let indices: [UInt8] = [0, 1, 2, 3, 4, 5, 0, 1, 1, 6, 6, 7, 8, 9, 10, 11, 6, 7]
    let geometrySource = SCNGeometrySource(vertices: vertices.map { SCNVector3($0) })
    let geometryElement = SCNGeometryElement(indices: indices, primitiveType: .triangleStrip)
    let geometry = SCNGeometry(sources: [geometrySource], elements: [geometryElement])
    
    let bone0 = SCNNode()
    bone0.simdPosition = float3(0,0,0)
    let bone1 = SCNNode()
    bone1.simdPosition = float3(0,1,0)
    let bone2 = SCNNode()
    bone2.simdPosition = float3(0,1,0) + normalize(float3(-1,1,0))
    let bones = [bone0, bone1, bone2]
    
    let boneInverseBindTransforms: [NSValue]? = bones.map { NSValue(scnMatrix4: SCNMatrix4Invert($0.transform)) }
    var boneWeights: [Float] = vertices.map { _ in 1.0 }
    var boneIndices: [UInt8] = [
        0, 1, 0, 1, 0, 1,
        1, 2, 1, 2, 1, 2,
    ]
    
    let boneWeightsData = Data(bytesNoCopy: &boneWeights, count: boneWeights.count * MemoryLayout<Float>.size, deallocator: .none)
    let boneIndicesData = Data(bytesNoCopy: &boneIndices, count: boneWeights.count * MemoryLayout<UInt8>.size, deallocator: .none)
    
    let boneWeightsGeometrySource = SCNGeometrySource(data: boneWeightsData, semantic: .boneWeights, vectorCount: boneWeights.count, usesFloatComponents: true, componentsPerVector: 1, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<Float>.size)
    let boneIndicesGeometrySource = SCNGeometrySource(data: boneIndicesData, semantic: .boneIndices, vectorCount: boneIndices.count, usesFloatComponents: false, componentsPerVector: 1, bytesPerComponent: MemoryLayout<UInt8>.size, dataOffset: 0, dataStride: MemoryLayout<UInt8>.size)
    
    let skinner = SCNSkinner(baseGeometry: geometry, bones: bones, boneInverseBindTransforms: boneInverseBindTransforms, boneWeights: boneWeightsGeometrySource, boneIndices: boneIndicesGeometrySource)
    
    let node = SCNNode(geometry: geometry)
    node.skinner = skinner