2017-09-23 5 views
0

Dans SceneKit, j'essaie de créer une simple pièce de géométrie personnalisée avec une texture. J'essaye juste de faire un cube mais ai chaque visage orienté correctement ainsi un SCNBox ne fonctionnera pas.SceneKit Texture de géométrie personnalisée incorrecte

La forme sort parfaitement bien, mais la texture est totalement erronée.

C'est ce que la géométrie vient à la recherche comme:

enter image description here

D'après ce que je comprends, les coordonnées de texture pour chaque visage doit être le même. Mais quand j'ajoute les points pour chaque visage dans le même ordre, il dessine de manière similaire incorrecte. J'ai donc joué avec l'ordre des coordonnées et j'ai obtenu le recto, le dos et une face pour dessiner la plupart du temps correctement. Je n'ai pas été en mesure de trouver un modèle ou une logique à ce qui a causé cela.

L'avant est à l'image de tous les visages.

Voilà comment je le fais:

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

Solution

obtenu ce travail, voici mon code pour une version de travail:

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

Répondre

1

Une position de sommet et tous les attributs associés forment un enregistrement. Cela signifie que si une position de sommet doit être utilisée plus d'une fois, avec des coordonnées de texture différentes, la position du sommet doit être ajoutée au tampon une fois pour chaque coordonnée de texture. Il n'est pas possible d'associer le tableau d'éléments à une coordonnée de texture.
il faut créer un tampon de position de sommet avec 4 sommets de chaque côté du cube et une texture de coordonnées tampon avec quatre coordonnées de texture pour chaque face du cube:

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 

le groupement d'éléments (indices) présente à contenir les 24 indices (4 pour chacun des 6 côtés du cube) dans l'ordre consciente de 0 à 23.

+0

Merci beaucoup! J'ai mis à jour mon code et cela a fonctionné parfaitement – harryisaac