public void CreateRotationX() { double angle = (double)MathHelper.ToRadians(30.0); Matrix33D m = Matrix33D.CreateRotationX(angle); Assert.IsTrue(Vector3D.AreNumericallyEqual(new Vector3D(0, (double)Math.Cos(angle), (double)Math.Sin(angle)), m * Vector3D.UnitY)); QuaternionD q = QuaternionD.CreateRotation(Vector3D.UnitX, angle); Assert.IsTrue(Vector3D.AreNumericallyEqual(q.Rotate(Vector3D.One), m * Vector3D.One)); Assert.IsTrue(Matrix33D.AreNumericallyEqual(Matrix33D.CreateRotation(Vector3D.UnitX, angle), m)); }
public void Test1() { PoseD p = PoseD.Identity; Assert.AreEqual(Matrix44D.Identity, p.ToMatrix44D()); Assert.AreEqual(Matrix33D.Identity, p.Orientation); Assert.AreEqual(Vector3D.Zero, p.Position); p.Position = new Vector3D(1, 2, 3); p.Orientation = Matrix33D.CreateRotation(new Vector3D(3, -4, 9), 0.49); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToWorldDirection(Vector3D.UnitX), 0), p * new Vector4D(1, 0, 0, 0))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToWorldDirection(Vector3D.UnitY), 0), p * new Vector4D(0, 1, 0, 0))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToWorldDirection(Vector3D.UnitZ), 0), p * new Vector4D(0, 0, 1, 0))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToWorldPosition(Vector3D.UnitX), 1), p * new Vector4D(1, 0, 0, 1))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToWorldPosition(Vector3D.UnitY), 1), p * new Vector4D(0, 1, 0, 1))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToWorldPosition(Vector3D.UnitZ), 1), p * new Vector4D(0, 0, 1, 1))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToLocalDirection(Vector3D.UnitX), 0), p.Inverse * new Vector4D(1, 0, 0, 0))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToLocalDirection(Vector3D.UnitY), 0), p.Inverse * new Vector4D(0, 1, 0, 0))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToLocalDirection(Vector3D.UnitZ), 0), p.Inverse * new Vector4D(0, 0, 1, 0))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToLocalPosition(Vector3D.UnitX), 1), p.Inverse * new Vector4D(1, 0, 0, 1))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToLocalPosition(Vector3D.UnitY), 1), p.Inverse * new Vector4D(0, 1, 0, 1))); Assert.IsTrue(Vector4D.AreNumericallyEqual(new Vector4D(p.ToLocalPosition(Vector3D.UnitZ), 1), p.Inverse * new Vector4D(0, 0, 1, 1))); PoseD p2 = PoseD.FromMatrix(new Matrix44D(p.Orientation, Vector3D.Zero)); Assert.IsTrue(Matrix33D.AreNumericallyEqual(p.Orientation, p2.Orientation)); Assert.IsTrue(Vector3D.AreNumericallyEqual(p2.Position, Vector3D.Zero)); Matrix44D m = p2; m.SetColumn(3, new Vector4D(p.Position, 1)); p2 = PoseD.FromMatrix(m); Assert.IsTrue(Matrix33D.AreNumericallyEqual(p.Orientation, p2.Orientation)); Assert.AreEqual(p.Position, p2.Position); //Assert.IsTrue(Vector3D.AreNumericallyEqual(p.Position, p2.Position)); // Test other constructors. Assert.AreEqual(Vector3D.Zero, new PoseD(QuaternionD.CreateRotationX(0.3)).Position); Assert.AreEqual(Matrix33D.CreateRotationX(0.3), new PoseD(Matrix33D.CreateRotationX(0.3)).Orientation); Assert.AreEqual(new Vector3D(1, 2, 3), new PoseD(new Vector3D(1, 2, 3)).Position); Assert.AreEqual(Matrix33D.Identity, new PoseD(new Vector3D(1, 2, 3)).Orientation); }
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)); }
/// <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); //} }