Exemple #1
0
        protected void SlerpToTargetOrientation(double percent)
        {
            double c = Quaternion4d.Dot(this.m_Orientation, this._targetOrientation);

            if (c > 1.0)
            {
                c = 1.0;
            }
            else if (c < -1.0)
            {
                c = -1.0;
            }

            this.angle = Angle.FromRadians(Math.Acos(c));

            this.m_Orientation = Quaternion4d.Slerp(this.m_Orientation, this._targetOrientation, percent);

            this._tilt     += (this._targetTilt - this._tilt) * percent;
            this._bank     += (this._targetBank - this._bank) * percent;
            this._distance += (this._targetDistance - this._distance) * percent;
            this.ComputeAltitude(this._distance + this._headZoom, this._tilt + this._headTilt, this._swivel + this._headSwivel);
            this._fov += (this._targetFov - this._fov) * percent;
        }
Exemple #2
0
        /// <summary>
        /// Find the intersection of a ray with the terrain.
        /// </summary>
        /// <param name="p1">Cartesian coordinate of starting point</param>
        /// <param name="p2">Cartesian coordinate of end point</param>
        /// <param name="samplingPrecision">Sample length in meter</param>
        /// <param name="resultPrecision">Final sampling length in meter</param>
        /// <param name="latitude">Out : intersection latitude</param>
        /// <param name="longitude">Out : intersection longitude</param>
        /// <param name="world">Current world</param>
        /// <returns>NaN if no intersection found</returns>
        public static void RayIntersectionWithTerrain(
            Point3d p1,
            Point3d p2,
            double samplingPrecision,
            double resultPrecision,
            out Angle latitude,
            out Angle longitude,
            World world)
        {
            // Check for sphere intersection first
            // Note : checks for world radius + highest possible elevation
            float  vertEx       = World.Settings.VerticalExaggeration;
            double maxRadius    = world.EquatorialRadius + 9000 * vertEx; // Max altitude for earth - should be dependant on world
            double a            = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.Z - p1.Z) * (p2.Z - p1.Z);
            double b            = 2.0 * ((p2.X - p1.X) * (p1.X) + (p2.Y - p1.Y) * (p1.Y) + (p2.Z - p1.Z) * (p1.Z));
            double c            = p1.X * p1.X + p1.Y * p1.Y + p1.Z * p1.Z - maxRadius * maxRadius;
            double discriminant = b * b - 4 * a * c;

            if (discriminant <= 0)
            {
                // No intersection with sphere
                latitude  = Angle.NaN;
                longitude = Angle.NaN;
                return;
            }
            // Factor to intersection
            // Note : if t1 > 0 intersection is forward, < 0 is behind us
            double  t1       = ((-1.0) * b - Math.Sqrt(discriminant)) / (2 * a);
            Point3d p1LatLon = MathEngine.CartesianToSphericalD(p1.X, p1.Y, p1.Z);

            if (t1 > 0 && p1LatLon.X > maxRadius)
            {
                // Looking from above max altitude : move p1 forward to intersection with max alt sphere
                p1 = new Point3d(p1.X + t1 * (p2.X - p1.X), p1.Y + t1 * (p2.Y - p1.Y), p1.Z + t1 * (p2.Z - p1.Z));
            }

            // Ray sample
            Vector3 sample       = new Vector3((float)(p2.X - p1.X), (float)(p2.Y - p1.Y), (float)(p2.Z - p1.Z));
            double  maxLength    = sample.Length();   // Max length for ray tracing
            double  sampleLength = samplingPrecision; // Sampling steps length

            sample.Normalize();
            sample.Scale((float)sampleLength);

            // Casting
            Point3d ray       = p1;
            double  rayLength = 0;

            while (rayLength < maxLength)
            {
                Point3d rayLatLon = MathEngine.CartesianToSphericalD(ray.X, ray.Y, ray.Z);
                // Altitude at ray position
                double rayAlt = rayLatLon.X - world.EquatorialRadius;
                // Altitude at terrain position - from cached data (no download)
                double terrainAlt = world.TerrainAccessor.GetCachedElevationAt(MathEngine.RadiansToDegrees(rayLatLon.Y), MathEngine.RadiansToDegrees(rayLatLon.Z)); // best loaded data
                if (double.IsNaN(terrainAlt))
                {
                    terrainAlt = 0;
                }
                terrainAlt *= vertEx;
                if (terrainAlt > rayAlt)
                {
                    // Intersection found
                    if (sampleLength > resultPrecision)
                    {
                        // Go back one step
                        ray.X     -= sample.X;
                        ray.Y     -= sample.Y;
                        ray.Z     -= sample.Z;
                        rayLength -= sampleLength;
                        // and refine sampling
                        sampleLength /= 10;
                        sample.Normalize();
                        sample.Scale((float)sampleLength);
                    }
                    else
                    {
                        // return location
                        latitude  = Angle.FromRadians(rayLatLon.Y);
                        longitude = Angle.FromRadians(rayLatLon.Z);
                        return;
                    }
                }
                // Move forward
                ray.X     += sample.X;
                ray.Y     += sample.Y;
                ray.Z     += sample.Z;
                rayLength += sampleLength;
            }
            // No intersection with terrain found
            latitude  = Angle.NaN;
            longitude = Angle.NaN;
        }
