加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 如何在代码中创建一个SceneKit SCNSkinner对象?

发布时间:2020-12-14 06:11:51 所属栏目:百科 来源:网络整理
导读:我有一个Swift应用程序使用SceneKit iOS 8。从一个.dae文件加载一个场景,包含一个骨架控制的网格。 在运行时,我需要修改纹理坐标。使用变换不是一个选项 – 我需要为网格中的每个顶点计算一个不同的,全新的UV。 我知道几何在SceneKit中是不可变的,我已经
我有一个Swift应用程序使用SceneKit iOS 8。从一个.dae文件加载一个场景,包含一个骨架控制的网格。
在运行时,我需要修改纹理坐标。使用变换不是一个选项 – 我需要为网格中的每个顶点计算一个不同的,全新的UV。

我知道几何在SceneKit中是不可变的,我已经读过,建议的方法是手动复制一个副本。我试图这样做,但我总是最终崩溃时试图重新创建SCNSkinner在代码中。崩溃是在C3DSourceAccessorGetMutableValuePtrAtIndex内的EXC_BAD_ACCESS。不幸的是,没有这个源代码,所以我不知道为什么它崩溃。我将它缩小到连接到网格节点的SCNSkinner对象。如果我不设置,我不会崩溃,事情似乎工作。

编辑:这里是一个更完整的调用堆栈的崩溃:

C3DSourceAccessorGetMutableValuePtrAtIndex
C3DSkinPrepareMeshForGPUIfNeeded
C3DSkinnerMakeCurrentMesh
C3DSkinnerUpdateCurrentMesh
__CFSetApplyFunction_block_invoke
CFBasicHashApply
CFSetApplyFunction
C3DAppleEngineRenderScene
...

我没有找到任何关于如何手动创建SCNSkinner对象的文档或示例代码。因为我只是基于一个以前工作的网格创建它,它不应该太难。我根据Swift文档创建SCNSkinner,将所有正确的东西传递到init。但是,在SCNSkinner中有一个框架属性,我不知道如何设置。我把它设置到我复制的网格的原始SCNSkinner上的骨架,我认为
应该工作…但它不。设置框架属性时,它似乎未分配。在分配之后立即检查它是否仍然为零。作为一个测试,我试图将原始网格的骨架属性设置为别的东西,并且在分配之后,它也保持不变。

任何人都可以知道发生了什么?或者如何手动正确创建和设置SCNSkinner对象?

这里是我使用的代码手动克隆一个网格,并用一个新的替换(我没有修改任何源数据在这里 – 我只是想确保我可以在这一点上创建一个副本) :

// This is at the start of the app,just so you can see how the scene is set up.
// I add the .dae contents into its own node in the scene. This seems to be the
// standard way to put multiple .dae models into the same scene. This doesn't seem to
// have any impact on the problem I'm having -- I've tried without this indirection
// and the same problem exists.
let scene = SCNScene()

let modelNode = SCNNode()
modelNode.name = "ModelNode"

scene.rootNode.addChildNode(modelNode)

let modelScene = SCNScene(named: "model.dae")

if modelScene != nil {
    if let childNodes = modelScene?.rootNode.childNodes {
        for childNode in childNodes {
            modelNode.addChildNode(childNode as SCNNode)
        }
    }
}


// This happens later in the app after a tap from the user.

let modelNode = scnView.scene!.rootNode.childNodeWithName("ModelNode",recursively: true)

let modelMesh = modelNode?.childNodeWithName("MeshName",recursively: true)

let verts = modelMesh?.geometry!.geometrySourcesForSemantic(SCNGeometrySourceSemanticVertex)
let normals = modelMesh?.geometry!.geometrySourcesForSemantic(SCNGeometrySourceSemanticNormal)
let texcoords = modelMesh?.geometry!.geometrySourcesForSemantic(SCNGeometrySourceSemanticTexcoord)
let boneWeights = modelMesh?.geometry!.geometrySourcesForSemantic(SCNGeometrySourceSemanticBoneWeights)
let boneIndices = modelMesh?.geometry!.geometrySourcesForSemantic(SCNGeometrySourceSemanticBoneIndices)
let geometry = modelMesh?.geometry!.geometryElementAtIndex(0)

// Note: the vertex and normal data is shared.
let vertsData = NSData(data: verts![0].data)
let texcoordsData = NSData(data: texcoords![0].data)
let boneWeightsData = NSData(data: boneWeights![0].data)
let boneIndicesData = NSData(data: boneIndices![0].data)
let geometryData = NSData(data: geometry!.data!)

