Example #1
0
        public static PerspectiveCamera CreateFromBounds(AxisAlignedBox3D bounds, Viewport3D viewport,
			float fieldOfView, float yaw = 0.0f, float pitch = 0.0f, float zoom = 1.0f)
        {
            // Calculate initial guess at camera settings.
            Matrix3D transform = Matrix3D.CreateFromYawPitchRoll(yaw, pitch, 0);
            Vector3D cameraDirection = Vector3D.Normalize(transform.Transform(Vector3D.Forward));
            PerspectiveCamera initialGuess = new PerspectiveCamera
            {
                FieldOfView = fieldOfView,
                NearPlaneDistance = 1.0f,
                FarPlaneDistance = bounds.Size.Length() * 10,
                Position = bounds.Center - cameraDirection * bounds.Size.Length() * 2,
                LookDirection = cameraDirection,
                UpDirection = Vector3D.Up
            };

            Matrix3D projection = initialGuess.GetProjectionMatrix(viewport.AspectRatio);
            Matrix3D view = initialGuess.GetViewMatrix();

            // Project bounding box corners onto screen, and calculate screen bounds.
            float closestZ = float.MaxValue;
            Box2D? screenBounds = null;
            Point3D[] corners = bounds.GetCorners();
            foreach (Point3D corner in corners)
            {
                Point3D screenPoint = viewport.Project(corner,
                    projection, view, Matrix3D.Identity);

                if (screenPoint.Z < closestZ)
                    closestZ = screenPoint.Z;

                IntPoint2D intScreenPoint = new IntPoint2D((int) screenPoint.X, (int) screenPoint.Y);
                if (screenBounds == null)
                    screenBounds = new Box2D(intScreenPoint, intScreenPoint);
                else
                {
                    Box2D value = screenBounds.Value;
                    value.Expand(intScreenPoint);
                    screenBounds = value;
                }
            }

            // Now project back from screen bounds into scene, setting Z to the minimum bounding box Z value.
            IntPoint2D minScreen = screenBounds.Value.Min;
            IntPoint2D maxScreen = screenBounds.Value.Max;
            Point3D min = viewport.Unproject(new Point3D(minScreen.X, minScreen.Y, closestZ),
                projection, view, Matrix3D.Identity);
            Point3D max = viewport.Unproject(new Point3D(maxScreen.X, maxScreen.Y, closestZ),
                projection, view, Matrix3D.Identity);

            // Use these new values to calculate the distance the camera should be from the AABB centre.
            Vector3D size = Vector3D.Abs(max - min);
            float radius = size.Length();
            float dist = radius / (2 * MathUtility.Tan(fieldOfView * viewport.AspectRatio / 2));

            Point3D closestBoundsCenter = (min + (max - min) / 2);
            Point3D position = closestBoundsCenter - cameraDirection * dist * (1 / zoom);

            return new PerspectiveCamera
            {
                FieldOfView = fieldOfView,
                NearPlaneDistance = 1.0f,
                FarPlaneDistance = dist * 10,
                Position = position,
                LookDirection = cameraDirection,
                UpDirection = Vector3D.Up
            };
        }
Example #2
0
 public static Box2D Union(Box2D box1, Box2D box2)
 {
     return(new Box2D(
                new IntPoint2D(Math.Min(box1.Min.X, box2.Min.X), Math.Min(box1.Min.Y, box2.Min.Y)),
                new IntPoint2D(Math.Max(box1.Max.X, box2.Max.X), Math.Max(box1.Max.Y, box2.Max.Y))));
 }
Example #3
0
 public static Box2D Union(Box2D box1, Box2D box2)
 {
     return new Box2D(
         new IntPoint2D(Math.Min(box1.Min.X, box2.Min.X), Math.Min(box1.Min.Y, box2.Min.Y)),
         new IntPoint2D(Math.Max(box1.Max.X, box2.Max.X), Math.Max(box1.Max.Y, box2.Max.Y)));
 }