0

I have the following code (this can be run by replacing the standard ViewController code in the Game base project for macOS):

    let scene = SCNScene()
    let cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    scene.rootNode.addChildNode(cameraNode)
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
    let lightNode = SCNNode()
    lightNode.light = SCNLight()
    lightNode.light!.type = .omni
    lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
    scene.rootNode.addChildNode(lightNode)
    let ambientLightNode = SCNNode()
    ambientLightNode.light = SCNLight()
    ambientLightNode.light!.type = .ambient
    ambientLightNode.light!.color = NSColor.darkGray
    scene.rootNode.addChildNode(ambientLightNode)

    /* RELEVANT CODE BEGINS */

    let boxGeo = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
    let boxMaterial = SCNMaterial()
    boxMaterial.diffuse.contents = NSColor.gray
    boxGeo.firstMaterial = boxMaterial
    let boxNode = SCNNode(geometry: boxGeo)
    scene.rootNode.addChildNode(boxNode)
    boxNode.name = "box0"

    let sphereGeo = SCNSphere(radius: 0.5)
    let sphereMaterial = SCNMaterial()
    sphereMaterial.diffuse.contents = NSColor.green
    sphereGeo.firstMaterial = sphereMaterial
    let sphereNode = SCNNode(geometry: sphereGeo)
    boxNode.addChildNode(sphereNode)
    sphereNode.name = "sphere0"

    sphereNode.constraints = [SCNConstraint]()

    let distance = SCNDistanceConstraint(target: boxNode)
    distance.minimumDistance = 2.0
    distance.maximumDistance = 5.0
    sphereNode.constraints?.append(distance)

    let ik = SCNIKConstraint.inverseKinematicsConstraint(chainRootNode: boxNode)
    sphereNode.constraints?.append(ik)

    let anim = CABasicAnimation(keyPath: "targetPosition.y")
    anim.fromValue = -2.0
    anim.toValue = 2.0
    anim.duration = 1
    anim.autoreverses = true
    anim.repeatCount = .infinity
    ik.addAnimation(anim, forKey: nil)

    /* RELEVANT CODE ENDS */

    let scnView = self.view as! SCNView
    scnView.scene = scene
    scnView.allowsCameraControl = true
    scnView.showsStatistics = true
    scnView.backgroundColor = NSColor.black

From what I can gather from the documentation, the animation (and yes, the scene kit view animation setting is set to both play and loop in IB) should move the sphere as close as possible to the points 2.0 and -2.0 on the y-axis by rotating the cube. However, the sphere simply stays stationary. I have also tried setting the initial position of the sphere and cube by manipulating their position vectors directly instead of via the distance constraint, but again the animation did nothing.

Additionally, I have attempted to use the distance constraint in combination with the box having a lookAt constraint to make it rotate to constantly look at the sphere - these caused the rendering of the box and sphere to completely freak out.

I feel as though maybe I am missing something in the documentation here, such as another constraint or some kind of transform matrix to setup some kind of initial value. But I have encountered some other issues with constraints, animations and skeletons that is making me begin to believe that there is either a bug or some undocumented aspects of SceneKit.

Louis
  • 135
  • 1
  • 8

1 Answers1

0

You have added the sphereNode as child of the boxNode. If you move the boxNode all childs are also moved and the constraint has no effect.

Stefan
  • 5,203
  • 8
  • 27
  • 51
  • For the IK constraint to work on a node, it needs to be a child of the constraint's effector, right? As in, the target for the IK is the boxNode, the sphereNode is its child and takes the IK as one of its constraints. I'm not aware that I'm moving the box node in the code sample provided, however I can see that the distance constraint does move the sphereNode within the range provided. Without the distance constraint or a position for the sphereNode the sphere sits in the same place as the box and changing the target position also does nothing to either. – Louis Jun 17 '18 at 07:37