Exemple #3
0
        public virtual void Update(Device device)
        {
            this.viewPort = device.Viewport;

            Point3d p = Quaternion4d.QuaternionToEuler(this.m_Orientation);

            if (!double.IsNaN(p.Y))
            {
                this._latitude.Radians = p.Y;
            }
            if (!double.IsNaN(p.X))
            {
                this._longitude.Radians = p.X;
            }
            if (!double.IsNaN(p.Z))
            {
                this._heading.Radians = p.Z;
            }

            // Compute matrices
            this.ComputeProjectionMatrix(this.viewPort);
            this.ComputeViewMatrix();
            device.SetTransform(TransformState.Projection, this.m_ProjectionMatrix);
            device.SetTransform(TransformState.View, this.m_ViewMatrix);
            device.SetTransform(TransformState.World, this.m_WorldMatrix);

            this.ViewFrustum.Update(
                Matrix.Multiply(this.m_absoluteWorldMatrix,
                                Matrix.Multiply(this.m_absoluteViewMatrix, this.m_absoluteProjectionMatrix)));

            // Old view range (used in quadtile logic)
            double factor = (this._altitude) / this._worldRadius;

            if (factor > 1)
            {
                this.viewRange = Angle.FromRadians(Math.PI);
            }
            else
            {
                this.viewRange = Angle.FromRadians(Math.Abs(Math.Asin((this._altitude) / this._worldRadius)) * 2);
            }

            // True view range
            if (factor < 1)
            {
                this.trueViewRange = Angle.FromRadians(Math.Abs(Math.Asin((this._distance + this._headZoom) / this._worldRadius)) * 2);
            }
            else
            {
                this.trueViewRange = Angle.FromRadians(Math.PI);
            }

            World.Settings.cameraAltitudeMeters = this.Altitude;
            World.Settings.cameraLatitude       = this._latitude;
            World.Settings.cameraLongitude      = this._longitude;
            World.Settings.cameraHeading        = this._heading;
            World.Settings.cameraTilt           = this._tilt;
            World.Settings.cameraSwivel         = this._swivel;

            if (World.Settings.cameraHeadTracking != this._headTracking)
            {
                this._headTracking = World.Settings.cameraHeadTracking;

                if (!this._headTracking)
                {
                    this._headTilt   = Angle.Zero;
                    this._headSwivel = Angle.Zero;
                    this._headZoom   = 0.0;
                    World.Settings.cameraHeadTilt   = this._headTilt;
                    World.Settings.cameraHeadSwivel = this._headSwivel;
                    World.Settings.cameraHeadZoom   = this._headZoom;
                }
            }

            if (this._headTracking)
            {
                World.Settings.cameraHeadTilt   = this._headTilt;
                World.Settings.cameraHeadSwivel = this._headSwivel;
                World.Settings.cameraHeadZoom   = this._headZoom;
            }
        }
