4

I have 2 SCNSphere and I want to "link" them with a SCNCylinder (something like this O<->O) but I cannot achieve it I tried using SCNNode pivot property applying rotations, the lookAt(_:) but none of them allow me to achieve what I want.

As a constraint, I want the cylinder to be child of the first sphere for architecture reasons.

Let's say we have a trivial case, first and second sphere have a radius of 0.1 and no rotation is applied to them, only the position is relevant :

static func createSphere(position: SCNVector3, color: UIColor = .red) -> SCNNode {
    let shape = SCNSphere(radius: 0.1)
    shape.firstMaterial?.diffuse.contents = color
    let node = SCNNode(geometry: shape)
    node.position = position
    return node
}

And to create the "link node" :

static func createCylinder(position: SCNVector3, color: UIColor = .green) -> SCNNode {
    let shape = SCNCylinder(radius: 0.2, height: 1.0)
    shape.firstMaterial?.diffuse.contents = color
    let node = SCNNode(geometry: shape)
    node.position = position
    return node
}

All being used like this :

 /// Create a sphere and the related link if there is a next sphere
 static func createPOI(position: SCNVector3, nextPosition: SCNVector3? = nil) -> SCNNode {
    var node: SCNNode = createSphere(position: position, color: .black)

    if let nextPosition = nextPosition {
        let lineNode = createLine(position: SCNVector3.zero, targetPosition: nextPosition)
        node.addChildNode(lineNode)
    }

    return node
}


static func createLine(position: SCNVector3, targetPosition: SCNVector3) -> SCNNode {
    let node = createCylinder(position: position)

    //step 1: handle rotation
    node.position = position
    //node.look(at: targetPosition)
    node.eulerAngles.x = Float.pi/2
    node.eulerAngles.y = atan2f(targetPosition.y, targetPosition.magnitude)

    //step 2: handle scaling and positioning
    node.pivot = SCNMatrix4MakeTranslation(-0.5, 0, 0)
    let width = CGFloat((targetPosition - position).magnitude)
    (node.geometry as? SCNCylinder)?.height = width

    //TODO: Cylinder should link source and target nodes
    //Tried a lot of things above but didn't manage to do it

    return node
}
michael-martinez
  • 767
  • 6
  • 24
  • You will probably get your answer here: https://stackoverflow.com/questions/30827401/cylinder-orientation-between-two-points-on-a-sphere-scenekit-quaternions-ios/41526915#41526915 – SWAT May 23 '18 at 08:53

0 Answers0