2017-09-23 55 views
0

在SceneKit中,我试图用它上面的纹理创建一个简单的自定义几何。我只是想制作一个立方体,但每张脸都正确定位,所以SCNBox将无法正常工作。SceneKit自定义几何纹理错误

形状非常好,但纹理映射完全错误。

这就是几何找出来,如:

enter image description here

根据我的理解,纹理坐标每个人脸上都应该是相同的。但是,当我以相同的顺序为每个面添加点时,它的绘制方式不正确。所以我玩弄了坐标的顺序,并获得了正面,背面和一面的正面。我一直无法弄清楚造成这种情况的模式或逻辑。

前面是每张脸的外观。

以下是我正在做它:

public struct face { 
    var topLeft: SCNVector3 
    var topRight: SCNVector3 
    var bottomLeft: SCNVector3 
    var bottomRight: SCNVector3 
} 

func createCube(startFace: face, endFace: face) -> SCNGeometry { 
    var vertices: [SCNVector3] = [] 
    var indices: [Int32] = [] 
    var textCords: [vector_float2] = [] 

    // Add table of contents to indices array because we're using polygons 
    let polygons = 6 // cube so 6 faces 
    indices.append(4) // front face 
    indices.append(4) // left face 
    indices.append(4) // right face 
    indices.append(4) // top face 
    indices.append(4) // bottom face 
    indices.append(4) // back face 

    // - Convenience Values - 

    // Indices offsets 
    let startFaceVertex: Int32 = 0 
    let endFaceVertex: Int32 = 4 

    // Vertex indices 
    let bottomLeftPos: Int32 = 0 
    let bottomRightPos: Int32 = 1 
    let topRightPos: Int32 = 2 
    let topLeftPos: Int32 = 3 

    // Texture Coordinates 
    let topLeft = CGPoint(x: 0, y: 1) 
    let topRight = CGPoint(x: 1, y: 1) 
    let bottomLeft = CGPoint(x: 0, y: 0) 
    let bottomRight = CGPoint(x: 1, y: 0) 


    // Add vertices 

    vertices.append(startFace.bottomLeft) 
    vertices.append(startFace.bottomRight) 
    vertices.append(startFace.topRight) 
    vertices.append(startFace.topLeft) 

    vertices.append(endFace.bottomLeft) 
    vertices.append(endFace.bottomRight) 
    vertices.append(endFace.topRight) 
    vertices.append(endFace.topLeft) 


    // Front Face 

    indices.append(startFaceVertex + bottomLeftPos) 
    indices.append(startFaceVertex + bottomRightPos) 
    indices.append(startFaceVertex + topRightPos) 
    indices.append(startFaceVertex + topLeftPos) 

    textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y))) 
    textCords.append(vector_float2(Float(topRight.x), Float(topRight.y))) 
    textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y))) 

    // Left Face 

    indices.append(startFaceVertex + bottomLeftPos) 
    indices.append(endFaceVertex + bottomLeftPos) 
    indices.append(endFaceVertex + topLeftPos) 
    indices.append(startFaceVertex + topLeftPos) 

    textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y))) 
    textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y))) 
    textCords.append(vector_float2(Float(topRight.x), Float(topRight.y))) 

    // Top Face 

    indices.append(endFaceVertex + topLeftPos) 
    indices.append(endFaceVertex + topRightPos) 
    indices.append(startFaceVertex + topRightPos) 
    indices.append(startFaceVertex + topLeftPos) 

    textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y))) 
    textCords.append(vector_float2(Float(topRight.x), Float(topRight.y))) 
    textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y))) 

    // Right Face 

    indices.append(endFaceVertex + bottomRightPos) 
    indices.append(startFaceVertex + bottomRightPos) 
    indices.append(startFaceVertex + topRightPos) 
    indices.append(endFaceVertex + topRightPos) 

    textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y))) 
    textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y))) 
    textCords.append(vector_float2(Float(topRight.x), Float(topRight.y))) 

    // Bottom Face 

    indices.append(startFaceVertex + bottomLeftPos) 
    indices.append(startFaceVertex + bottomRightPos) 
    indices.append(endFaceVertex + bottomRightPos) 
    indices.append(endFaceVertex + bottomLeftPos) 

    textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y))) 
    textCords.append(vector_float2(Float(topRight.x), Float(topRight.y))) 
    textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y))) 


    // Back Face 

    indices.append(endFaceVertex + bottomLeftPos) 
    indices.append(endFaceVertex + bottomRightPos) 
    indices.append(endFaceVertex + topRightPos) 
    indices.append(endFaceVertex + topLeftPos) 

    textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y))) 
    textCords.append(vector_float2(Float(topRight.x), Float(topRight.y))) 
    textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y))) 


    // Create geometry 

    let verticesSource = SCNGeometrySource(vertices: vertices) 

    let uvData = Data(bytes: textCords, count: textCords.count * MemoryLayout<vector_float2>.size) 
    let textureSource = SCNGeometrySource(data: uvData, 
              semantic: .texcoord, 
              vectorCount: textCords.count, 
              usesFloatComponents: true, 
              componentsPerVector: 2, 
              bytesPerComponent: MemoryLayout<Float>.size, 
              dataOffset: 0, 
              dataStride: MemoryLayout<vector_float2>.size) 

    let indexData = Data(bytes: indices, 
         count: indices.count * MemoryLayout<Int32>.size) 
    let elements = SCNGeometryElement(data: indexData, 
             primitiveType: .polygon, 
             primitiveCount: polygons, 
             bytesPerIndex: MemoryLayout<Int32>.size) 

    return SCNGeometry(sources: [verticesSource, textureSource], elements: [elements]) 
} 

