I want to be able to center fit a 3D model inside a SK3DNode. I have the following code:
public extension SK3DNode {
static func forModel(_ model: SCNNode, size: CGSize) -> SK3DNode {
let scene = SCNScene()
let node3D = SK3DNode()
node3D.scnScene = scene
node3D.viewportSize = size
scene.rootNode.addChildNode(model)
let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
node3D.pointOfView = cameraNode
cameraNode.constraints = [SCNLookAtConstraint(target: model)]
// TODO: adjust position to center fit the model
cameraNode.position = SCNVector3(x: 0, y: 0, z: 4)
return node3D
}
}
I have done the following:
let planeX = model.boundingSize.x
let planeY = model.boundingSize.y
let planeLength = max(planeX, planeY)
let angleInRadian = NumberUtil.degreeToRadian(degree: camera.fieldOfView)
let distance = planeLength / 2 / tan(angleInRadian/2)
I got the above calculation based on the picture in this answer: Camera position based on model size?
This seems to be close to what I want, but it doesn’t consider the size and aspect ratio of the viewport in the calculation, so I don’t think it’s correct. Is there a better way to compute this?
EDIT:
Here you can download a sample project: https://drive.google.com/file/d/1W_v0jMR1w9SkP-__SlKcPfiRF9cpTyEb/view?usp=sharing
When you run it, you will see 4 SK3DNode
s (see the 4 blue areas in the screenshot below), and they are (from top to bottom):
- A tall viewport with a wide 3d model inside
- A tall viewport with a tall 3d model inside
- A wide viewport with a tall 3d model inside
- A wide viewport with a wide 3d model inside
I want to control the camera so that all 3D models will appear to "center fit" the viewport.
2
Answers
I came up with the solution: I need to set the
projectionDirection
based on the model's aspect ratio and the viewport's aspect ratio.For example, this code below sets the models (white boxes) to center fit the viewports (blue windows) with a padding of 20%.
And as you can see from the result, all the white boxes are scaled to center fit the blue viewport, with a padding of 20%.
You need to consider the depth of the 3d model while calculating the distance from the camera to the model or it would be calculated from the model center (or origin point) to the camera.
This adjustment would take care of everything
P.S. You don’t need also to be at 90% of the size. you would be perfectly having the model in the camera viewport.
Update:
The full code would be like that:
And Here is the image from the device.