/// <summary> /// Creates a view tranformation from the given vectors. /// Transformation from world- into view-space. /// </summary> /// <param name="location">Origin of the view</param> /// <param name="right">Right vector of the view-plane</param> /// <param name="up">Up vector of the view-plane</param> /// <param name="normal">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param> /// <returns>The view transformation</returns> public static M44f ViewTrafo(V3f location, V3f right, V3f up, V3f normal) { return(new M44f( right.X, right.Y, right.Z, -location.Dot(right), up.X, up.Y, up.Z, -location.Dot(up), normal.X, normal.Y, normal.Z, -location.Dot(normal), 0, 0, 0, 1 )); }
// https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another public static Rot3f HalfWayVec(V3f from, V3f into) { if (from.Dot(into).ApproximateEquals(-1)) { return(new Rot3f(0, from.AxisAlignedNormal())); } else { V3f half = Vec.Normalized(from + into); QuaternionF q = new QuaternionF(Vec.Dot(from, half), Vec.Cross(from, half)); return(new Rot3f(q.Normalized)); } }
public void RasterTest(uint raster) { int iraster = (int)raster; V3fCoder coder = new V3fCoder(raster); uint step = 1; bool large = false; if (iraster > 52) { step = 7; large = true; } if (iraster > 591) { step = 63; } if (iraster > 6688) { step = 2039; } int bits = (int)Fun.Ceiling(Fun.Log2(coder.Count)); Test.Begin("normal coder raster {0} ({1} bits)", iraster, bits); /* * Console.WriteLine(" raster = {0}", m_raster); * Console.WriteLine(" rasterMul2Sub1 = {0}", m_r2Sub1); * Console.WriteLine(" doubleRaster = {0}", m_doubleRaster); * Console.WriteLine(" invDoubleRaster = {0}", m_invDoubleRaster); * Console.WriteLine(" edgeBasis = {0}", m_edgeBasis); * Console.WriteLine(" cornerBasis = {0}", m_cornerBasis); */ Test.Begin("testing {0} of {1} codes", 1 + ((long)coder.Count - 1) / (long)step, coder.Count); for (uint code = 0; code < coder.Count; code += step) { V3f dir = coder.Decode(code); uint newCode = coder.Encode(dir); Test.IsTrue(code == newCode); } Test.End(); double minDot = 1.0; float eps = Constant <float> .PositiveTinyValue; float[] factorTable = { 1.0f - eps, 1.0f, 1.0f + eps }; for (int sign = -1; sign < 2; sign += 2) { for (int axis = 0; axis < 3; axis++) { float factor = factorTable[axis]; for (int xi = -2 * iraster; xi <= 2 * iraster; xi++) { if (large && (xi > 3 - 2 * iraster) && (xi < -3)) { continue; } if (large && (xi < 2 * iraster - 3) && (xi > +3)) { continue; } double x = (double)xi * factor / (2 * iraster); #if (!V3FCODER_NO_WARP) x = V3fCoder.SphericalOfBox(x); #endif for (int yi = -2 * iraster; yi <= 2 * iraster; yi++) { if (large && (yi > 3 - 2 * iraster) && (yi < -3)) { continue; } if (large && (yi < 2 * iraster - 3) && (yi > +3)) { continue; } double y = (double)yi * factor / (2 * iraster); #if (!V3FCODER_NO_WARP) y = V3fCoder.SphericalOfBox(y); #endif V3f n = new V3f(0, 0, 0); // init to make compiler h. n[axis] = sign; n[(axis + 1) % 3] = (float)x; n[(axis + 2) % 3] = (float)y; n.Normalize(); uint code = coder.Encode(n); V3f newN = coder.Decode(code); double newDot = V3f.Dot(n, newN); if (newDot < minDot) { minDot = newDot; } } } } } double maxErr = System.Math.Acos(minDot) * 180.0 / System.Math.PI; Report.Line("maximal error {0:g4} degrees", maxErr); Test.End(); }