【问题标题】:SceneKit - Map cube texture to boxSceneKit - 将立方体纹理映射到盒子
【发布时间】:2016-12-21 07:18:51
【问题描述】:

我有一个立方体的纹理,看起来像

我想在 SceneKit 视图中的立方体上使用它。为此,我正在使用 SceneKit 几何体SCNBox。不幸的是,结果是纹理完全投影在每个面上,而不是只使用相应的部分:

let videoGeometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
videoGeometry.firstMaterial?.isDoubleSided = true
videoGeometry.firstMaterial?.diffuse.contents = UIImage(named: "test")!

我知道我可以在几何体上使用着色器修改器,但我不确定从哪里开始。由于纹理当前使用了六次,我的直觉是SCNBox 几何可能不适合我的目标,但我真的不知道如何更改它。

【问题讨论】:

    标签: ios opengl-es scenekit geometry-shader


    【解决方案1】:

    您可以让它与自定义几何体一起使用:创建一个立方体(http://ronnqvi.st/custom-scenekit-geometry/ 是一个很好的起点),您可以在顶部添加一些自定义纹理映射。获得正确的索引有点棘手(对我来说),但最后它工作正常:

    func getSimpleCubeGeo() -> SCNGeometry {
        let halfSide = Float(0.5)
    
        /* The cube vertex are like:
    
            5---------4
           /.        /|
          / .       / |
         7---------6  |
         |  .      |  |
         |  .      |  |
         |  1......|..0
         | .       | /
         |.        |/
         3---------2
    
         */
        let _positions = [
            SCNVector3(x:-halfSide, y:-halfSide, z:  halfSide),
            SCNVector3(x: halfSide, y:-halfSide, z:  halfSide),
            SCNVector3(x:-halfSide, y:-halfSide, z: -halfSide),
            SCNVector3(x: halfSide, y:-halfSide, z: -halfSide),
            SCNVector3(x:-halfSide, y: halfSide, z:  halfSide),
            SCNVector3(x: halfSide, y: halfSide, z:  halfSide),
            SCNVector3(x:-halfSide, y: halfSide, z: -halfSide),
            SCNVector3(x: halfSide, y: halfSide, z: -halfSide),
        ]
    
        // points are tripled since they are each used on 3 faces
        // and there's no continuity in the UV mapping
        // so we need to duplicate the points
        //
        // we'll use the first third for the faces orthogonal to the X (left) axis,
        // the second for the Y (top) axis and the third for the Z (front) axis
        let positions = _positions + _positions + _positions
    
        let X = 0
        let Y = 8
        let Z = 16
    
        let indices = [
            // bottom
            0 + Y, 2 + Y, 1 + Y,
            1 + Y, 2 + Y, 3 + Y,
            // back
            2 + Z, 6 + Z, 3 + Z,
            3 + Z, 6 + Z, 7 + Z,
            // left
            0 + X, 4 + X, 2 + X,
            2 + X, 4 + X, 6 + X,
            // right
            1 + X, 3 + X, 5 + X,
            3 + X, 7 + X, 5 + X,
            // front
            0 + Z, 1 + Z, 4 + Z,
            1 + Z, 5 + Z, 4 + Z,
            // top
            4 + Y, 5 + Y, 6 + Y,
            5 + Y, 7 + Y, 6 + Y,
        ]
    
        // get the points in the texture where the faces are split
        var textureSplitPoints = [CGPoint]()
        for i in 0...12 {
            let x = Double(i % 4)
            let y = Double(i / 4)
            textureSplitPoints.append(CGPoint(x: x / 3.0, y: y / 2.0))
        }
        let textCoords = [
            textureSplitPoints[4],
            textureSplitPoints[6],
            textureSplitPoints[5],
            textureSplitPoints[5],
            textureSplitPoints[8],
            textureSplitPoints[10],
            textureSplitPoints[9],
            textureSplitPoints[9],
    
            textureSplitPoints[5],
            textureSplitPoints[4],
            textureSplitPoints[1],
            textureSplitPoints[0],
            textureSplitPoints[7],
            textureSplitPoints[6],
            textureSplitPoints[11],
            textureSplitPoints[10],
    
            textureSplitPoints[2],
            textureSplitPoints[1],
            textureSplitPoints[2],
            textureSplitPoints[3],
            textureSplitPoints[6],
            textureSplitPoints[5],
            textureSplitPoints[6],
            textureSplitPoints[7],
        ]
    
        let vertexSource = SCNGeometrySource(vertices: positions)
    
        let textSource = SCNGeometrySource(textureCoordinates: textCoords)
        let indexData = NSData(bytes: indices, length: sizeof(Int) * indices.count)
        let elements = SCNGeometryElement(
            data: indexData as Data,
            primitiveType: SCNGeometryPrimitiveType.triangles,
            primitiveCount: indices.count / 3,
            bytesPerIndex: sizeof(Int)
        )
        return SCNGeometry(sources: [vertexSource, textSource], elements: [elements])
    }
    

    【讨论】:

    猜你喜欢
    • 2014-01-09
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多