SceneKit-将多维数据集纹理映射到框 [英] SceneKit - Map cube texture to box

查看:102
本文介绍了SceneKit-将多维数据集纹理映射到框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've a texture for a cube that looks like

我想在SceneKit视图中的多维数据集上使用它.我为此使用了SceneKit几何SCNBox.不幸的是,结果是纹理完全投影在每个面上,而不是仅使用相应的部分:

I'd like to use it on a cube in a SceneKit view. I'm using the SceneKit geometry SCNBox for that. Unfortunately, the result is that the texture is projected entirely on each face, instead of using only the corresponding part:

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

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

I know I can use shader modifiers on the geometry but I'm not sure where to get started. Since the texture is currently used six times, my intuition is that the SCNBox geometry might not be adapted to my goal, but I don't really know how to change it.

推荐答案

您可以将其与自定义几何一起使用:创建一个多维数据集(

You can get it to work with a custom geometry: create a cube (http://ronnqvi.st/custom-scenekit-geometry/ is a good place to get started) and you can add some custom texture mapping on top. It's a bit tricky to get the indices right (was for me), but at the end it worked fine:

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])
}

这篇关于SceneKit-将多维数据集纹理映射到框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