2016-08-15 11 views
3

をボックスに私はenter image description hereSceneKit - 地図キューブテクスチャ

よう

に見えるキューブのテクスチャをした私は、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")! 

私はジオメトリにシェーダ修飾子を使用することができます知っているが始めるためにどこがわかりません。テクスチャは現在6回使用されているので、私の直感は、SCNBoxのジオメトリが私の目標に適合しないかもしれないということですが、私はそれをどのように変更するのか本当に分かりません。

答えて

6

カスタムジオメトリを使用すると、キューブを作成することができます(開始するには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]) 
}