解决方案

得到它的工作,这是我的工作版本代码:

public struct face { 
    var topLeft: SCNVector3 
    var topRight: SCNVector3 
    var bottomLeft: SCNVector3 
    var bottomRight: SCNVector3 
} 

let topLeft = CGPoint(x: 0, y: 1) 
let topRight = CGPoint(x: 1, y: 1) 
let bottomLeft = CGPoint(x: 0, y: 0) 
let bottomRight = CGPoint(x: 1, y: 0) 

func createCube(startFace: face, endFace: face) -> SCNGeometry { 
    var vertices: [SCNVector3] = [] 
    var indexTable: [Int32] = [] 
    var indices: [Int32] = [] 
    var textCords: [vector_float2] = [] 

    // Front Face 
    addFace(face: startFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords) 

    // Left Face 

    let leftFace = face(topLeft: endFace.topLeft, topRight: startFace.topLeft, bottomLeft: endFace.bottomLeft, bottomRight: startFace.bottomLeft, center: SCNVector3Zero, originOffset: startFace.originOffset) 
    addFace(face: leftFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords) 

    // Top Face 

    //let topFace = face(topLeft: startFace.topLeft, topRight: endFace.topLeft, bottomLeft: startFace.topRight, bottomRight: endFace.topRight, center: SCNVector3Zero, originOffset: startFace.originOffset) 
    let topFace = face(topLeft: startFace.topLeft, topRight: endFace.topLeft, bottomLeft: startFace.topRight, bottomRight: endFace.topRight, center: SCNVector3Zero, originOffset: startFace.originOffset) 
    addFace(face: topFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords) 

    // Right Face 

    let rightFace = face(topLeft: startFace.topRight, topRight: endFace.topRight, bottomLeft: startFace.bottomRight, bottomRight: endFace.bottomRight, center: SCNVector3Zero, originOffset: startFace.originOffset) 
    addFace(face: rightFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords) 

    // Bottom Face 

    let bottomFace = face(topLeft: endFace.bottomLeft, topRight: startFace.bottomLeft, bottomLeft: endFace.bottomRight, bottomRight: startFace.bottomRight, center: SCNVector3Zero, originOffset: startFace.originOffset) 
    addFace(face: bottomFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords) 

    // Back Face 

    addFace(face: endFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords) 

    // Create geometry 

    let verticesSource = SCNGeometrySource(vertices: vertices) 

    let uvData = Data(bytes: textCords, count: textCords.count * MemoryLayout<vector_float2>.size) 
    let textureSource = SCNGeometrySource(data: uvData, 
              semantic: .texcoord, 
              vectorCount: textCords.count, 
              usesFloatComponents: true, 
              componentsPerVector: 2, 
              bytesPerComponent: MemoryLayout<Float>.size, 
              dataOffset: 0, 
              dataStride: MemoryLayout<vector_float2>.size) 

    var finalIndices: [Int32] = [] 
    finalIndices.append(contentsOf: indexTable) 
    finalIndices.append(contentsOf: indices) 

    let indexData = Data(bytes: finalIndices, 
         count: finalIndices.count * MemoryLayout<Int32>.size) 
    let elements = SCNGeometryElement(data: indexData, 
             primitiveType: .polygon, 
             primitiveCount: indexTable.count, 
             bytesPerIndex: MemoryLayout<Int32>.size) 

    return SCNGeometry(sources: [verticesSource, textureSource], elements: [elements]) 
} 
fileprivate func addFace(face: face, textureOffset: CGPoint, textureSize: CGSize, toVertices: inout [SCNVector3], indexTable: inout [Int32], indices: inout [Int32], textCords: inout [vector_float2]) { 
    toVertices.append(face.topRight) 
    toVertices.append(face.topLeft) 
    toVertices.append(face.bottomLeft) 
    toVertices.append(face.bottomRight) 

    let polygonPointCount: Int32 = 4 
    indexTable.append(polygonPointCount) 
    for _ in 0..<polygonPointCount { 
     indices.append(Int32(indices.count)) 
    } 

    textCords.append(vector_float2(Float(bottomRight.x + textureOffset.x + textureSize.width), Float(bottomRight.y + textureOffset.y))) 
    textCords.append(vector_float2(Float(bottomLeft.x + textureOffset.x + textureSize.width), Float(bottomLeft.y + textureOffset.y))) 
    textCords.append(vector_float2(Float(topLeft.x + textureOffset.x + textureSize.width), Float(topLeft.y + textureOffset.y))) 
    textCords.append(vector_float2(Float(topRight.x + textureOffset.x + textureSize.width), Float(topRight.y + textureOffset.y))) 
} 

