4 点之间的 Scenekit 形状
Scenekit shape between 4 points
鉴于我在上一个问题中所走的路线:
ARKit - place a SCNPlane between 2 vector points on a plane in Swift 3
...似乎有缺陷,我正在寻找其他选择。我可以在 2 个节点之间画一条线,然后我可以在这些节点之上创建节点,有效地在一个正方形中,但即使我在它们之间画线,我也无法将其变成一个形状。是否可以在 Scenekit 中绘制一个形状(正方形),其中 4 个角中的每一个都连接到一个节点。
我可以创建一个平面,将其放置在一个节点上,变换轴心然后旋转,但它并不总是有效,但 SCNGeometry 线可以。
谢谢
所以答案,至少我的解决方案是使用 SCNGeometry 三角形。我想要一个正方形(而不是立方体)作为增强现实中的墙,所以我使用映射墙的 4 个角的 4 个节点简单地构建了 2 个三角形。
class构建三角形:
extension SCNGeometry {
class func triangleFrom(vector1: SCNVector3, vector2: SCNVector3, vector3: SCNVector3) -> SCNGeometry {
let indices: [Int32] = [0, 1, 2]
let source = SCNGeometrySource(vertices: [vector1, vector2, vector3])
let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)
return SCNGeometry(sources: [source], elements: [element])
}
}
2 个三角形的点是 [p1, p2, p4] 和 [p1, p3, p4],调用方式如下:
let thirdPoint = firstPoint.clone()
thirdPoint.position = SCNVector3Make(thirdPoint.position.x,
thirdPoint.position.y + Float(1.5), thirdPoint.position.z)
sceneView.scene.rootNode.addChildNode(thirdPoint)
let fourthPoint = secondPoint.clone()
fourthPoint.position = SCNVector3Make(fourthPoint.position.x,
fourthPoint.position.y + Float(1.5), fourthPoint.position.z)
sceneView.scene.rootNode.addChildNode(fourthPoint)
let triangle = SCNGeometry.triangleFrom(vector1: firstPoint.position, vector2: secondPoint.position, vector3: fourthPoint.position)
let triangleNode = SCNNode(geometry: triangle)
triangleNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
triangleNode.geometry?.firstMaterial?.isDoubleSided = true
sceneView.scene.rootNode.addChildNode(triangleNode)
let triangle2 = SCNGeometry.triangleFrom(vector1: firstPoint.position, vector2: thirdPoint.position, vector3: fourthPoint.position)
let triangle2Node = SCNNode(geometry: triangle2)
triangle2Node.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
triangle2Node.geometry?.firstMaterial?.isDoubleSided = true
sceneView.scene.rootNode.addChildNode(triangle2Node)
这一切都是基于通过在 ARKit 中选择墙的底部 2 个点来创建 2 个初始节点。
希望这对搜索类似答案的其他人有意义。
编辑:添加 Material
这里有一个稍微不同的扩展和添加 material 的代码,墙的最终结果保持不变:
extension SCNGeometry {
class func Quad() -> SCNGeometry {
let verticesPosition = [
SCNVector3(x: -0.242548823, y: -0.188490361, z: -0.0887458622),
SCNVector3(x: -0.129298389, y: -0.188490361, z: -0.0820985138),
SCNVector3(x: -0.129298389, y: 0.2, z: -0.0820985138),
SCNVector3(x: -0.242548823, y: 0.2, z: -0.0887458622)
]
let textureCord = [
CGPoint(x: 1, y: 1),
CGPoint(x: 0, y: 1),
CGPoint(x: 0, y: 0),
CGPoint(x: 1, y: 0),
]
let indices: [CInt] = [
0, 2, 3,
0, 1, 2
]
let vertexSource = SCNGeometrySource(vertices: verticesPosition)
let srcTex = SCNGeometrySource(textureCoordinates: textureCord)
let date = NSData(bytes: indices, length: MemoryLayout<CInt>.size * indices.count)
let scngeometry = SCNGeometryElement(data: date as Data,
primitiveType: SCNGeometryPrimitiveType.triangles, primitiveCount: 2,
bytesPerIndex: MemoryLayout<CInt>.size)
let geometry = SCNGeometry(sources: [vertexSource,srcTex],
elements: [scngeometry])
return geometry
}
}
然后只需在 viewDidLoad() 中调用它并应用 material
let scene = SCNScene()
let quad = SCNGeometry.Quad()
let (min, max) = quad.boundingBox
let width = CGFloat(max.x - min.x)
let height = CGFloat(max.y - min.y)
quad.firstMaterial?.diffuse.contents = UIImage(named: "wallpaper.jpg")
quad.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(Float(width), Float(height), 1)
quad.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat
quad.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat
let node = SCNNode()
node.geometry = quad
scene.rootNode.addChildNode(node)
sceneView.scene = scene
鉴于我在上一个问题中所走的路线:
ARKit - place a SCNPlane between 2 vector points on a plane in Swift 3
...似乎有缺陷,我正在寻找其他选择。我可以在 2 个节点之间画一条线,然后我可以在这些节点之上创建节点,有效地在一个正方形中,但即使我在它们之间画线,我也无法将其变成一个形状。是否可以在 Scenekit 中绘制一个形状(正方形),其中 4 个角中的每一个都连接到一个节点。
我可以创建一个平面,将其放置在一个节点上,变换轴心然后旋转,但它并不总是有效,但 SCNGeometry 线可以。
谢谢
所以答案,至少我的解决方案是使用 SCNGeometry 三角形。我想要一个正方形(而不是立方体)作为增强现实中的墙,所以我使用映射墙的 4 个角的 4 个节点简单地构建了 2 个三角形。
class构建三角形:
extension SCNGeometry {
class func triangleFrom(vector1: SCNVector3, vector2: SCNVector3, vector3: SCNVector3) -> SCNGeometry {
let indices: [Int32] = [0, 1, 2]
let source = SCNGeometrySource(vertices: [vector1, vector2, vector3])
let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)
return SCNGeometry(sources: [source], elements: [element])
}
}
2 个三角形的点是 [p1, p2, p4] 和 [p1, p3, p4],调用方式如下:
let thirdPoint = firstPoint.clone()
thirdPoint.position = SCNVector3Make(thirdPoint.position.x,
thirdPoint.position.y + Float(1.5), thirdPoint.position.z)
sceneView.scene.rootNode.addChildNode(thirdPoint)
let fourthPoint = secondPoint.clone()
fourthPoint.position = SCNVector3Make(fourthPoint.position.x,
fourthPoint.position.y + Float(1.5), fourthPoint.position.z)
sceneView.scene.rootNode.addChildNode(fourthPoint)
let triangle = SCNGeometry.triangleFrom(vector1: firstPoint.position, vector2: secondPoint.position, vector3: fourthPoint.position)
let triangleNode = SCNNode(geometry: triangle)
triangleNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
triangleNode.geometry?.firstMaterial?.isDoubleSided = true
sceneView.scene.rootNode.addChildNode(triangleNode)
let triangle2 = SCNGeometry.triangleFrom(vector1: firstPoint.position, vector2: thirdPoint.position, vector3: fourthPoint.position)
let triangle2Node = SCNNode(geometry: triangle2)
triangle2Node.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
triangle2Node.geometry?.firstMaterial?.isDoubleSided = true
sceneView.scene.rootNode.addChildNode(triangle2Node)
这一切都是基于通过在 ARKit 中选择墙的底部 2 个点来创建 2 个初始节点。
希望这对搜索类似答案的其他人有意义。
编辑:添加 Material
这里有一个稍微不同的扩展和添加 material 的代码,墙的最终结果保持不变:
extension SCNGeometry {
class func Quad() -> SCNGeometry {
let verticesPosition = [
SCNVector3(x: -0.242548823, y: -0.188490361, z: -0.0887458622),
SCNVector3(x: -0.129298389, y: -0.188490361, z: -0.0820985138),
SCNVector3(x: -0.129298389, y: 0.2, z: -0.0820985138),
SCNVector3(x: -0.242548823, y: 0.2, z: -0.0887458622)
]
let textureCord = [
CGPoint(x: 1, y: 1),
CGPoint(x: 0, y: 1),
CGPoint(x: 0, y: 0),
CGPoint(x: 1, y: 0),
]
let indices: [CInt] = [
0, 2, 3,
0, 1, 2
]
let vertexSource = SCNGeometrySource(vertices: verticesPosition)
let srcTex = SCNGeometrySource(textureCoordinates: textureCord)
let date = NSData(bytes: indices, length: MemoryLayout<CInt>.size * indices.count)
let scngeometry = SCNGeometryElement(data: date as Data,
primitiveType: SCNGeometryPrimitiveType.triangles, primitiveCount: 2,
bytesPerIndex: MemoryLayout<CInt>.size)
let geometry = SCNGeometry(sources: [vertexSource,srcTex],
elements: [scngeometry])
return geometry
}
}
然后只需在 viewDidLoad() 中调用它并应用 material
let scene = SCNScene()
let quad = SCNGeometry.Quad()
let (min, max) = quad.boundingBox
let width = CGFloat(max.x - min.x)
let height = CGFloat(max.y - min.y)
quad.firstMaterial?.diffuse.contents = UIImage(named: "wallpaper.jpg")
quad.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(Float(width), Float(height), 1)
quad.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat
quad.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat
let node = SCNNode()
node.geometry = quad
scene.rootNode.addChildNode(node)
sceneView.scene = scene