Exemple #4
0
        public virtual void ComputeViewMatrix()
        {
            // Compute camera elevation
            if (World.Settings.ElevateCameraLookatPoint)
            {
                int minStep = 10;
                this.targetCameraElevation = this.TerrainElevation * World.Settings.VerticalExaggeration;
                float stepToTarget = this.targetCameraElevation - this.curCameraElevation;
                if (Math.Abs(stepToTarget) > minStep)
                {
                    float step = 0.05f * stepToTarget;
                    if (Math.Abs(step) < minStep)
                    {
                        step = step > 0 ? minStep : -minStep;
                    }
                    this.curCameraElevation = this.curCameraElevation + step;
                }
                else
                {
                    this.curCameraElevation = this.targetCameraElevation;
                }
            }
            else
            {
                this.curCameraElevation = 0;
            }

            // Absolute matrices
            this.ComputeAbsoluteMatrices();

            // needs to be double precsion
            double radius    = this.WorldRadius + this.curCameraElevation;
            double radCosLat = radius * Math.Cos(this._latitude.Radians);

            LookFrom = new Point3d(radCosLat * Math.Cos(this._longitude.Radians),
                                   radCosLat * Math.Sin(this._longitude.Radians),
                                   radius * Math.Sin(this._latitude.Radians));

            // this constitutes a local tri-frame hovering above the sphere
            Point3d zAxis = LookFrom.normalize(); // on sphere the normal vector and position vector are the same
            Point3d xAxis = Point3d.cross(cameraUpVector, zAxis).normalize();
            Point3d yAxis = Point3d.cross(zAxis, xAxis);

            this.ReferenceCenter = MathEngine.SphericalToCartesianD(
                Angle.FromRadians(Convert.ToSingle(this._latitude.Radians)),
                Angle.FromRadians(Convert.ToSingle(this._longitude.Radians)), this.WorldRadius);

            // Important step !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // In order to use single precsion rendering, we need to define a local frame (i.e. center of center tile, etc.)
            // Vector3d LocalCenter should be defined & initialized in the CameraBase class
            // Each time the camera moves, a new local center could be defined
            // The local center also has to be subtracted from all the terrain vertices!!!!
            relCameraPos = LookFrom - this.ReferenceCenter;

            // Important step: construct the single precision m_ViewMatrix by hand

            // We can build the m_ViewMatrix by hand
            this.m_ViewMatrix.M11 = (float)xAxis.X;
            this.m_ViewMatrix.M21 = (float)xAxis.Y;
            this.m_ViewMatrix.M31 = (float)xAxis.Z;

            this.m_ViewMatrix.M12 = (float)yAxis.X;
            this.m_ViewMatrix.M22 = (float)yAxis.Y;
            this.m_ViewMatrix.M32 = (float)yAxis.Z;

            this.m_ViewMatrix.M13 = (float)zAxis.X;
            this.m_ViewMatrix.M23 = (float)zAxis.Y;
            this.m_ViewMatrix.M33 = (float)zAxis.Z;

            this.m_ViewMatrix.M41 = -(float)(xAxis.X * relCameraPos.X + xAxis.Y * relCameraPos.Y + xAxis.Z * relCameraPos.Z);
            this.m_ViewMatrix.M42 = -(float)(yAxis.X * relCameraPos.X + yAxis.Y * relCameraPos.Y + yAxis.Z * relCameraPos.Z);
            this.m_ViewMatrix.M43 = -(float)(zAxis.X * relCameraPos.X + zAxis.Y * relCameraPos.Y + zAxis.Z * relCameraPos.Z);

            this.m_ViewMatrix.M14 = (float)0.0;
            this.m_ViewMatrix.M24 = (float)0.0;
            this.m_ViewMatrix.M34 = (float)0.0;
            this.m_ViewMatrix.M44 = (float)1.0;

            double cameraDisplacement = this._distance + this._headZoom;

            //if(cameraDisplacement < targetCameraElevation + minimumAltitude)
            //	cameraDisplacement = targetCameraElevation + minimumAltitude;

            this.m_ViewMatrix *= Matrix.RotationYawPitchRoll(
                (float)-(this._swivel.Radians + this._headSwivel.Radians),
                (float)-(this._tilt.Radians + this._headTilt.Radians),
                (float)this._heading.Radians);
            //m_ViewMatrix *= Matrix.Translation(0, 0, (float)(-cameraDisplacement + curCameraElevation));
            this.m_ViewMatrix *= Matrix.Translation(0, 0, (float)(-cameraDisplacement));
            this.m_ViewMatrix *= Matrix.RotationZ((float)this._bank.Radians);

            // Extract camera position
            Matrix cam = Matrix.Invert(this.m_absoluteViewMatrix);

            this._position = new Vector3(cam.M41, cam.M42, cam.M43);
        }
