SCNBox 每张脸上都有不同的颜色或纹理

Posted

技术标签:

【中文标题】SCNBox 每张脸上都有不同的颜色或纹理【英文标题】:SCNBox different colour or texture on each face 【发布时间】:2015-02-15 00:39:37 【问题描述】:

我是 ios 开发的新手,我被难住了。我正在尝试使用 SceneKit 渲染一个立方体,每个面都有不同的颜色。

这是我目前得到的:

func sceneSetup() 
    // 1
    let scene = SCNScene()

    // 2
    let BoxGeometry = SCNBox(width: 0.9, height: 0.9, length: 0.9, chamferRadius: 0.0)

    BoxGeometry.firstMaterial?.diffuse.contents = UIColor.redColor()
    let cube = SCNNode(geometry: BoxGeometry)
    cube.position = SCNVector3(x: 0, y: 0, z: -1)
    scene.rootNode.addChildNode(cube)

    // 3
    sceneView.scene = scene
    sceneView.autoenablesDefaultLighting = true
    sceneView.allowsCameraControl = true

但我希望每张脸都有不同的颜色。我该怎么做?

【问题讨论】:

【参考方案1】:

盒子由六个不同的元素组成(每边一个)。您可能还注意到,几何对象有一个属性用于 first 材质,但也有一个属性用于材质数组。

具有多个元素和多种材质的对象将为每个元素选择材质(和包裹)增量。

例如 4 个元素和 1 个材质

Element   1  2  3  4
Material  1  1  1  1

或 4 个元素和 2 个材料

Element   1  2  3  4
Material  1  2  1  2  // note that they are repeating 

例如 4 个元素和 7 个材质

Element   1  2  3  4
Material  1  2  3  4  // (5, 6, 7) is unused

就盒子而言,这意味着您可以使用包含六种材质的数组来在盒子的每一侧拥有一种独特的材质。我在 the sample code for one of the chapters 我的 Scene Kit 书(在 Objective-C 中)有一个这样的例子:

// Each side of the box has its own color
// --------------------------------------
// All have the same diffuse and ambient colors to show the
// effect of the ambient light, even with these materials.

SCNMaterial *greenMaterial              = [SCNMaterial material];
greenMaterial.diffuse.contents          = [NSColor greenColor];
greenMaterial.locksAmbientWithDiffuse   = YES;

SCNMaterial *redMaterial                = [SCNMaterial material];
redMaterial.diffuse.contents            = [NSColor redColor];
redMaterial.locksAmbientWithDiffuse     = YES;

SCNMaterial *blueMaterial               = [SCNMaterial material];
blueMaterial.diffuse.contents           = [NSColor blueColor];
blueMaterial.locksAmbientWithDiffuse    = YES;

SCNMaterial *yellowMaterial             = [SCNMaterial material];
yellowMaterial.diffuse.contents         = [NSColor yellowColor];
yellowMaterial.locksAmbientWithDiffuse  = YES;

SCNMaterial *purpleMaterial             = [SCNMaterial material];
purpleMaterial.diffuse.contents         = [NSColor purpleColor];
purpleMaterial.locksAmbientWithDiffuse  = YES;

SCNMaterial *magentaMaterial            = [SCNMaterial material];
magentaMaterial.diffuse.contents        = [NSColor magentaColor];
magentaMaterial.locksAmbientWithDiffuse = YES;


box.materials =  @[greenMaterial,  redMaterial,    blueMaterial,
                   yellowMaterial, purpleMaterial, magentaMaterial];

【讨论】:

干得好,先生!还有一点值得注意:对于许多几何图形,您可以通过查询其geometryElementCount 来了解它支持多少种材料。这不适用于SCNBox,不过...它会根据您分配的材料数量自动重新创建其几何元素集(这样,如果它没有六种材料,它就不需要六次绘制调用来渲染)。 哪边是哪边(前、右、后、左、上、下)? 我也想知道这个^虽然我也不确定你会如何定义前/右/后/左/上/下... @RubenMartinezJr。数组顺序定义了哪个面是哪个。它应该与为SCNMaterialProperty.contents 指定立方体贴图的顺序相同:+x、-x、+y、-y、+z、-z。 (相对于默认方向的查看器,即右、左、上、下、远、近。) Swift 转换代码方便:gist.github.com/mattrobmattrob/e934d664ef0fc8d45b7837d9eb797255【参考方案2】:

这是 Swift 4 的答案。

    let colors = [UIColor.green, // front
                  UIColor.red, // right
                  UIColor.blue, // back
                  UIColor.yellow, // left
                  UIColor.purple, // top
                  UIColor.gray] // bottom

    let sideMaterials = colors.map  color -> SCNMaterial in
        let material = SCNMaterial()
        material.diffuse.contents = color
        material.locksAmbientWithDiffuse = true
        return material
    

    materials = sideMaterials

要改变前面的材料,只需抓住材料并改变它的内容

let frontMaterial = materials[0]
frontMaterial.diffuse.contents = UIColor.white

【讨论】:

【参考方案3】:

感谢您的快速帮助。我使用了您提出的代码但无法使用 NSColor 所以我尝试了 uicolor 但我得到的只是一个黑色立方体所以我尝试了这个并且我得到了它的工作

    let BoxGeometry = SCNBox(width: 0.95, height: 0.95, length: 0.95, chamferRadius: 0.0)

    let greenMaterial = SCNMaterial()
    greenMaterial.diffuse.contents = UIImage(named: "g")
    greenMaterial.locksAmbientWithDiffuse = true;

    let redMaterial = SCNMaterial()
    redMaterial.diffuse.contents = UIImage(named: "r")
    redMaterial.locksAmbientWithDiffuse = true;


    let blueMaterial  = SCNMaterial()
    blueMaterial.diffuse.contents = UIImage(named: "b")
    blueMaterial.locksAmbientWithDiffuse = true;


    let yellowMaterial = SCNMaterial()
    yellowMaterial.diffuse.contents = UIImage(named: "y")
    yellowMaterial.locksAmbientWithDiffuse = true;


    let purpleMaterial = SCNMaterial()
    purpleMaterial.diffuse.contents = UIImage(named: "p")
    purpleMaterial.locksAmbientWithDiffuse = true;


    let WhiteMaterial = SCNMaterial()
    WhiteMaterial.diffuse.contents = UIImage(named: "w")
    WhiteMaterial.locksAmbientWithDiffuse   = true;


    BoxGeometry.materials =  [greenMaterial,  redMaterial,    blueMaterial,
    yellowMaterial, purpleMaterial, WhiteMaterial];

g 是一个绿色的 jpeg 等等,现在它已经开始工作了。

【讨论】:

以上是关于SCNBox 每张脸上都有不同的颜色或纹理的主要内容,如果未能解决你的问题,请参考以下文章

在 SceneKit 中,如何在不同大小的对象上平铺纹理,同时保持最小的绘制调用?

来自 UIColor 的纹理?

(寒假集训) 卡片(离散化)

Three.js 立方体,每个面都有不同的纹理

从共现矩阵中提取纹理特征

列表视图中的重叠行