1

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

medright
  • 138
  • 10

2 Answers2

2

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

Juguang
  • 621
  • 2
  • 5
  • 15
0

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.

Xartec
  • 2,369
  • 11
  • 22
  • thank you, taking that out did correct that error. the button function stops right above the if statement (hatNode.boundingBoxContains......) and does not hide/show any of the cubeNode objects in the scene. feels like i'm not catching the actual boundingBox of the hatNode object in the scene. – medright Dec 06 '17 at 17:51
  • What do you mean with “stops” right above? Does it throw an exception on a specific line if code? If it doesn’t run passed the first return statement the presentation node is nil. If it does continue passed the return statement but doesnt run the if line inside the for loop then there is no cubeNode in cubeNodes. – Xartec Dec 06 '17 at 18:36