Move camera to fit 3D scene

后端 未结 6 999
别跟我提以往
别跟我提以往 2020-12-01 00:37

I\'m looking for an algorithm to fit a bounding box inside a viewport (in my case a DirectX scene). I know about algorithms for centering a bounding sphere in a orthographic

6条回答
  •  没有蜡笔的小新
    2020-12-01 01:06

    I know there are some excellent answers above, but I wanted to add a rediculously simple solution to fit the bounding sphere inside the camera frustrum. It makes the assumption that you want to keep the camera Target and Forward vector the same, and simply adjust camera distance to target.

    Note, this won't give you the best fit but it will give you an approximate fit, showing all geometry, and only in a few lines of code, and without screen to world transformations

    // Compute camera radius to fit bounding sphere
    // Implementation in C#
    // 
    
    // Given a bounding box around your scene
    BoundingBox bounds = new BoundingBox();
    
    // Compute the centre point of the bounding box
    // NOTE: The implementation for this is to take the mid-way point between 
    // two opposing corners of the bounding box
    Vector3 center = bounds.Center;
    
    // Find the corner of the bounding box which is maximum distance from the 
    // centre of the bounding box. Vector3.Distance computes the distance between 
    // two vectors. Select is just nice syntactic sugar to loop 
    // over Corners and find the max distance.
    double boundSphereRadius = bounds.Corners.Select(x => Vector3.Distance(x, bounds.Center)).Max();
    
    // Given the camera Field of View in radians
    double fov = Math3D.DegToRad(FieldOfView);
    
    // Compute the distance the camera should be to fit the entire bounding sphere
    double camDistance = (boundSphereRadius * 2.0) / Math.Tan(fov / 2.0);
    
    // Now, set camera.Target to bounds.Center
    // set camera.Radius to camDistance
    // Keep current forward vector the same
    

    The implementation of BoundingBox in C# is found below. The important points are the Centre and Corners properties. Vector3 is a pretty standard implementation of a 3 component (X,Y,Z) vector

    public struct BoundingBox
    {        
        public Vector3 Vec0;
        public Vector3 Vec1;
    
        public BoundingBox(Vector3 vec0, Vector3 vec1)
        {
            Vec0 = vec0;
            Vec1 = vec1;
        }
    
        public Vector3 Center
        {
            get { return (Vec0 + Vec1)*0.5; }
        }
    
        public IList Corners
        {
            get
            {
                Vector3[] corners = new[]
                {
                    new Vector3( Vec0.X, Vec0.Y, Vec0.Z ), 
                    new Vector3( Vec1.X, Vec0.Y, Vec0.Z ), 
                    new Vector3( Vec0.X, Vec1.Y, Vec0.Z ), 
                    new Vector3( Vec0.X, Vec0.Y, Vec1.Z ), 
                    new Vector3( Vec1.X, Vec1.Y, Vec0.Z ), 
                    new Vector3( Vec1.X, Vec0.Y, Vec1.Z ), 
                    new Vector3( Vec0.X, Vec1.Y, Vec1.Z ), 
                    new Vector3( Vec1.X, Vec1.Y, Vec1.Z ), 
                };
    
                return corners;
            }
        } 
    }
    

提交回复
热议问题