let newVerts = SCNGeometrySource(data: vertsData,semantic: SCNGeometrySourceSemanticVertex,vectorCount: verts![0].vectorCount,floatComponents: verts![0].floatComponents,componentsPerVector: verts![0].componentsPerVector,bytesPerComponent: verts![0].bytesPerComponent,dataOffset: verts![0].dataOffset,dataStride: verts![0].dataStride)

let newNormals = SCNGeometrySource(data: vertsData,semantic: SCNGeometrySourceSemanticNormal,vectorCount: normals![0].vectorCount,floatComponents: normals![0].floatComponents,componentsPerVector: normals![0].componentsPerVector,bytesPerComponent: normals![0].bytesPerComponent,dataOffset: normals![0].dataOffset,dataStride: normals![0].dataStride)

let newTexcoords = SCNGeometrySource(data: texcoordsData,semantic: SCNGeometrySourceSemanticTexcoord,vectorCount: texcoords![0].vectorCount,floatComponents: texcoords![0].floatComponents,componentsPerVector: texcoords![0].componentsPerVector,bytesPerComponent: texcoords![0].bytesPerComponent,dataOffset: texcoords![0].dataOffset,dataStride: texcoords![0].dataStride)

let newBoneWeights = SCNGeometrySource(data: boneWeightsData,semantic: SCNGeometrySourceSemanticBoneWeights,vectorCount: boneWeights![0].vectorCount,floatComponents: boneWeights![0].floatComponents,componentsPerVector: boneWeights![0].componentsPerVector,bytesPerComponent: boneWeights![0].bytesPerComponent,dataOffset: boneWeights![0].dataOffset,dataStride: boneWeights![0].dataStride)

let newBoneIndices = SCNGeometrySource(data: boneIndicesData,semantic: SCNGeometrySourceSemanticBoneIndices,vectorCount: boneIndices![0].vectorCount,floatComponents: boneIndices![0].floatComponents,componentsPerVector: boneIndices![0].componentsPerVector,bytesPerComponent: boneIndices![0].bytesPerComponent,dataOffset: boneIndices![0].dataOffset,dataStride: boneIndices![0].dataStride)

let newGeometry = SCNGeometryElement(data: geometryData,primitiveType: geometry!.primitiveType,primitiveCount: geometry!.primitiveCount,bytesPerIndex: geometry!.bytesPerIndex)

let newMeshGeometry = SCNGeometry(sources: [newVerts,newNormals,newTexcoords,newBoneWeights,newBoneIndices],elements: [newGeometry])

newMeshGeometry.firstMaterial = modelMesh?.geometry!.firstMaterial

let newModelMesh = SCNNode(geometry: newMeshGeometry)

let bones = modelMesh?.skinner?.bones
let boneInverseBindTransforms = modelMesh?.skinner?.boneInverseBindTransforms
let skeleton = modelMesh!.skinner!.skeleton!
let baseGeometryBindTransform = modelMesh!.skinner!.baseGeometryBindTransform

newModelMesh.skinner = SCNSkinner(baseGeometry: newMeshGeometry,bones: bones,boneInverseBindTransforms: boneInverseBindTransforms,boneWeights: newBoneWeights,boneIndices: newBoneIndices)

newModelMesh.skinner?.baseGeometryBindTransform = baseGeometryBindTransform

// Before this assignment,newModelMesh.skinner?.skeleton is nil.
newModelMesh.skinner?.skeleton = skeleton
// After,it is still nil... however,skeleton itself is completely valid.

modelMesh?.removeFromParentNode()

newModelMesh.name = "MeshName"

let meshParentNode = modelNode?.childNodeWithName("MeshParentNode",recursively: true)

meshParentNode?.addChildNode(newModelMesh)
这三种方法可以帮助您找到解决方案:

>

SCNNode *hero = [SCNScene sceneNamed:@"Hero"].rootNode;
SCNNode *hat = [SCNScene sceneNamed:@"FancyFedora"].rootNode;
hat.skinner.skeleton = hero.skinner.skeleton;

>

[Export ("initWithFrame:")]
public UIView (System.Drawing.RectangleF frame) : base (NSObjectFlag.Empty)
{
// Invoke the init method now.
    var initWithFrame = new Selector ("initWithFrame:").Handle;
    if (IsDirectBinding)
        Handle = ObjCRuntime.Messaging.IntPtr_objc_msgSend_RectangleF (this.Handle,initWithFrame,frame);
    else
        Handle = ObjCRuntime.Messaging.IntPtr_objc_msgSendSuper_RectangleF (this.SuperHandle,frame);
}

>参见this link。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读