回答

1

顶点位置和所有相关属性形成一个记录。这意味着,如果一个顶点位置必须多次使用,并且具有不同的纹理坐标,则必须将每个纹理坐标的顶点位置添加到缓冲区中一次。将元素数组与纹理坐标关联是不可能的。
你必须创建与4个顶点的顶点位置缓冲器为立方体的每一侧,并与为立方体的每一侧4个纹理坐标的纹理坐标缓冲器:

texureCoordsSide =[ 
    vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)), 
    vector_float2(Float(bottomRight.x), Float(bottomRight.y)), 
    vector_float2(Float(topRight.x), Float(topRight.y)), 
    vector_float2(Float(topLeft.x), Float(topLeft.y))] 

// Front Face 
vertices += [startFace.bottomLeft, startFace.bottomRight, startFace.topRight, startFace.topLeft]; 
textCords += texureCoordsSide 

// Left Face 
vertices += [endFace.bottomLeft, startFace.bottomLeft, startFace.topLeft, endFace.topLeft]; 
textCords += texureCoordsSide 

// Top Face 
vertices += [startFace.topLeft, startFace.topRight, endFace.topRight, endFace.topLeft]; 
textCords += texureCoordsSide 

// Right Face 
vertices += [startFace.bottomRight, endFace.bottomRight, endFace.topRight, startFace.topRight]; 
textCords += texureCoordsSide 

// Bottom Face 
vertices += [endFace.bottomRight, endFace.bottomLeft, startFace.bottomLeft, startFace.bottomRight]; 
textCords += texureCoordsSide 

// Back Face 
vertices += [endFace.bottomRight, endFace.bottomLeft, endFace.topLeft, endFace.topRight]; 
textCords += texureCoordsSide 

的元件阵列(indices)具有至包含从0到23的连续顺序的24个索引(立方体的6个边中的每一个4个)。

+0

非常感谢!我更新了我的代码,这完美运作 – harryisaac