코드에서 SceneKit SCNskinner 개체를 만드는 방법은 무엇입니까?
iOS 8용 SceneKit을 사용하는 Swift 앱을 가지고 있습니다. 스켈레톤으로 제어되는 메쉬가 포함된 .dae 파일의 장면을 로드합니다.런타임에 텍스처 좌표를 수정해야 합니다.변형을 사용하는 것은 선택사항이 아닙니다. 저는 그물망의 각 꼭짓점에 대해 완전히 다른 새로운 UV를 계산해야 합니다.
SceneKit에서 지오메트리는 불변이라는 것을 알고 있으며, 제안된 접근 방식은 수동으로 복사본을 만드는 것입니다.저는 그렇게 하려고 노력하고 있지만, 저는 항상 그것을 다시 만들려고 할 때 충돌하게 됩니다.SCNSkinner
암호상충돌은EXC_BAD_ACCESS
안에서.C3DSourceAccessorGetMutableValuePtrAtIndex
유감스럽게도, 이것에 대한 소스 코드가 없어서 정확히 왜 충돌하는지 모르겠습니다.제가 범위를 좁혀봤는데,SCNSkinner
메시 노드에 연결된 개체입니다.설정하지 않으면 충돌이 발생하지 않고 작동하는 것처럼 보입니다.
편집: 다음은 충돌에 대한 보다 완전한 콜 스택입니다.
C3DSourceAccessorGetMutableValuePtrAtIndex
C3DSkinPrepareMeshForGPUIfNeeded
C3DSkinnerMakeCurrentMesh
C3DSkinnerUpdateCurrentMesh
__CFSetApplyFunction_block_invoke
CFBasicHashApply
CFSetApplyFunction
C3DAppleEngineRenderScene
...
생성 방법에 대한 문서나 예제 코드를 찾지 못했습니다.SCNSkinner
수동으로 반대합니다.기존에 작업하던 메시를 기반으로 제작하는 것이기 때문에 크게 어렵지는 않을 것 같습니다.내가 만든 것은SCNSkinner
스위프트 문서에 따르면, 모든 올바른 것들을 그 안에 전달합니다.하지만, 해골 속성이 있습니다.SCNSkinner
어떻게 설정해야 할지 모르겠어요원본에 있던 해골로 설정했습니다.SCNSkinner
제가 복사하고 있는 그물망에 대해서요, 제 생각엔...하지만 그렇지 않습니다.골격 속성을 설정할 때 할당하는 것으로 보이지 않습니다.할당 직후 확인해 보면 여전히 0입니다.테스트로 원래 메쉬의 골격 속성을 다른 것으로 설정하려고 했는데, 과제가 끝난 후에도 그대로 남아 있었습니다.
누가 무슨 일이 일어나고 있는지 밝힐 수 있습니까?또는 올바르게 생성하고 설정하는 방법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, initWithFrame, frame); }
구체적으로 무엇이 당신의 코드를 손상시키는지는 모르지만, 여기 메시, 뼈, 그리고 그 메시를 생성하는 방법이 있습니다. 모두 코드에서 나온 것입니다.스위프트4와 iOS 12.
이 예에서는 다음과 같이 두 실린더의 연결을 나타내는 메시가 있으며, 실린더 중 하나가 45도 각도로 분기됩니다.
\
|
실린더는 돌출된 삼각형일 뿐입니다.radialSegmentCount = 3.
(두 실린더가 실제로 결합되지 않았기 때문에 9개가 아닌 12개의 꼭짓점이 있습니다.삼각형의 순서는 다음과 같습니다.
v5
^
v3 /__|__\ v1
| | |
| v4 |
v2 |/___\| v0
3개의 뼈가 실린더의 머리와 발에 해당하며, 가운데 뼈는 하단 실린더의 머리와 동시에 상단 실린더의 발에 해당합니다.예를 꼭짓점은 예들어, 은점꼭입니다.v0
,v2
,그리고.v4
에해하는에 합니다.bone0
;v1
,v3
,v5
에해하는에 합니다.bone1
등등.그것이 이유입니다.boneIndices
(아래 참조)는 가치가 있습니다.
합니다(골격정위위형치해실정다당니합치에지의더린서상에지는의(▁the▁of다해니▁of당합▁(골▁in▁resting▁the▁corresponds▁to▁cylinders▁geometry▁the위치).bone2
에서 45도 각도로 싹이 텄습니다.bone1
실린더 형상과 동일).
이를 컨텍스트로 사용하여 다음 코드는 지오메트리의 스킨 작업에 필요한 모든 것을 만듭니다.
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
은 고참: 대부의다사합니다야용해경음을 해야 합니다.UInt16
것은 아니다.UInt8
.
언급URL : https://stackoverflow.com/questions/27233066/how-to-create-a-scenekit-scnskinner-object-in-code
'programing' 카테고리의 다른 글
왼쪽 외부 조인에 대한 SQL 성능이 존재하지 않음 (0) | 2023.08.02 |
---|---|
"이것.앱inits[i]는 함수가 아닙니다. (0) | 2023.08.02 |
처리되지 않은 약속거부 경고:유형 오류: Jest + Angular를 사용하여 원형 구조를 JSON으로 변환하는 중 (0) | 2023.08.02 |
Python 헤더와 함께 POST 전송 (0) | 2023.08.02 |
Html에 ID 속성을 추가하는 방법.asp.net mvc에서 양식()을 시작하시겠습니까? (0) | 2023.08.02 |