Как правильно использовать NSImage в качестве материала формы SCNGeometry? - PullRequest
1 голос
/ 27 апреля 2019

В университете я получил задание добавить изображение в качестве текстуры в октаэдр SCNGeometry.Это мой первый проект в Swift.

Существует множество советов по UIKit с классом UIImage, но я использую AppKit для macos и класса NSImage.И ни один из вариантов, которые я нашел в Интернете, еще не работал для меня.Возможно, я неправильно понимаю что-то фундаментальное.Ну, во-первых, я перетащил изображение с именем "sims.jpg" в папку своего проекта и в папку art.scnassets.А также добавил их с помощью меню «Файл» → «Добавить файлы» в «art.scnassets» и общую папку.И ничего не сделал с Assets.xcassets.

Тогда вот как создается фигура:

func createOctahedron() {

   let vertices: [SCNVector3] = [
       SCNVector3(0, 1, 0),
       SCNVector3(-0.5, 0, 0.5),
       SCNVector3(0.5, 0, 0.5),
       SCNVector3(0.5, 0, -0.5),
       SCNVector3(-0.5, 0, -0.5),
       SCNVector3(0, -1, 0)
   ]

   let source = SCNGeometrySource(vertices: vertices)

   let indices: [UInt16] = [
       0, 1, 2,
       2, 3, 0,
       3, 4, 0,
       4, 1, 0,
       1, 5, 2,
       2, 5, 3,
       3, 5, 4,
       4, 5, 1
   ]

   let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)
   let geometry = SCNGeometry(sources: [source], elements: [element])
   let node = SCNNode(geometry: geometry)

   node.geometry?.firstMaterial?.diffuse.contents = NSColor.green // назначаем цвет октаэдру

   let scnView = self.view as! SCNView
   scnView.scene?.rootNode.addChildNode(node)

   let rotateAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: .pi, z: 0, duration: 5))
   node.runAction(rotateAction)
}

На всякий случай позвольте мне оставить полный код

Итак, я бы добавил изображение вот так

let imageMaterial = SCNMaterial()
let image = NSImage.Name("sims")
imageMaterial.diffuse.contents = image
geometry.materials = [imageMaterial, imageMaterial, imageMaterial, imageMaterial, imageMaterial, imageMaterial, imageMaterial, imageMaterial]

Или, может быть, так?

node.geometry?.firstMaterial?.diffuse.contents = NSImage.Name("sims")

Или мне как-то дополнительно сопоставить его?Помогите мне, пожалуйста, потому что я действительно не понимаю.Xcode выводит только вращающийся октаэдр без дополнительной текстуры, без ошибок либо

Ответы [ 2 ]

1 голос
/ 04 мая 2019

Я узнал, о чем идет речь. Там не было текстуры из-за отсутствия УФ-картирования. Я должен был объявить массив 2d координат на отрезке [0, 1] с помощью CGPoint, а затем добавить его в массив source.

Вот как это выглядит примерно:

         let width:CGFloat = 1/8
         let coordinates: [CGPoint] = [
         CGPoint(x: 0,     y: 0),// BAC
         CGPoint(x: width, y: 0),
         CGPoint(x: width, y: 1),
         CGPoint(x: 0,     y: 1),// BAE
         CGPoint(x: width * 7, y: 0),
         CGPoint(x: 1,         y: 0),
         CGPoint(x: 1,         y: 1),// EDA
         CGPoint(x: width * 7, y: 1),
         CGPoint(x: width * 6, y: 0),
         CGPoint(x: width * 7, y: 0),// DAC
         CGPoint(x: width,     y: 0),
         CGPoint(x: width * 4, y: 0),
         CGPoint(x: width * 7, y: 1),// DFC
         CGPoint(x: width * 6, y: 1),
         CGPoint(x: width * 4, y: 1),
         CGPoint(x: width,     y: 1),// BFC
         CGPoint(x: width * 4, y: 0),
         CGPoint(x: width * 5, y: 0),
         CGPoint(x: width * 5, y: 1),// BFE
         CGPoint(x: width * 6, y: 1),
         CGPoint(x: width * 5, y: 0),
         CGPoint(x: width * 6, y: 0),// EFD
         CGPoint(x: width * 4, y: 1),
         CGPoint(x: width * 5, y: 1),
         ]

        let source = [
            SCNGeometrySource(vertices: vertices),
            SCNGeometrySource(textureCoordinates: coordinates)
        ]
        let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)

        let octahedron = SCNGeometry(sources: source, elements: [element])

После того, как мы указали координаты, достаточно записать следующее:

        let image = NSImage(named: NSImage.Name("sims"))
        octahedron.firstMaterial?.diffuse.contents = image

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

1 голос
/ 27 апреля 2019

Эта строка здесь:

let image = NSImage.Name("sims")

Только объявляет имя.Вам необходимо:

let image = NSImage(named: NSImage.Name("sims"))

Причина, по которой ваш код компилируется, состоит в том, что свойство contents имеет тип Any?, поэтому вы можете поместить в него любую старую липучку.Это молча терпит неудачу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...