/// <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); }
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); }
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); } }
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 }); }
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; } }
public AxisAlignedBox3D Transform(AxisAlignedBox3D box) { return(box.Transform(Value)); }