我希望能够将 3D 模型居中放置在 SK3DNode 内。我有以下代码:
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
}
}
我已完成以下操作:
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)
我根据这个答案中的图片得到了上述计算:基于模型尺寸的相机位置?
这似乎很接近我想要的,但它在计算时没有考虑视口的大小和长宽比,所以我认为它不正确。有没有更好的方法来计算这个?
计算相机到模型的距离时需要考虑 3D 模型的深度,或者从模型中心(或原点)到相机计算距离。 这个调整会解决一切问题
附注您不需要也达到 90% 的大小。您将完美地将模型显示在相机视口中。
// get the boundingBox aka maximun size of X Y Z of the model (no need for /0.9)
let planeX = model.boundingBox.max.x
let planeY = model.boundingBox.max.y
// you need planZ to get the depth of the 3d model for accurate
// distance calculation
let planeZ = model.boundingBox.max.z
let planeLength = max(planeX, planeY)
// to convert to radian you can multiply the angle to (.pi/180)
let angleInRadian = cameraNode.camera!.fieldOfView * (.pi/180)
// this is the distance from the center of the 3d model to the camera
let distance = planeLength / 2 / tan(angleInRadian/2)
// you have to add half the depth of the 3d model to it
let actualDistance = distance + (planeZ/2)
cameraNode.position = SCNVector3(x: 0, y: 0, z: actualDistance)