1
votes

Having an issue getting a function to work when trying to setup boundingBox detection in a SCNNode. I'm expecting to be able to call the boundingBox function to detect objects inside a SCNNode and hide/show those objects on a button tap, here is my current state below:

 @IBAction func hideCubeButtonTapped(sender: UIButton) {
    guard let hatNode = hatNode?.presentation.worldPosition else { return }


    for cubeNode in cubeNodes {


        // hide/show cubeNodes in the hat
        if (hatNode.boundingBoxContains(point: cubeNode.presentation.worldPosition)) {
            print("Hide Button Tapped")
            if cubeNode.isHidden == true {
                cubeNode.isHidden = false
            } else {
                cubeNode.isHidden = true
            }
        }
    }
}

which is calling the boundingBox function from this struct and extension:

extension SCNNode {
func boundingBoxContains(point: SCNVector3, in node: SCNNode) -> Bool {
    let localPoint = self.convertPosition(point, from: node)
    return boundingBoxContains(point: localPoint)
}

func boundingBoxContains(point: SCNVector3) -> Bool {
    return BoundingBox(self.boundingBox).contains(point)
}

}

struct BoundingBox { let min: SCNVector3 let max: SCNVector3

init(_ boundTuple: (min: SCNVector3, max: SCNVector3)) {
    min = boundTuple.min
    max = boundTuple.max
}

func contains(_ point: SCNVector3) -> Bool {
    let contains =
        min.x <= point.x &&
            min.y <= point.y &&
            min.z <= point.z &&

            max.x > point.x &&
            max.y > point.y &&
            max.z > point.z

    return contains
}

}

when calling the hatNode.boundingBoxContains this error is showing: "Value of type 'SCNVector3' has no member 'boundingBoxContains'"

the hatNode is not getting set as a SCNVector3? what am i missing here? i'm new to swift so please correct me here!

this code was adapted from this question: How to detect if a specific SCNNode is located inside another SCNNode's boundingBox - SceneKit - iOS

2

2 Answers

2
votes

worldPosition and its siblings, and their simd cousins are newly introduced to SCNNode in iOS11, even it is poorly (or not) documented, you can get some clues in the term "world" itself, and comments in source as below.

/*!
 @abstract Determines the receiver's position in world space (relative to the scene's root node).
 */
@available(iOS 11.0, *)
open var simdWorldPosition: simd_float3

To your problem, there are 2 solutions, but you have to choose one style you preferred. From your code, you were mixing using 2 different coordinate space.

  1. If you choose to use "world" space, you should convert both hat and cube into "world" space. Obviously, your cubes are, but hat not.

  2. If you do not want to bother with world, rather believed in relativity, you can simply convert cube into hat's coordinate/space, using convertPosition or simdConvertPosition at your favorite , before boundingBoxContains

0
votes

In the second line of code you assign the worldPosition (a SCNVector3) to the hatNode variable. So by the time you call boundingBoxContains on hatNode, hatNode is a SCNVector3. Remove .worldPosition from the second line if code so you assign the presentation node to hatNode.