Пример #1
0
        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;
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        public static float SphericalPhi(Vector v)
        {
            float p = MathUtility.Atan2(v.Y, v.X);

            return((p < 0.0f) ? p + 2.0f * MathUtility.Pi : p);
        }