Ejemplo n.º 1
0
    public void CreateRotationZ()
    {
      double angle = (double)MathHelper.ToRadians(30);
      Matrix33D m = Matrix33D.CreateRotationZ(angle);
      Assert.IsTrue(Vector3D.AreNumericallyEqual(new Vector3D((double)Math.Cos(angle), (double)Math.Sin(angle), 0), m * Vector3D.UnitX));

      QuaternionD q = QuaternionD.CreateRotation(Vector3D.UnitZ, angle);
      Assert.IsTrue(Vector3D.AreNumericallyEqual(q.Rotate(Vector3D.One), m * Vector3D.One));

      Assert.IsTrue(Matrix33D.AreNumericallyEqual(Matrix33D.CreateRotation(Vector3D.UnitZ, angle), m));
    }
Ejemplo n.º 2
0
    public void Orthogonalize()
    {
      var m = Matrix33D.CreateRotationX(0.1) * Matrix33D.CreateRotationX(20) * Matrix33D.CreateRotationZ(1000);

      // Introduce error.
      m.M01 += 0.1f;
      m.M22 += 0.1f;

      Assert.IsFalse(m.IsOrthogonal);
      Assert.IsFalse(m.IsRotation);

      m.Orthogonalize();

      Assert.IsTrue(m.IsOrthogonal);
      Assert.IsTrue(m.IsRotation);

      // Orthogonalizing and orthogonal matrix does not change the matrix.
      var n = m;
      n.Orthogonalize();
      Assert.IsTrue(Matrix33D.AreNumericallyEqual(m, n));
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Computes the derived values, like sun/moon positions, transformation matrices and light
    /// intensities. This method must be called when the location or time has changed.
    /// </summary>
    /// <remarks>
    /// This method must be called when the input properties <see cref="Latitude"/>,
    /// <see cref="Longitude"/>, <see cref="Altitude"/>, or <see cref="Time"/>) have changed.
    /// </remarks>
    public void Update()
    {
      _epoch2000Centuries = ToEpoch2000Centuries(Time, true);
      _epoch1990Days = ToEpoch1990Days(Time, false);

      // To transform from ecliptic to equatorial, we rotate by the obliquity of the ecliptic.
      _e = 0.409093 - 0.000227 * _epoch2000Centuries;
      EclipticToEquatorial = Matrix33D.CreateRotationX(_e);

      // GMST = Greenwich mean sidereal time (mittlere Greenwich-Sternzeit) in radians.
      double gmst = 4.894961 + 230121.675315 * ToEpoch2000Centuries(Time, false);
      EquatorialToGeographic = Matrix33D.CreateRotationZ(-gmst);

      // The earth axis slowly changes over time (precession). The precession movement repeats
      // itself approx. all 26000 years. When we move from to horizontal or geographics,
      // we need to apply the precession.

      // In Game Engine Gems:
      //var Rx = Matrix33D.CreateRotationX(0.1118 * _epoch2000Centuries);
      //var Ry = Matrix33D.CreateRotationY(-0.00972 * _epoch2000Centuries);
      //var Rz = Matrix33D.CreateRotationZ(0.01118 * _epoch2000Centuries);
      //var precession = Rz * (Ry * Rx);

      // In original article:
      var Ry = Matrix33D.CreateRotationY(-0.00972 * _epoch2000Centuries);
      var Rz = Matrix33D.CreateRotationZ(0.01118 * _epoch2000Centuries);
      var precession = Rz * Ry * Rz;

      // In game engine gems precession is applied in EclipticToWorld and in
      // EquatorialToWorld. This makes no sense since precession cannot be valid for both
      // coordinate systems. --> We assume the precession is given in equatorial space.
      //EclipticToWorld = rLat * rLong * EclipticToEquatorial * precession;

      // Latitude rotation
      var rLat = Matrix33D.CreateRotationY(MathHelper.ToRadians(Latitude) - ConstantsD.PiOver2);

      // Longitude rotation
      // LMST = Local mean sidereal time (mittlere Ortssternzeit) in radians.
      double lmst = gmst + MathHelper.ToRadians(Longitude);
      var rLong = Matrix33D.CreateRotationZ(-lmst);

      // Earth radius at the equator. (We assume a perfect sphere. We do not support geodetic 
      // systems with imperfect earth spheres.)
      const double earthRadius = 6378.137 * 1000;
      var equatorialToHorizontalTranslation = new Vector3D(0, -earthRadius - Altitude, 0);

      // Switching of the coordinate axes between Equatorial (z up) and Horizontal (y up).
      var axisSwitch = new Matrix33D(0, 1, 0,
                                     0, 0, 1,
                                     1, 0, 0);

      EquatorialToWorld = new Matrix44D(axisSwitch * rLat * rLong * precession,
                                        equatorialToHorizontalTranslation);

      _equatorialToWorldNoPrecession = new Matrix44D(axisSwitch * rLat * rLong,
                                                     equatorialToHorizontalTranslation);

      //WorldToGeographic = EquatorialToGeographic * EquatorialToWorld.Minor.Transposed;

      ComputeSunPosition();
      ComputeMoonPosition();
      ComputeEarthPosition();

      //for (int i = 0; i < NumberOfPlanets; i++)
      //{
      //  var planet = (VisiblePlanets)i;
      //  if (planet != VisiblePlanets.Earth)
      //    ComputePlanetData(planet);
      //}
    }