6

这段代码摘录(场景、相机、灯光等)在 iOS 模拟器上的 Swift 中工作:

    let boxNode = SCNNode()

    // Create a box
    boxNode.geometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.1)
    let numFaces = 6

    scene.rootNode.addChildNode(boxNode)

    // create and configure a material for each face
    var materials: [SCNMaterial] = Array()

    for i in 1...numFaces
    {
        let material = SCNMaterial()
        material.diffuse.contents = UIImage(named: "texture")
        materials += material
    }

    // set the material to the 3d object geometry
    boxNode.geometry.materials = materials

它生成一个框,每个面都是方格图像。

应用内的 SCNBox

使用在 Wings3D 中创建、保存到 DAE 并加载到应用程序中的简单库存几何体尝试同样的事情,可以得到合适的形状,但脸上没有阴影和图像:

    let boxNode = SCNNode()

    // Load the geometry
    let urlToColladaFile = NSBundle.mainBundle().URLForResource("Objects", withExtension:"dae")
    let sceneSource = SCNSceneSource(URL:urlToColladaFile, options:nil)

    boxNode.geometry = sceneSource.entryWithIdentifier("dodecahedron3-0", withClass:SCNGeometry.self) as SCNGeometry
    let numFaces = 10

    scene.rootNode.addChildNode(boxNode)

    // create and configure a material for each face
    var materials: [SCNMaterial] = Array()

    for i in 1...numFaces
    {
        let material = SCNMaterial()
        material.diffuse.contents = UIImage(named: "texture")
        materials += material
    }

    // set the material to the 3d object geometry
    boxNode.geometry.materials = materials

来自 Wings3D 的十二面体

我错过了什么?

4

3 回答 3

6

你的几何图形有纹理坐标吗?您可以通过编程方式(通过检查是否存在具有 SCNGeometrySourceSemanticTexcoord 语义的源)或在 Xcode 中内置的 SceneKit 编辑器中验证这一点。

另请注意,您不必为每个几何元素创建一种材料。如果它们都相同,只需构建一种材料的数组,它将用于整个几何体。

于 2014-07-12T11:10:06.660 回答
1

谢谢,mnuages & rickster。您的推论使我研究了我在 Wings3D 中的选项,并且我能够在 Wings3D 中解决问题。

简而言之,我需要为实体的每个面创建一个 UV 映射。

对于常规多面体,我有多种选择:

  • 选择整个身体(以及所有的脸),对其进行一次 UV 映射,并在所有脸上拉伸一张图像。有关于如何做到这一点的在线教程。
  • 对于每个面,选择它,做一个 UV 映射(我通常选择 Projection Normal 来做),然后每个面都会得到相同的映射,不管你在我的代码中放入了多少张图像。
  • 对于每张脸,首先执行上述操作。然后进入 Outliner 窗口,复制 AUV(自动 UV)文件,以便每个面都有一个唯一的文件。然后选择每个 AUV 并将其分配给不同的面。这将给我尽可能多的面,例如,允许我为骰子的每个面创建一个新图像。这是我必须弄清楚的——在设置材质时,Wings3D 中的 AUV 映射与 SceneKit 所称的几何元素之间似乎存在一对一的映射。
  • 以上的组合,使多个人脸可以共享相同的映射,然后自动分配相同的图像。

如果我开始在边缘添加边框或更平滑的倒角,这一切都会变得有点复杂,现在我需要确保 UV 映射对我工作的每组面都有意义。同样,网上也有这方面的教程。

再次感谢!

干杯,亨利

于 2014-07-15T20:57:03.493 回答
1

首先,您必须在设计 3D 对象时定义材质。

然后以编程方式为每个材质分配纹理。

 let material1 = SCNMaterial()
 material1.diffuse.contents = UIImage(named: "1")?.xFlipped
 material1.locksAmbientWithDiffuse = true

 let material2 = SCNMaterial()
 material2.diffuse.contents = UIImage(named: "2")?.xFlipped
 material2.locksAmbientWithDiffuse = true

 ...

 let material12 = SCNMaterial()
 material12.diffuse.contents = UIImage(named: "12")?.xFlipped
 material12.locksAmbientWithDiffuse = true


 scene.rootNode.childNodeWithName("Dice", recursively: false)?.geometry?.materials = [material1, material2, material3, material4, material5, material6, material7, material8, material9, material10, material11, material12]

其中“骰子”是您在属性检查器中设置的对象身份名称。

extension UIImage {
    var xFlipped: UIImage {
        let tempImageView = UIImageView(frame: CGRectMake(0, 0, self.size.width, self.size.height))
        tempImageView.image = self
        let viewTempImage = UIView(frame: tempImageView.frame)
        viewTempImage.addSubview(tempImageView)

        tempImageView.transform = CGAffineTransformMakeScale(-1, 1)
        let img = viewTempImage.screenshot

        return img

    }
}


extension UIView {
    var screenshot: UIImage{
        UIGraphicsBeginImageContext(self.bounds.size);
        let context = UIGraphicsGetCurrentContext();
        self.layer.renderInContext(context!)
        let screenShot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return screenShot
    }
}

注意:在我添加纹理的情况下,图像是水平翻转的。所以我像上面一样手动翻转。

于 2016-04-11T06:12:33.080 回答