I'm downloading Collada DAE scenes and rendering them in SceneKit, but having trouble getting the downloaded node to "fit" within its parent node. I mainly care about scaling it's y-height to fit in the parent node.
Here's the code I'm using:
// Reset everything
node.position = SCNVector3(0, 0, 0)
node.pivot = SCNMatrix4Identity
node.scale = SCNVector3(1, 1, 1)
// Calculate absolute bounding box
let (min, max) = node.boundingBox
let size = max - min
// Get the biggest dimension of the node
guard let scaleRef = [size.x, size.y, size.z].max() else {
return
}
// Desired bounding box is of size SCNVector3(0.4, 0.4, 0.4)
let parentSize: Float = 0.4
let ratio = (parentSize/scaleRef)
node.scale = SCNVector3(node.scale.x * ratio, node.scale.y * ratio, node.scale.z * ratio)
//Correctly position the node at the bottom of its parent node by setting pivot
let (minNode, maxNode) = node.boundingBox
let dx = (maxNode.x - minNode.x) / 2
let dy = minNode.y
let dz = (maxNode.z - minNode.z) / 2
node.pivot = SCNMatrix4Translate(node.pivot, dx, dy, dz)
node.position.x = dx * ratio
node.position.y = dy * ratio
node.position.z = dz * ratio
This seems to work for most cases, but I'm ending up with a few that scale incorrectly.
For example, this object scales correctly (Poly Astornaut):
MIN: SCNVector3(x: -1.11969805, y: -0.735845089, z: -4.02169418)
MAX: SCNVector3(x: 1.11969805, y: 0.711179018, z: 0.0)
NEW SCALE: SCNVector3(x: 0.099460572, y: 0.099460572, z: 0.099460572)
This one does not (Basketball player):
MIN: SCNVector3(x: -74.8805618, y: 0.0459594727, z: -21.4300499)
MAX: SCNVector3(x: 74.8805618, y: 203.553589, z: 15.6760511)
NEW SCALE: SCNVector3(x: 0.00196552835, y: 0.00196552835, z: 0.00196552835)
Screenshots:
Correct scaling
Incorrect scaling
So what I ended up doing was a little different, as I wanted to scale my asset to exactly the reference size.
.scn
file, going to the Node Inspector tab and looking at the bounding box of the asset I'm working with:func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor)
function. I access mine through the following code:
guard let imageAnchor = anchor as? ARImageAnchor else { return }
let referenceImage = imageAnchor.referenceImage
print(referenceImage.physicalSize.width)
print(referenceImage.physicalSize.height)
let threeDimensionalAssetToRealReferenceImageScale = referenceImageWidth / threeDimensionalAssetBoundingBoxWidth
scale
on your SCNNode
I wrote this up, as I was very confused with this situation, I hope it helps someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With