簡體   English   中英

SceneKit自定義幾何紋理錯誤

[英]SceneKit Custom Geometry Texture Wrong

在SceneKit中,我試圖創建一個簡單的自定義幾何圖形,上面帶有紋理。 我只是想制作一個立方體,但每個面都正確定向,因此SCNBox無法正常工作。

形狀完美無瑕,但紋理映射完全錯誤。

幾何圖形如下所示:

在此處輸入圖片說明

根據我的理解,每張臉的紋理坐標應該相同。 但是,當我以相同順序將每個面的點相加時,其繪制方式類似地不正確。 因此,我按照坐標順序進行操作,並正確地繪制了正面,背面和一個側面。 我還無法找出導致這種情況的模式或邏輯。

正面是每張臉的外觀。

這是我的做法:

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

頂點位置和所有相關屬性形成一條記錄。 這意味着,如果必須使用不同紋理紋理坐標多次使用頂點位置,則必須為每個紋理坐標將頂點位置添加到緩沖區一次。 無法將元素數組與紋理坐標關聯。
您必須為多維數據集的每一側創建一個具有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個)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM