Esempio n. 1
0
        /// <summary>
        /// Creates the WorldViewProjection matrix from the perspective of the
        /// light using the cameras bounding frustum to determine what is visible
        /// in the scene.
        /// </summary>
        /// <returns>The WorldViewProjection for the light</returns>
        private static Matrix3D CreateLightViewProjectionMatrix(Model model, Vector3D lightDirection)
        {
            // Matrix with that will rotate in points the direction of the light
            Matrix3D lightRotation = Matrix3D.CreateLookAt(Point3D.Zero, -lightDirection, Vector3D.Up);

            /*// Get the corners of the frustum
             * Point3D[] frustumCorners = _cameraFrustum.GetCorners();
             *
             * // Transform the positions of the corners into the direction of the light
             * for (int i = 0; i < frustumCorners.Length; i++)
             *      frustumCorners[i] = Point3D.Transform(frustumCorners[i], lightRotation);*/

            // Find the smallest box around the points
            //AxisAlignedBoundingBox lightBox = new AxisAlignedBoundingBox(frustumCorners);
            AxisAlignedBox3D lightBox = model.SourceScene.Bounds;

            lightBox.Transform(lightRotation);

            //lightBox = lightBox.Transform(Matrix3D.CreateScale(2f));

            Vector3D boxSize     = lightBox.Max - lightBox.Min;
            Vector3D halfBoxSize = boxSize * 0.5f;

            // The position of the light should be in the center of the back
            // pannel of the box.
            Point3D lightPosition = lightBox.Min + halfBoxSize;

            lightPosition.Z = lightBox.Min.Z;

            // We need the position back in world coordinates so we transform
            // the light position by the inverse of the lights rotation
            lightPosition = Point3D.Transform(lightPosition, Matrix3D.Invert(lightRotation));

            // Create the view matrix for the light
            Matrix3D lightView = Matrix3D.CreateLookAt(lightPosition, -lightDirection, Vector3D.Up);

            // Create the projection matrix for the light
            // The projection is orthographic since we are using a directional light
            Matrix3D lightProjection = Matrix3D.CreateOrthographic(boxSize.X * 2, boxSize.Y * 2, -boxSize.Z, boxSize.Z);

            return(lightView * lightProjection);
        }
Esempio n. 2
0
        public Renderer(Device device, Model model, int width, int height, Transform3D cameraTransform)
        {
            _device          = device;
            _model           = model;
            _cameraTransform = cameraTransform;

            const float fov = MathUtility.PI_OVER_4;

            AxisAlignedBox3D bounds = _model.SourceScene.Bounds;
            Vector3D         max    = bounds.Size;
            float            radius = System.Math.Max(max.X, System.Math.Max(max.Y, max.Z));

            _projection = Matrix3D.CreatePerspectiveFieldOfView(
                fov,
                width / (float)height,
                1.0f, radius * 10);

            float dist = radius / MathUtility.Sin(fov / 2);

            _view = Matrix3D.CreateLookAt(
                bounds.Center + Vector3D.Backward * dist,
                Vector3D.Forward,
                Vector3D.Up);
        }
Esempio n. 3
0
        public float?Intersects(AxisAlignedBox3D box)
        {
            //first test if start in box
            if (Origin.X >= box.Min.X &&
                Origin.X <= box.Max.X &&
                Origin.Y >= box.Min.Y &&
                Origin.Y <= box.Max.Y &&
                Origin.Z >= box.Min.Z &&
                Origin.Z <= box.Max.Z)
            {
                return(0.0f);               // here we concidere cube is full and origine is in cube so intersect at origine
            }
            //Second we check each face
            Vector3D maxT = new Vector3D(-1.0f);

            //Vector3 minT = new Vector3(-1.0f);
            //calcul intersection with each faces
            if (Origin.X < box.Min.X && Direction.X != 0.0f)
            {
                maxT.X = (box.Min.X - Origin.X) / Direction.X;
            }
            else if (Origin.X > box.Max.X && Direction.X != 0.0f)
            {
                maxT.X = (box.Max.X - Origin.X) / Direction.X;
            }
            if (Origin.Y < box.Min.Y && Direction.Y != 0.0f)
            {
                maxT.Y = (box.Min.Y - Origin.Y) / Direction.Y;
            }
            else if (Origin.Y > box.Max.Y && Direction.Y != 0.0f)
            {
                maxT.Y = (box.Max.Y - Origin.Y) / Direction.Y;
            }
            if (Origin.Z < box.Min.Z && Direction.Z != 0.0f)
            {
                maxT.Z = (box.Min.Z - Origin.Z) / Direction.Z;
            }
            else if (Origin.Z > box.Max.Z && Direction.Z != 0.0f)
            {
                maxT.Z = (box.Max.Z - Origin.Z) / Direction.Z;
            }

            //get the maximum maxT
            if (maxT.X > maxT.Y && maxT.X > maxT.Z)
            {
                if (maxT.X < 0.0f)
                {
                    return(null);                   // ray go on opposite of face
                }
                //coordonate of hit point of face of cube
                float coord = Origin.Z + maxT.X * Direction.Z;
                // if hit point coord ( intersect face with ray) is out of other plane coord it miss
                if (coord < box.Min.Z || coord > box.Max.Z)
                {
                    return(null);
                }
                coord = Origin.Y + maxT.X * Direction.Y;
                if (coord < box.Min.Y || coord > box.Max.Y)
                {
                    return(null);
                }
                return(maxT.X);
            }
            if (maxT.Y > maxT.X && maxT.Y > maxT.Z)
            {
                if (maxT.Y < 0.0f)
                {
                    return(null);                   // ray go on opposite of face
                }
                //coordonate of hit point of face of cube
                float coord = Origin.Z + maxT.Y * Direction.Z;
                // if hit point coord ( intersect face with ray) is out of other plane coord it miss
                if (coord < box.Min.Z || coord > box.Max.Z)
                {
                    return(null);
                }
                coord = Origin.X + maxT.Y * Direction.X;
                if (coord < box.Min.X || coord > box.Max.X)
                {
                    return(null);
                }
                return(maxT.Y);
            }
            else             //Z
            {
                if (maxT.Z < 0.0f)
                {
                    return(null);                   // ray go on opposite of face
                }
                //coordonate of hit point of face of cube
                float coord = Origin.X + maxT.Z * Direction.X;
                // if hit point coord ( intersect face with ray) is out of other plane coord it miss
                if (coord < box.Min.X || coord > box.Max.X)
                {
                    return(null);
                }
                coord = Origin.Y + maxT.Z * Direction.Y;
                if (coord < box.Min.Y || coord > box.Max.Y)
                {
                    return(null);
                }
                return(maxT.Z);
            }
        }
Esempio n. 4
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
            });
        }
Esempio n. 5
0
        public float? Intersects(AxisAlignedBox3D box)
        {
            //first test if start in box
            if (Origin.X >= box.Min.X
                && Origin.X <= box.Max.X
                && Origin.Y >= box.Min.Y
                && Origin.Y <= box.Max.Y
                && Origin.Z >= box.Min.Z
                && Origin.Z <= box.Max.Z)
                return 0.0f;// here we concidere cube is full and origine is in cube so intersect at origine

            //Second we check each face
            Vector3D maxT = new Vector3D(-1.0f);
            //Vector3 minT = new Vector3(-1.0f);
            //calcul intersection with each faces
            if (Origin.X < box.Min.X && Direction.X != 0.0f)
                maxT.X = (box.Min.X - Origin.X) / Direction.X;
            else if (Origin.X > box.Max.X && Direction.X != 0.0f)
                maxT.X = (box.Max.X - Origin.X) / Direction.X;
            if (Origin.Y < box.Min.Y && Direction.Y != 0.0f)
                maxT.Y = (box.Min.Y - Origin.Y) / Direction.Y;
            else if (Origin.Y > box.Max.Y && Direction.Y != 0.0f)
                maxT.Y = (box.Max.Y - Origin.Y) / Direction.Y;
            if (Origin.Z < box.Min.Z && Direction.Z != 0.0f)
                maxT.Z = (box.Min.Z - Origin.Z) / Direction.Z;
            else if (Origin.Z > box.Max.Z && Direction.Z != 0.0f)
                maxT.Z = (box.Max.Z - Origin.Z) / Direction.Z;

            //get the maximum maxT
            if (maxT.X > maxT.Y && maxT.X > maxT.Z)
            {
                if (maxT.X < 0.0f)
                    return null;// ray go on opposite of face
                //coordonate of hit point of face of cube
                float coord = Origin.Z + maxT.X * Direction.Z;
                // if hit point coord ( intersect face with ray) is out of other plane coord it miss
                if (coord < box.Min.Z || coord > box.Max.Z)
                    return null;
                coord = Origin.Y + maxT.X * Direction.Y;
                if (coord < box.Min.Y || coord > box.Max.Y)
                    return null;
                return maxT.X;
            }
            if (maxT.Y > maxT.X && maxT.Y > maxT.Z)
            {
                if (maxT.Y < 0.0f)
                    return null;// ray go on opposite of face
                //coordonate of hit point of face of cube
                float coord = Origin.Z + maxT.Y * Direction.Z;
                // if hit point coord ( intersect face with ray) is out of other plane coord it miss
                if (coord < box.Min.Z || coord > box.Max.Z)
                    return null;
                coord = Origin.X + maxT.Y * Direction.X;
                if (coord < box.Min.X || coord > box.Max.X)
                    return null;
                return maxT.Y;
            }
            else //Z
            {
                if (maxT.Z < 0.0f)
                    return null;// ray go on opposite of face
                //coordonate of hit point of face of cube
                float coord = Origin.X + maxT.Z * Direction.X;
                // if hit point coord ( intersect face with ray) is out of other plane coord it miss
                if (coord < box.Min.X || coord > box.Max.X)
                    return null;
                coord = Origin.Y + maxT.Z * Direction.Y;
                if (coord < box.Min.Y || coord > box.Max.Y)
                    return null;
                return maxT.Z;
            }
        }
Esempio n. 6
0
 public AxisAlignedBox3D Transform(AxisAlignedBox3D box)
 {
     return(box.Transform(Value));
 }