SceneKit 进口的 COLLADA 盒子未“点亮”

Posted

技术标签:

【中文标题】SceneKit 进口的 COLLADA 盒子未“点亮”【英文标题】:SceneKit Imported COLLADA Box not "Lit" 【发布时间】:2017-05-12 21:16:42 【问题描述】:

我有一个 SceneKit 项目,在场景视图中有两个对象。第一个对象是通过 SCNPlane 创建的平面。第二个对象是在 Blender 中创建的一个简单的盒子。在代码中,我设置了环境和全向照明。它的灯光效果适用于飞机:

但是,当我在飞机顶部添加盒子时,灯光效果在飞机上起作用,但从 COLLADA 文件导入的盒子却不起作用:

我怀疑问题与法线有关,但我不确定。有没有人通过 SceneKit 导入 DAE 遇到过这种情况?灯光和物体的设置代码是这样的:

private func setupAmbientLight() 

    // setup ambient light source
    let ambientLightNode = SCNNode()
    ambientLightNode.light = SCNLight()
    ambientLightNode.light!.type = SCNLight.LightType.ambient
    ambientLightNode.light!.color = NSColor(white: 0.35, alpha: 1.0).cgColor

    // add to scene
    guard let scene = sceneView.scene else 

        return
    
    scene.rootNode.addChildNode(ambientLightNode)


private func setupOmniDirectionalLight() 

    // initialize noe
    let omniLightNode = SCNNode()
    // assign light
    omniLightNode.light = SCNLight()
    // set type
    omniLightNode.light!.type = SCNLight.LightType.omni
    // color and position
    omniLightNode.light!.color = NSColor(white: 0.56, alpha: 1.0).cgColor
    omniLightNode.position = SCNVector3Make(0.0, 2000.0, 0.0)

    // add to scene
    guard let scene = sceneView.scene else 

        return
    
    scene.rootNode.addChildNode(omniLightNode)


private func setupPlane() 

    // create plane geometry with size and material properties
    let myPlane = SCNPlane(width: planeSideLength, height: planeSideLength)
    myPlane.firstMaterial!.diffuse.contents = NSColor.orange.cgColor
    myPlane.firstMaterial!.specular.contents = NSColor.white.cgColor

    // intialize node
    let planeNode = SCNNode()
    // assign plane geometry to the node
    planeNode.geometry = myPlane

    // rotate -90.0 about the x-axis
    let rotMat = SCNMatrix4MakeRotation(-CGFloat(M_PI/2.0), 1.0, 0.0, 0.0)
    planeNode.transform = rotMat
    planeNode.position = SCNVector3Make(0.0, 0.0, 0.0)

    // setup the node's physics body property
    planeNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: myPlane, options: nil))
    planeNode.physicsBody!.categoryBitMask = PhysicsMask3DOF.plane.rawValue

    // add to scene
    guard let scene = sceneView.scene else 

        return
    

    scene.rootNode.addChildNode(planeNode)


private func setupRobot() 

    guard let mainScene = sceneView.scene else 

        return
    

    let bundle = Bundle.main

    guard let url = bundle.url(forResource: "robot.scnassets/test_cube", withExtension: "dae") else 

        return
    

    var cubeScene: SCNScene?

    do 

        try cubeScene = SCNScene.init(url: url, options: nil)
    
    catch 

        return
    

    guard let cubeNode = cubeScene!.rootNode.childNode(withName: "Cube", recursively: true) else 

        return
    

    cubeNode.removeFromParentNode()
    cubeNode.scale = SCNVector3Make(2000.0, 2000.0, 2000.0)
    cubeNode.geometry!.firstMaterial!.diffuse.contents = NSColor.blue.cgColor
    cubeNode.geometry!.firstMaterial!.specular.contents = NSColor.white.cgColor

    mainScene.rootNode.addChildNode(cubeNode)

更新:

所以我注释了从 DAE 导入盒子的代码,而是添加了通过 SCNBox 创建盒子的代码,灯光效果似乎可以工作:

【问题讨论】:

【参考方案1】:

呃,盒子是 [2000 x 2000 x 2000],它的节点在 (0, 0, 0)。全光源节点的位置为 (0, 2000, 0)。只需要向上移动光源。这就引出了一个问题,当我通过 SCNBox 函数而不是从 DAE 文件导入创建具有相同尺寸的盒子时,为什么盒子会正确点亮

【讨论】:

你的立方体.dae文件有光源吗?您可以在 Xcode 场景编辑器中检查。 @dmsurti,是的,有一个,但我只想要对象并在主场景中使用光源,这不是 DAE 文件中的那个。 我猜这个developer.apple.com/reference/scenekit/scnscenerenderer/… 可以解释它,上面写着If this property’s value is false (the default), the only light sources SceneKit uses for rendering a scene are those contained in the scene graph。而且你的场景确实有来自cube.dae 文件的光线。

以上是关于SceneKit 进口的 COLLADA 盒子未“点亮”的主要内容,如果未能解决你的问题,请参考以下文章

使用 iOS 场景工具包加载未压缩的 collada 文件

SceneKit + Collada + 动画

SceneKit - 停止连续循环 Collada 动画

从scenekit中的网络服务器加载collada文件

将带有物理的 collada 场景加载到 SceneKit

使用 SceneKit 从 DAE/COLLADA 中提取动画顶点