两点之间的 SceneKit 对象

SceneKit Object between two points

给定 2 个 3D 点(ab)和一个 SCNCapsule、SCNTorus、SCNTube 等, 如何定位对象,使对象从 a 点开始并在 b 点结束?

Swift 或 Objective-C 中的代码示例将不胜感激。

根据 Moustachs 的回答,我设法做了一个二维解决方案:

var v1 = SCNVector3(x: Float(a.x), y: Float(a.y), z: 0.0)
var v2 = SCNVector3(x: Float(b.x), y: Float(b.y), z: 0.0)

let height = CGFloat(v1.distance(v2))
var capsule = SCNCapsule(capRadius: 0.1, height: height)

var node = SCNNode(geometry: capsule)

var midpoint = (v1 + v2) / 2.0

node.position = midpoint

var rotp = v2 - midpoint

let rotx = atan2( rotp.y, rotp.x )
node.eulerAngles = SCNVector3Make(0.0, 0.0, rotx)

self.addChildNode(node)

我知道,完整的三维旋转有无数种解法,但我不关心第三轴。尽管如此,似乎即使是第二轴旋转也不适合我。也许我的数学让我望而却步。任何人都可以告诉我如何将此代码提升为 3D space?

(我正在使用 Swift 和 Kim Pedersens SCNVector3Extensions:https://github.com/devindazzle/SCNVector3Extensions

没有容易的方法,但也不应该那么难。您应该实现一个算法,该算法经过以下步骤:

  • 获取 A 和 B 的位置为 SCNVector3
  • 计算出这些矢量点之间的距离、中点和角度(这是基本的矢量数学,你可以在网上找到很多代码示例)
  • 创建您想要的任何形状,大小如下:(假设 d 是之前找到的距离)。
    • 对于SCNCapsuleSCNTube,将height设置为距离
    • 对于SCNTorus,将ringRadius设置为d/2-pipeRadius
    • 对于SCNBox,将任意一侧设置为d
  • 将该形状移动到您之前找到的中间点
  • 使用点之间的角度旋转形状(您可能需要调整轴)

完成后,您创建的形状应该与两端的点相交。您可以使用边界框检查这是否正确,确保右轴等于距离。

我没有代码示例,但请尝试一下,如果它不起作用,我可以为您调试。

我有好消息要告诉你!你可以 link 两个点,然后在这个 Vector 上放一个 SCNNode !

拿着这个,享受两点之间的画线!

class   CylinderLine: SCNNode
{
    init( parent: SCNNode,//Needed to line to your scene
        v1: SCNVector3,//Source
        v2: SCNVector3,//Destination
        radius: CGFloat,// Radius of the cylinder
        radSegmentCount: Int, // Number of faces of the cylinder
        color: UIColor )// Color of the cylinder
    {
        super.init()

        //Calcul the height of our line
        let  height = v1.distance(v2)

        //set position to v1 coordonate
        position = v1

        //Create the second node to draw direction vector
        let nodeV2 = SCNNode()

        //define his position
        nodeV2.position = v2
        //add it to parent
        parent.addChildNode(nodeV2)

        //Align Z axis
        let zAlign = SCNNode()
        zAlign.eulerAngles.x = CGFloat(M_PI_2)

        //create our cylinder
        let cyl = SCNCylinder(radius: radius, height: CGFloat(height))
        cyl.radialSegmentCount = radSegmentCount
        cyl.firstMaterial?.diffuse.contents = color

        //Create node with cylinder
        let nodeCyl = SCNNode(geometry: cyl )
        nodeCyl.position.y = CGFloat(-height/2)
        zAlign.addChildNode(nodeCyl)

        //Add it to child
        addChildNode(zAlign)

        //set constraint direction to our vector
        constraints = [SCNLookAtConstraint(target: nodeV2)]
    }

    override init() {
        super.init()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

private extension SCNVector3{
    func distance(receiver:SCNVector3) -> Float{
        let xd = receiver.x - self.x
        let yd = receiver.y - self.y
        let zd = receiver.z - self.z
        let distance = Float(sqrt(xd * xd + yd * yd + zd * zd))

        if (distance < 0){
            return (distance * -1)
        } else {
            return (distance)
        }
    }
}