gpt4 book ai didi

ios - SceneKit自定义几何纹理错误

转载 作者:行者123 更新时间:2023-11-28 15:18:49 24 4
gpt4 key购买 nike

在 SceneKit 中,我试图创建一个带有纹理的简单自定义几何体。我只是想制作一个立方体,但每个面的方向都正确,因此 SCNBox 将无法工作。

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

这是几何图形的样子:

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

最佳答案

一个顶点位置和所有相关的属性组成一条记录。这意味着,如果必须使用不同的纹理坐标多次使用顶点位置,则必须为每个纹理坐标将顶点位置添加到缓冲区一次。不可能将元素数组与纹理坐标相关联。
您必须为立方体的每一侧创建一个具有 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 个)。

关于ios - SceneKit自定义几何纹理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46383685/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com