使用SCNMorpher会在SceneKit中生成不需要的平面多边形渲染

jaw*_*awj 5 scenekit

我在iOS SceneKit中使用SCNMorpher在从Blender导出为DAE文件的3D人脸模型上的不同面部表情之间进行变换.变形本身很好.

在我第一次调用setWeight:forTargetAtIndex:变形器之前,根据需要可以平滑地渲染模型.

但是一旦我进行调用,所有多边形边缘都变得可见,这是非常不吸引人的.这与Blender本身从"平滑"渲染到"平面"渲染的区别相同.

图像如下:首先是平滑渲染,预变形,然后是平面渲染,后变形.

平滑渲染,预变换 平面渲染,后变形

我正在使用Lambert光照模型(尽管其他模型受到相同的影响),litPerPixel适用于每个目标几何体的每种材质.

我不清楚这是否是SCNMorpher的已知/故意限制,一个错误,或者我做错了什么.我想知道变形是否以某种方式搞砸了通常用于平滑渲染的顶点法线数据.

任何人都可以放下任何光线都会非常感激.(我想一个可能的解决方法可能是通过插入所有顶点和法线向量来形成一个新的几何图形来手动进行变形,但我想这将是令人不快的慢速).

代码的相关部分如下:

faceNode.geometry = faces.rootNode.childNodeWithName("neutral", recursively: true)!.geometry
scene.rootNode.addChildNode(faceNode)

var morphs: [SCNGeometry] = []

let moods: [String] = "mood1 mood2".componentsSeparatedByString(" ")
for mood in moods {
  let moodFace = faces.rootNode.childNodeWithName(mood, recursively: true)!.geometry!
  morphs.append(moodFace)
}

let morpher = SCNMorpher()
morpher.targets = morphs

faceNode.morpher = morpher
morpher.setWeight(0.5, forTargetAtIndex: 0)
Run Code Online (Sandbox Code Playgroud)

小智 6

只是也遇到了这个问题。您需要将morpher上的unifiedNormals设置为true。

let morpher = SCNMorpher()
morpher.targets = morphs
morpher.unifiesNormals = true
faceNode.morpher = morpher
Run Code Online (Sandbox Code Playgroud)


jaw*_*awj 0

我上面提到的可能解决方法的更新:通过插入所有顶点和法线向量来手动变形以形成新的几何体。

\n\n

事实上,使用 Accelerate/vDSP 进行插值,效果出奇地好。

\n\n

我的用例比 SCNMorpher \xe2\x80\x94 提供的不太通用,我只需要随时在两个模型之间进行变形。下面的代码实现了这一点(在我的 iPhone 6 上,对于大约 40,000 个顶点的几何图形,速度约为 30fps):

\n\n
// .h\n\n@property (nonatomic) size_t morphBufferSize;\n@property (nonatomic) float* morphBuffer;\n\n// .m (note: we assume floats not doubles by using vDSP_vintb rather than vDSP_vintbD)\n\n- (SCNGeometry*)morphGeometry:(SCNGeometry*)g1 toGeometry:(SCNGeometry*)g2 withWeight:(float)weight {\n  SCNGeometrySource* v1 = [g1 geometrySourcesForSemantic:SCNGeometrySourceSemanticVertex].firstObject;\n  SCNGeometrySource* n1 = [g1 geometrySourcesForSemantic:SCNGeometrySourceSemanticNormal].firstObject;\n  SCNGeometrySource* v2 = [g2 geometrySourcesForSemantic:SCNGeometrySourceSemanticVertex].firstObject;\n  SCNGeometrySource* n2 = [g2 geometrySourcesForSemantic:SCNGeometrySourceSemanticNormal].firstObject;\n\n  vDSP_Length len = v1.data.length;\n  vDSP_Length numFloats = len / sizeof(float);\n\n  if (_morphBufferSize < len) {\n    _morphBuffer = realloc(_morphBuffer, len);\n    _morphBufferSize = len;\n  }\n\n  vDSP_vintb(v1.data.bytes, 1,\n             v2.data.bytes, 1,\n             &weight,\n             _morphBuffer, 1,\n             numFloats);\n\n  SCNGeometrySource* v3 = [SCNGeometrySource geometrySourceWithData:[NSData dataWithBytesNoCopy:_morphBuffer length:len freeWhenDone:NO]\n                                                           semantic:SCNGeometrySourceSemanticVertex\n                                                        vectorCount:v1.vectorCount\n                                                    floatComponents:v1.floatComponents\n                                                componentsPerVector:v1.componentsPerVector\n                                                  bytesPerComponent:v1.bytesPerComponent\n                                                         dataOffset:v1.dataOffset\n                                                         dataStride:v1.dataStride];\n\n  vDSP_vintb(n1.data.bytes, 1,\n             n2.data.bytes, 1,\n             &weight,\n             _morphBuffer, 1,\n             numFloats);\n\n  SCNGeometrySource* n3  = [SCNGeometrySource geometrySourceWithData:[NSData dataWithBytesNoCopy:_morphBuffer length:len freeWhenDone:NO]\n                                                            semantic:SCNGeometrySourceSemanticNormal\n                                                         vectorCount:n1.vectorCount\n                                                     floatComponents:n1.floatComponents\n                                                 componentsPerVector:n1.componentsPerVector\n                                                   bytesPerComponent:n1.bytesPerComponent\n                                                          dataOffset:n1.dataOffset\n                                                          dataStride:n1.dataStride];\n\n  NSMutableArray* elements = [NSMutableArray arrayWithCapacity:g1.geometryElementCount];\n  for (NSInteger i = 0, len = g1.geometryElementCount; i < len; i ++) [elements addObject:[g1 geometryElementAtIndex:i]];\n\n  SCNGeometry* g3 = [SCNGeometry geometryWithSources:@[v3, n3] elements:elements];\n  return g3;\n}\n\n- (void)dealloc {\n    free(_morphBuffer);\n}\n
Run Code Online (Sandbox Code Playgroud)\n