首页 > 解决方案 > SceneKit - 不同平面的纹理映射

问题描述

我想在场景包中平铺一个自定义平面。平面是可以具有任何形状的多边形。这是contentTransform和 uv 源纹理坐标:

let textureCoordinates = [  CGPoint(x: 0, y: 0),
                            CGPoint(x: 1, y: 0),
                            CGPoint(x: 0, y: 1),
                            CGPoint(x: 1, y: 1)
//...

polygonDiffuse.contentsTransform = .init(m11: 2.5, m12: 0,    m13: 0,    m14: 0,
                                         m21: 0,    m22: 2.5, m23: 0,    m24: 0,
                                         m31: 0,    m32: 0,    m33: 1,    m34: 0,
                                         m41: 0,    m42: 0,   m43: 0,    m44: 1)

我应该如何更改纹理映射以防止所有多边形平面的图块被拉伸?

标签: iosswiftaugmented-realityscenekitarkit

解决方案


既然你说“任何”形状,这里有几个例子。您必须将它们旋转到位。你可能需要调整你的纹理,但是是的——它会拉伸。如果图像只是“必须是正方形的,您可以对动态多边形的大小进行一些数学运算,并将一个四边形面板居中在贝塞尔轮廓内,也许使用相同的背景来覆盖重叠。

func getPentPanelSelectorNode(vPanelType: panelTypes, vUp: Int) -> SCNNode
    {
        let bezierPath = UIBezierPath()
        
        bezierPath.move(to:    CGPoint(x: -6.9, y: -10.15))
        
        bezierPath.addLine(to: CGPoint(x:  6.9, y: -10.15))
        bezierPath.addLine(to: CGPoint(x:  15.2, y:  3.22))
        bezierPath.addLine(to: CGPoint(x:  0.2, y:  13.40))
        bezierPath.addLine(to: CGPoint(x: -15.2, y:  3.22))
        bezierPath.close()
        
        let plane = SCNShape(path: bezierPath, extrusionDepth: 0.1)
        
        let topMaterial = SCNMaterial()
        topMaterial.diffuse.contents = UIColor.green
        topMaterial.locksAmbientWithDiffuse = true
        plane.materials = [topMaterial]
        let vNode = SCNNode(geometry: plane)
}

func getTriPanelNode(vPanelType: panelTypes, vUp: Int) -> SCNNode
{

        let bezierPath = UIBezierPath()
        bezierPath.move(to:    CGPoint(x: -2.0, y: -1.5))
        bezierPath.addLine(to: CGPoint(x:  2.0, y: -1.5))
        bezierPath.addLine(to: CGPoint(x:  0.0, y:  1.5))
        bezierPath.addLine(to: CGPoint(x: -2.0, y: -1.5))
        bezierPath.close()
        
        let plane = SCNShape(path: bezierPath, extrusionDepth: 0.0001)
        
        plane.materials = []
        plane.materials = setTriPanelTextures(vPanelType: vPanelType, vUp: vUp)
        plane.firstMaterial?.isDoubleSided = false
        
        let vNode = SCNNode(geometry: plane)
}

编辑 - 我只是试图向您发送几个不同的贝塞尔路径示例。这些只是三角形和五边形面板。

func setTriPanelTextures(vPanelType: panelTypes, vUp: Int) -> [SCNMaterial]
    {
        let topMaterial = SCNMaterial()
        switch vPanelType
        {
        case .normal:   topMaterial.diffuse.contents = "art.scnassets/Images/Panels/TileNormal.png"; break
        case .entry:    topMaterial.diffuse.contents = "art.scnassets/Images/Panels/TileEntryTri.png"; break
        case .exit:     topMaterial.diffuse.contents = "art.scnassets/Images/Panels/TileExitTri.png"; break
        case .path:     topMaterial.diffuse.contents = "art.scnassets/Images/Panels/TilePathTri.png"; break
        case .occupied: topMaterial.diffuse.contents = "art.scnassets/Images/Panels/TileNormal.png"; break
        }
        topMaterial.locksAmbientWithDiffuse = true
        
        return [topMaterial]
    }

推荐阅读