Exemple #5
0
        WorldWindWFSPlacenameFile[] GetWFSFiles(double north, double south, double west, double east)
        {
            double tileSize = 0;

            //base the tile size on the max viewing distance
            double maxDistance = Math.Sqrt(this.m_maximumDistanceSq);

            double factor = maxDistance / this.m_parentWorld.EquatorialRadius;

            // True view range
            if (factor < 1)
            {
                tileSize = Angle.FromRadians(Math.Abs(Math.Asin(maxDistance / this.m_parentWorld.EquatorialRadius)) * 2).Degrees;
            }
            else
            {
                tileSize = Angle.FromRadians(Math.PI).Degrees;
            }

            tileSize = (180 / (int)(180 / tileSize));

            if (tileSize == 0)
            {
                tileSize = 0.1;
            }
            //Log.Write(Log.Levels.Debug, string.Format("TS: {0} -> {1}", name, tileSize));
            //not working for some reason...
            //int startRow = MathEngine.GetRowFromLatitude(south, tileSize);
            //int endRow = MathEngine.GetRowFromLatitude(north, tileSize);
            //int startCol = MathEngine.GetColFromLongitude(west, tileSize);
            //int endCol = MathEngine.GetColFromLongitude(east, tileSize);

            ArrayList placenameFiles = new ArrayList();

            double currentSouth = -90;

            //for (int row = 0; row <= endRow; row++)
            while (currentSouth < 90)
            {
                double currentNorth = currentSouth + tileSize;
                if (currentSouth > north || currentNorth < south)
                {
                    currentSouth += tileSize;
                    continue;
                }

                double currentWest = -180;
                while (currentWest < 180)
                //    for (int col = startCol; col <= endCol; col++)
                {
                    double currentEast = currentWest + tileSize;
                    if (currentWest > east || currentEast < west)
                    {
                        currentWest += tileSize;
                        continue;
                    }

                    WorldWindWFSPlacenameFile placenameFile = new WorldWindWFSPlacenameFile(this.m_name, this.m_placenameBaseUrl, this.m_typename, this.m_labelfield, currentNorth, currentSouth, currentWest, currentEast, this.m_parentWorld, this.m_cache);

                    int key = placenameFile.GetHashCode();
                    if (!this.m_fileHash.Contains(key))
                    {
                        this.m_fileHash.Add(key, placenameFile);
                    }
                    else
                    {
                        placenameFile = (WorldWindWFSPlacenameFile)this.m_fileHash[key];
                    }
                    placenameFiles.Add(placenameFile);

                    currentWest += tileSize;
                }
                currentSouth += tileSize;
            }

            return((WorldWindWFSPlacenameFile[])placenameFiles.ToArray(typeof(WorldWindWFSPlacenameFile)));
        }
        public static Point3d GetGeocentricPosition(System.DateTime utcDateTime)
        {
            if (World.Settings.SunSynchedWithTime)
            {
                // Sun synched with time and date
                double JD = getJulianDay(utcDateTime);
                double T  = (JD - 2451545.0) / 36525; // number of Julian centuries since Jan 1, 2000, 12 UT

                double k  = Math.PI / 180.0;
                double M  = 357.52910 + 35999.05030 * T - 0.0001559 * T * T - 0.00000048 * T * T * T; // mean anomaly, degree
                double L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T * T;                          // mean longitude, degree
                double DL = (1.914600 - 0.004817 * T - 0.000014 * T * T) * Math.Sin(k * M) + (0.019993 - 0.000101 * T) * Math.Sin(k * 2 * M) + 0.000290 * Math.Sin(k * 3 * M);
                double L  = L0 + DL;                                                                  // true longitude, degree
                L = L % 360;
                //		obliquity eps of ecliptic:
                double eps = 23.0 + 26.0 / 60.0 + 21.448 / 3600.0 - (46.8150 * T + 0.00059 * T * T - 0.001813 * T * T * T) / 3600;

                double X = Math.Cos(k * L);
                double Y = Math.Cos(k * eps) * Math.Sin(k * L);
                double Z = Math.Sin(k * eps) * Math.Sin(k * L);

                double R = Math.Sqrt(1.0 - Z * Z);

                double dec = (180 / Math.PI) * Math.Atan(Z / R);                                                                  // in degrees
                double RA  = (24 / Math.PI) * Math.Atan(Y / (X + R));                                                             // in hours

                double theta0 = 280.46061837 + 360.98564736629 * (JD - 2451545.0) + 0.000387933 * T * T - T * T * T / 38710000.0; // Greenwich Sidereal Time

                theta0 = theta0 % 360;
                RA    *= 15; // convert from hours to degrees
                double tau = theta0 - RA;

                Point3d pos = MathEngine.SphericalToCartesianD(
                    Angle.FromDegrees(-dec),
                    Angle.FromDegrees(-(tau - 180)),
                    1);

                return(pos);
            }
            else
            {
                // Fixed sun heading and elevation
                double  worldRadius = 6378137;  // Earth meter
                Vector3 position    = MathEngine.SphericalToCartesian(World.Settings.CameraLatitude, World.Settings.CameraLongitude, worldRadius);
                return(GetGeocentricPosition(position, Angle.FromRadians(World.Settings.SunHeading), Angle.FromRadians(World.Settings.SunElevation), World.Settings.SunDistance));
            }
        }
Exemple #7
0
		/// <summary>
		/// Returns the absolute value of the specified angle
		/// </summary>
		public static Angle Abs( Angle a )
		{
			return Angle.FromRadians(Math.Abs(a.Radians));
		}
Exemple #8
0
		public static Angle operator /(Angle a, double divisor) 
		{
			return Angle.FromRadians(a.Radians / divisor);
		}
Exemple #9
0
		public static Angle operator *(double times, Angle a) 
		{
			return Angle.FromRadians(a.Radians * times);
		}
Exemple #10
0
		public static Angle operator -(Angle a, Angle b) 
		{
			double res = a.Radians - b.Radians;
			return Angle.FromRadians(res);
		}
Exemple #11
0
 public static Angle operator /(double divisor, Angle a)
 {
     return(Angle.FromRadians(a.Radians / divisor));
 }
Exemple #12
0
 public static Angle operator *(Angle a, double times)
 {
     return(Angle.FromRadians(a.Radians * times));
 }
Exemple #13
0
        public static Angle operator +(Angle a, Angle b)
        {
            double res = a.Radians + b.Radians;

            return(Angle.FromRadians(res));
        }