在 SceneKit 中的平面上重复纹理
Repeating a texture over a plane in SceneKit
我有一个 32x32 .png 图像,我想在 SCNPlane 上重复。我得到的代码(见下文)导致图像被拉伸以适应飞机的大小,而不是重复。
代码:
let planeGeo = SCNPlane(width: 15, height: 15)
let imageMaterial = SCNMaterial()
imageMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png")
planeGeo.firstMaterial = imageMaterial
let plane = SCNNode(geometry: planeGeo)
plane.geometry?.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat
plane.geometry?.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat
我修好了。图像似乎被放大了。如果我这样做 imageMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(32, 32, 0)
,图像会重复。
我在 ARKit 中实现平面可视化时遇到了同样的问题。我想将检测到的平面可视化为棋盘图案。我通过创建自定义 SCNNode called a "PlaneNode" with a correctly configured SCNMaterial 来修复它。 material 使用 wrapS, wrapT = .repeat 并根据平面本身的大小正确计算比例。
看起来像这样:
看看下面的代码,内联注释包含解释。
class PlaneNode : SCNNode {
init(planeAnchor: ARPlaneAnchor) {
super.init()
// Create the 3D plane geometry with the dimensions reported
// by ARKit in the ARPlaneAnchor instance
let planeGeometry = SCNPlane(width:CGFloat(planeAnchor.extent.x), height:CGFloat(planeAnchor.extent.z))
// Instead of just visualizing the grid as a gray plane, we will render
// it in some Tron style colours.
let material = SCNMaterial()
material.diffuse.contents = PaintCode.imageOfViewARPlane
//the scale gives the number of times the image is repeated
//ARKit givest the width and height in meters, in this case we want to repeat
//the pattern each 2cm = 0.02m so we divide the width/height to find the number of patterns
//we then round this so that we always have a clean repeat and not a truncated one
let scaleX = (Float(planeGeometry.width) / 0.02).rounded()
let scaleY = (Float(planeGeometry.height) / 0.02).rounded()
//we then apply the scaling
material.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0)
//set repeat mode in both direction otherwise the patern is stretched!
material.diffuse.wrapS = .repeat
material.diffuse.wrapT = .repeat
//apply material
planeGeometry.materials = [material];
//make a node for it
self.geometry = planeGeometry
// Move the plane to the position reported by ARKit
position.x = planeAnchor.center.x
position.y = 0
position.z = planeAnchor.center.z
// Planes in SceneKit are vertical by default so we need to rotate
// 90 degrees to match planes in ARKit
transform = SCNMatrix4MakeRotation(-Float.pi / 2.0, 1.0, 0.0, 0.0);
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(planeAnchor: ARPlaneAnchor) {
guard let planeGeometry = geometry as? SCNPlane else {
fatalError("update(planeAnchor: ARPlaneAnchor) called on node that has no SCNPlane geometry")
}
//update the size
planeGeometry.width = CGFloat(planeAnchor.extent.x)
planeGeometry.height = CGFloat(planeAnchor.extent.z)
//and material properties
let scaleX = (Float(planeGeometry.width) / 0.02).rounded()
let scaleY = (Float(planeGeometry.height) / 0.02).rounded()
planeGeometry.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0)
// Move the plane to the position reported by ARKit
position.x = planeAnchor.center.x
position.y = 0
position.z = planeAnchor.center.z
}
}
你可以从Scene kit viewer学习它假设你的场景kit中有SCNplane
创建场景文件拖一个平面
12英寸的尺寸是0.3048
和select漫反射图像
现在你的图像有 4 个网格,如图所示
我们希望每个盒子都以每英寸显示,所以对于 12 英寸,我们需要 12 盒子 * 12 盒子,因为我们有 12 英寸盒子
计算一下。首先我们需要将 0.3048 米转换为英寸
即米/0.0254答案是12.
但我们需要每个网格显示在每一英寸中,所以我们还需要除以 12 / 4 = 3
现在转到显示 material 检查器并将比例值更改为 3
12寸飞机可以看到12个盒子
希望对您有所帮助
要在 SceneKit 编辑器中执行此操作,请在场景中 select 您的飞机(如果需要,添加一架),然后 select 右上角的 "Material Inspector" 选项卡。然后,在 "Properties" 和 "Diffuse" 下,select 你的纹理。现在,通过单击 "Diffuse" 左侧的克拉展开漫反射部分,然后向下移动到显示 "Scale" 的位置。在这里,您可以增加缩放比例,使纹理看起来重复而不是拉伸。对于这个问题,OP 必须将缩放比例设置为 32x32。
我有一个 32x32 .png 图像,我想在 SCNPlane 上重复。我得到的代码(见下文)导致图像被拉伸以适应飞机的大小,而不是重复。
代码:
let planeGeo = SCNPlane(width: 15, height: 15)
let imageMaterial = SCNMaterial()
imageMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png")
planeGeo.firstMaterial = imageMaterial
let plane = SCNNode(geometry: planeGeo)
plane.geometry?.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat
plane.geometry?.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat
我修好了。图像似乎被放大了。如果我这样做 imageMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(32, 32, 0)
,图像会重复。
我在 ARKit 中实现平面可视化时遇到了同样的问题。我想将检测到的平面可视化为棋盘图案。我通过创建自定义 SCNNode called a "PlaneNode" with a correctly configured SCNMaterial 来修复它。 material 使用 wrapS, wrapT = .repeat 并根据平面本身的大小正确计算比例。
看起来像这样:
看看下面的代码,内联注释包含解释。
class PlaneNode : SCNNode {
init(planeAnchor: ARPlaneAnchor) {
super.init()
// Create the 3D plane geometry with the dimensions reported
// by ARKit in the ARPlaneAnchor instance
let planeGeometry = SCNPlane(width:CGFloat(planeAnchor.extent.x), height:CGFloat(planeAnchor.extent.z))
// Instead of just visualizing the grid as a gray plane, we will render
// it in some Tron style colours.
let material = SCNMaterial()
material.diffuse.contents = PaintCode.imageOfViewARPlane
//the scale gives the number of times the image is repeated
//ARKit givest the width and height in meters, in this case we want to repeat
//the pattern each 2cm = 0.02m so we divide the width/height to find the number of patterns
//we then round this so that we always have a clean repeat and not a truncated one
let scaleX = (Float(planeGeometry.width) / 0.02).rounded()
let scaleY = (Float(planeGeometry.height) / 0.02).rounded()
//we then apply the scaling
material.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0)
//set repeat mode in both direction otherwise the patern is stretched!
material.diffuse.wrapS = .repeat
material.diffuse.wrapT = .repeat
//apply material
planeGeometry.materials = [material];
//make a node for it
self.geometry = planeGeometry
// Move the plane to the position reported by ARKit
position.x = planeAnchor.center.x
position.y = 0
position.z = planeAnchor.center.z
// Planes in SceneKit are vertical by default so we need to rotate
// 90 degrees to match planes in ARKit
transform = SCNMatrix4MakeRotation(-Float.pi / 2.0, 1.0, 0.0, 0.0);
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(planeAnchor: ARPlaneAnchor) {
guard let planeGeometry = geometry as? SCNPlane else {
fatalError("update(planeAnchor: ARPlaneAnchor) called on node that has no SCNPlane geometry")
}
//update the size
planeGeometry.width = CGFloat(planeAnchor.extent.x)
planeGeometry.height = CGFloat(planeAnchor.extent.z)
//and material properties
let scaleX = (Float(planeGeometry.width) / 0.02).rounded()
let scaleY = (Float(planeGeometry.height) / 0.02).rounded()
planeGeometry.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0)
// Move the plane to the position reported by ARKit
position.x = planeAnchor.center.x
position.y = 0
position.z = planeAnchor.center.z
}
}
你可以从Scene kit viewer学习它假设你的场景kit中有SCNplane
创建场景文件拖一个平面
12英寸的尺寸是0.3048
和select漫反射图像
现在你的图像有 4 个网格,如图所示
我们希望每个盒子都以每英寸显示,所以对于 12 英寸,我们需要 12 盒子 * 12 盒子,因为我们有 12 英寸盒子
计算一下。首先我们需要将 0.3048 米转换为英寸
即米/0.0254答案是12.
但我们需要每个网格显示在每一英寸中,所以我们还需要除以 12 / 4 = 3
现在转到显示 material 检查器并将比例值更改为 3
12寸飞机可以看到12个盒子
希望对您有所帮助
要在 SceneKit 编辑器中执行此操作,请在场景中 select 您的飞机(如果需要,添加一架),然后 select 右上角的 "Material Inspector" 选项卡。然后,在 "Properties" 和 "Diffuse" 下,select 你的纹理。现在,通过单击 "Diffuse" 左侧的克拉展开漫反射部分,然后向下移动到显示 "Scale" 的位置。在这里,您可以增加缩放比例,使纹理看起来重复而不是拉伸。对于这个问题,OP 必须将缩放比例设置为 32x32。