【问题标题】:How do I use an NSImage as material of an SCNGeometry shape correctly?如何正确使用 NSImage 作为 SCNGeometry 形状的材料?
【发布时间】:2019-05-04 20:00:16
【问题描述】:

我在大学接到了一项任务,将图片作为纹理添加到 SCNGeometry 八面体。这是我在 Swift 中的第一个项目。

对于带有 UIImage 类的 UIKit 有很多建议,但我将 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)
}

以防万一让我留下full code

所以,我会像这样添加图像

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 只输出一个旋转的八面体,没有额外的纹理,也没有错误

【问题讨论】:

  • 你的图片不是 NSImage,它是 NSImage.Name。您可以使用该名称通过 NSImage(named: ...) 获取图像

标签: swift xcode macos


【解决方案1】:

这里的这一行:

let image = NSImage.Name("sims")

仅声明名称。你需要:

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

您的代码编译的原因是contents 属性的类型为Any?,因此您可以在该属性中放置任何旧的粘性物。它默默地失败了。

【讨论】:

  • 非常感谢!现在对我来说更有意义了。我改变了这条线,但我的八面体仍然没有纹理。还有什么需要修复或添加的,你觉得呢?
  • 您的资产文件夹中有一个名为“sims”的资产?
  • 是的,但我仍然不确定它是否正确?所以我选择了screenshotone more。请检查它们。它们看起来相关吗?
  • 资产文件夹看起来不错。我想知道 SceneKit 是否不喜欢 JPG 图像。我会 1) 检查您是否使用调试器断点实际实例化了 NSImage 2) 看看使用 PNG 格式图像时会发生什么。
  • 无需将图像粘贴到资产文件夹。将它拖放到 xcode 中的项目文件夹中是可以的。 JPG 图像与 PNG 一样受欢迎。问题是我没有为纹理放置指定足够的数据:我在下面描述了对我有用的方法:)
【解决方案2】:

我发现了这笔交易的内容。由于没有 UV 贴图,因此没有出现纹理。我应该在CGPoint 的帮助下在[0, 1] 段上声明一个二维坐标数组,然后将其添加到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

并且图像将在八面体的面上拉伸。 附上full code

【讨论】:

    猜你喜欢
    • 2017-12-10
    • 2021-07-08
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 2017-12-08
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多