private bool DoIntersection(Ray r, out float phi, out Point phit, out float thit) { phi = 0.0f; phit = new Point(); thit = 0.0f; // Transform _Ray_ to object space Ray ray = WorldToObject.TransformRay(r); // Compute quadratic cylinder coefficients float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y; float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y); float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y - _radius * _radius; // Solve quadratic equation for _t_ values float t0, t1; if (!MathUtility.TryQuadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.MaxT || t1 < ray.MinT) return false; thit = t0; if (t0 < ray.MinT) { thit = t1; if (thit > ray.MaxT) return false; } // Compute cylinder hit point and $\phi$ phit = ray.Evaluate(thit); phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0) phi += 2.0f * MathUtility.Pi; // Test cylinder intersection against clipping parameters if (phit.Z < _zMin || phit.Z > _zMax || phi > _phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.MaxT) return false; // Compute cylinder hit point and $\phi$ phit = ray.Evaluate(thit); phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0f) phi += 2.0f * MathUtility.Pi; if (phit.Z < _zMin || phit.Z > _zMax || phi > _phiMax) return false; } return true; }
private bool DoIntersection(Ray r, out float phi, out float dist2, out Point phit, out float thit) { phi = dist2 = thit = 0; phit = Point.Zero; // Transform _Ray_ to object space Ray ray = WorldToObject.TransformRay(r); // Compute plane intersection for disk if (Math.Abs(ray.Direction.Z) < 1e-7) { return(false); } thit = (_height - ray.Origin.Z) / ray.Direction.Z; if (thit < ray.MinT || thit > ray.MaxT) { return(false); } // See if hit point is inside disk radii and $\phimax$ phit = ray.Evaluate(thit); dist2 = phit.X * phit.X + phit.Y * phit.Y; if (dist2 > _radius * _radius || dist2 < _innerRadius * _innerRadius) { return(false); } // Test disk $\phi$ value against $\phimax$ phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0) { phi += 2.0f * MathUtility.Pi; } if (phi > _phiMax) { return(false); } return(true); }
public void UpdateCamera(GameTime gameTime) { if (_animation != null) { _animation.Update(this, gameTime); if (_animation.Finished) { _animation = null; } } var yaw = MathUtility.Atan2(_lookDirection.Y, _lookDirection.X); var pitch = MathUtility.Lerp( 0, -_pitchAngle, _pitch); var cameraHeight = MathUtility.Lerp( 0, _defaultHeight, _zoom); float clampedPitch = pitch; if (pitch > 0 && pitch < _pitchAngle) { clampedPitch = _pitchAngle; } else if (pitch < 0 && pitch > -_pitchAngle) { clampedPitch = -_pitchAngle; } var cameraToTerrainDirection = Vector3.Normalize(new Vector3( MathUtility.Cos(yaw), MathUtility.Sin(yaw), MathUtility.Sin(clampedPitch))); // Back up camera from terrain position. var toCameraRay = new Ray(_terrainPosition, -cameraToTerrainDirection); var plane = Plane.CreateFromVertices( new Vector3(0, 0, cameraHeight), new Vector3(0, 1, cameraHeight), new Vector3(1, 0, cameraHeight)); var toCameraIntersectionDistance = toCameraRay.Intersects(ref plane).Value; var newPosition = _terrainPosition - cameraToTerrainDirection * toCameraIntersectionDistance; // Pitch - 0 means top-down view. // Pitch between 0 and CameraPitch = Move camera position to match pitch. // Pitch between CameraPitch and horizontal = Raise or lower target height. var lookDirection = new Vector3( MathUtility.Cos(yaw), MathUtility.Sin(yaw), MathUtility.Sin(pitch)); var targetPosition = newPosition + lookDirection; _camera.View = Matrix4x4.CreateLookAt( newPosition, targetPosition, Vector3.UnitZ); }
private bool DoIntersection(Ray r, out float phi, out Point phit, out float thit) { phi = 0.0f; phit = new Point(); thit = 0.0f; // Transform _Ray_ to object space Ray ray = WorldToObject.TransformRay(r); // Compute quadratic sphere coefficients float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y + ray.Direction.Z * ray.Direction.Z; float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y + ray.Direction.Z * ray.Origin.Z); float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y + ray.Origin.Z * ray.Origin.Z - _radius * _radius; // Solve quadratic equation for _t_ values float t0, t1; if (!MathUtility.TryQuadratic(A, B, C, out t0, out t1)) { return(false); } // Compute intersection distance along ray if (t0 > ray.MaxT || t1 < ray.MinT) { return(false); } thit = t0; if (t0 < ray.MinT) { thit = t1; if (thit > ray.MaxT) { return(false); } } // Compute sphere hit position and $\phi$ phit = ray.Evaluate(thit); if (phit.X == 0.0f && phit.Y == 0.0f) { phit.X = 1e-5f * _radius; } phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0f) { phi += 2.0f * MathUtility.Pi; } // Test sphere intersection against clipping parameters if ((_zMin > -_radius && phit.Z < _zMin) || (_zMax < _radius && phit.Z > _zMax) || phi > _phiMax) { if (thit == t1) { return(false); } if (t1 > ray.MaxT) { return(false); } thit = t1; // Compute sphere hit position and $\phi$ phit = ray.Evaluate(thit); if (phit.X == 0.0f && phit.Y == 0.0f) { phit.X = 1e-5f * _radius; } phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0f) { phi += 2.0f * MathUtility.Pi; } if ((_zMin > -_radius && phit.Z < _zMin) || (_zMax < _radius && phit.Z > _zMax) || phi > _phiMax) { return(false); } } return(true); }
public static float SphericalPhi(Vector v) { float p = MathUtility.Atan2(v.Y, v.X); return((p < 0.0f) ? p + 2.0f * MathUtility.Pi : p); }