代码之家  ›  专栏  ›  技术社区  ›  harryisaac

SceneKit自定义几何体纹理错误

  •  0
  • harryisaac  · 技术社区  · 7 年前

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

    这就是几何体的外观:

    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 回复  |  直到 7 年前
        1
  •  1
  •   Rabbid76    7 年前


    必须创建一个顶点位置缓冲区,立方体每侧有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