Exemple #1
0
        /// <summary>
        /// Computes from a <see cref="V3f"/> point (origin) and
        /// a <see cref="V3f"/> normal the transformation matrix
        /// and its inverse.
        /// </summary>
        /// <param name="origin">The point which will become the new origin.</param>
        /// <param name="normal">The normal vector of the new ground plane.</param>
        /// <param name="local2global">A <see cref="M44f"/>The trafo from local to global system.</param>
        /// <param name="global2local">A <see cref="M44f"/>The trafofrom global to local system.</param>
        public static void NormalFrame(V3f origin, V3f normal,
                                       out M44f local2global, out M44f global2local
                                       )
        {
            V3f   min;
            float x = Fun.Abs(normal.X);
            float y = Fun.Abs(normal.Y);
            float z = Fun.Abs(normal.Z);

            if (x < y)
            {
                if (x < z)
                {
                    min = V3f.XAxis;
                }
                else
                {
                    min = V3f.ZAxis;
                }
            }
            else
            {
                if (y < z)
                {
                    min = V3f.YAxis;
                }
                else
                {
                    min = V3f.ZAxis;
                }
            }

            V3f xVec = Vec.Cross(normal, min);

            xVec.Normalize(); // this is now guaranteed to be normal to the input normal
            V3f yVec = Vec.Cross(normal, xVec);

            yVec.Normalize();
            V3f zVec = normal;

            zVec.Normalize();

            local2global = new M44f(xVec.X, yVec.X, zVec.X, origin.X,
                                    xVec.Y, yVec.Y, zVec.Y, origin.Y,
                                    xVec.Z, yVec.Z, zVec.Z, origin.Z,
                                    0, 0, 0, 1);

            M44f mat = new M44f(xVec.X, xVec.Y, xVec.Z, 0,
                                yVec.X, yVec.Y, yVec.Z, 0,
                                zVec.X, zVec.Y, zVec.Z, 0,
                                0, 0, 0, 1);

            var shift = M44f.Translation(-origin);

            global2local = mat * shift;
        }
        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();
        }