Отображение растянутого материала применяется к узлу SCNGeometrySource - PullRequest
1 голос
/ 26 июня 2019

Я создал SCNNode, используя пользовательские выбранные точки SCNVector3, более трех, используя SCNGeometrySource, и применяю материал изображения для отображения очень растянутого материала. Как правильно применить материал на узле SCNGeometrySource.

func getsquareDrawnLineFrom(pos1: SCNVector3,
                            pos2: SCNVector3,
                            pos3: SCNVector3) -> SCNNode {

    let square = SquareplanlineFrom(vector1: pos1, vector2: pos2, vector3: pos3)
    //SCNGeometrySource.Semantic.texcoord
    //SCNGeometrySource.Semantic.normal
    let material = SCNMaterial()
    // material.diffuse.contents = UIColor.lightGray
    material.diffuse.contents = UIImage(named: "grid")
    material.diffuse.contentsTransform = SCNMatrix4MakeScale(32, 32, 0)
    material.diffuse.wrapS = .repeat
    material.diffuse.wrapT = .repeat
    square.materials = [material]
    let square1 = SCNNode(geometry: square)
    square1.name = "tringle"
    return square1
}

// get line geometry between two vectors
func SquareplanlineFrom(vector1: SCNVector3,
              vector2: SCNVector3, vector3: SCNVector3) -> SCNGeometry {
     let normalsPerFace = 3
    let indices: [Int32] = [0, 1, 2]
    let source = SCNGeometrySource(vertices: [vector1, vector2, vector3])
    let normals:[SCNVector3] = [
        vector1,
        vector2,
        vector3].map{[SCNVector3](repeating:$0,count:normalsPerFace)}.flatMap{$0}
    let normalSource = SCNGeometrySource(normals: normals)
    let cgp1 = CGPoint(x: CGFloat(vector1.x), y: CGFloat(vector1.y))
    let cgp2 = CGPoint(x: CGFloat(vector2.x), y: CGFloat(vector2.y))
    let cgp3 = CGPoint(x: CGFloat(vector3.x), y: CGFloat(vector3.y))
    let textcoord = SCNGeometrySource(textureCoordinates: [cgp1,cgp2,cgp3])

    // let texcoord = SCNGeometrySource(textureCoordinates: [])
    // let normalSource = SCNGeometrySource(normals: [vector1, vector2, vector3])

    let element = SCNGeometryElement(indices: indices,
                                     primitiveType: .triangles)
    return SCNGeometry(sources: [source,normalSource,textcoord], elements: [element])
}

enter image description here

1 Ответ

1 голос
/ 26 июня 2019

В вашем случае это проблема масштаба текстуры:

Я не знаю размер вашей модели, но я думаю, что проблема в том, что вы увеличили масштаб, хотя вам нужно уменьшить его, чтобы правильно разместить текстуру.

enter image description here

Совет : размер моей текстуры - 2K квадрата (2048x2048, 72 точек на дюйм).

Вот код (извините, я использовал версию macOS):

func getSquareDrawnLineFrom(pos1: SCNVector3,
                            pos2: SCNVector3,
                            pos3: SCNVector3) -> SCNNode {

    let square = squarePlanLineFrom(vector1: pos1, 
                                    vector2: pos2, 
                                    vector3: pos3)

    let material = SCNMaterial()
    material.diffuse.contents = NSImage.Name("art.scnassets/jaguar.jpg")

    // your scale
    // material.diffuse.contentsTransform = SCNMatrix4MakeScale(32, 32, 0)           

    material.isDoubleSided = true

    material.diffuse.contentsTransform = .init(m11: 0.05, m12: 0,    m13: 0,    m14: 0, 
                                               m21: 0,    m22: 0.05, m23: 0,    m24: 0, 
                                               m31: 0,    m32: 0,    m33: 1,    m34: 0, 
                                               m41: 0,    m42: 0,    m43: 0,    m44: 1)
    material.diffuse.wrapS = .repeat
    material.diffuse.wrapT = .repeat
    square.materials = [material]

    let square1 = SCNNode(geometry: square)
    scene.rootNode.addChildNode(square1)
    square1.name = "triangle"
    return square1
}

func squarePlanLineFrom(vector1: SCNVector3,
                        vector2: SCNVector3,
                        vector3: SCNVector3) -> SCNGeometry {

    let normalsPerFace = 3
    let indices: [Int32] = [0, 1, 2]
    let source = SCNGeometrySource(vertices: [vector1, vector2, vector3])

    let vec = [vector1, vector2, vector3].map { [SCNVector3](repeating: $0,
                                                                 count: normalsPerFace) }.flatMap{ $0 }
    let normals: [SCNVector3] = vec

    let normalSource = SCNGeometrySource(normals: normals)
    let cgp1 = CGPoint(x: CGFloat(vector1.x), y: CGFloat(vector1.y))
    let cgp2 = CGPoint(x: CGFloat(vector2.x), y: CGFloat(vector2.y))
    let cgp3 = CGPoint(x: CGFloat(vector3.x), y: CGFloat(vector3.y))
    let textcoord = SCNGeometrySource(textureCoordinates: [cgp1, cgp2, cgp3])

    let element = SCNGeometryElement(indices: indices,
                               primitiveType: .triangles)

    return SCNGeometry(sources: [source, normalSource, textcoord], 
                      elements: [element])
}


let instance = getSquareDrawnLineFrom(pos1: SCNVector3(x: 0, y: 0, z: 0),
                                      pos2: SCNVector3(x: 8, y: 5, z: 0),
                                      pos3: SCNVector3(x:-8, y: 5, z: 0))

Но иногда это может быть проблемой направления нормалей:

Часто разработчики создают векторыпараллельны поверхности , поэтому текстура растягивается (один ряд пикселей текстуры дублируется по всей поверхности). Но нормали геометрии должны быть перпендикулярны поверхности, а не параллельны .

enter image description here

...