如何在SceneKit中定位相机来控制屏幕上3D模型的大小

问题描述 投票:0回答:1

我使用 SK3DNode 在屏幕上显示一些 3D 模型文件。它们的尺寸不同,但我想在屏幕上显示它们或多或少相同的尺寸。

我有以下代码:

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 so that it takes 90% of the viewport size.
    cameraNode.position = VEC3(0, 0, 4)
    
    return node3D
  }
}

我已经完成了以下操作(假设我想要 90% 的大小):

    let planeX = model.boundingSize.x / 0.9
    let planeY = model.boundingSize.y / 0.9
    let planeLength = max(planeX, planeY)
    let angleInRadian = NumberUtil.degreeToRadian(degree: camera.fieldOfView)
    let distance = planeLength / 2 / tan(angleInRadian/2)

我根据这个答案中的图片得到了上述计算:基于模型尺寸的相机位置?

这似乎很接近我想要的,但它在计算时没有考虑视口的大小和长宽比,所以我认为它不正确。有没有更好的方法来计算这个?

ios swift scenekit
1个回答
0
投票

在计算从相机到模型的距离时,您需要考虑 3D 模型的深度,否则将计算从模型中心(或原点)到相机的距离,这样就可以解决所有问题。

    // get the boundingBox aka maximun size of X Y Z of the model
    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)
© www.soinside.com 2019 - 2024. All rights reserved.