/// <summary>
 /// Returns the outer product (tensor-product) of v1 * v2^T as a 3x3 Matrix.
 /// </summary>
 public static M33f OuterProduct(this V3f v1, V3f v2)
 {
     return(new M33f(
                v2.X * v1.X, v2.Y * v1.X, v2.Z * v1.X,
                v2.X * v1.Y, v2.Y * v1.Y, v2.Z * v1.Y,
                v2.X * v1.Z, v2.Y * v1.Z, v2.Z * v1.Z));
 }
Exemple #2
0
        /// <summary></summary>
        public static V3f[] GetV3fArray(this Storage storage, string key, CancellationToken ct)
        {
            var data = (V3f[])storage.f_tryGetFromCache(key, ct);

            if (data != null)
            {
                return(data);
            }

            var buffer = storage.f_get(key, ct);

            if (buffer == null)
            {
                return(null);
            }
            data = new V3f[buffer.Length / 12];
            using (var ms = new MemoryStream(buffer))
                using (var br = new BinaryReader(ms))
                {
                    for (var i = 0; i < data.Length; i++)
                    {
                        data[i] = new V3f(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                    }
                }
            storage.f_add(key, data, null, ct);
            return(data);
        }
 /// <summary>
 /// Returns the skew-symmetric "cross" matrix (A^T = -A) of the vector v.
 /// </summary>
 public static M33f CrossMatrix(this V3f v)
 {
     return(new M33f(
                0, -v.Z, +v.Y,
                +v.Z, 0, -v.X,
                -v.Y, +v.X, 0));
 }
Exemple #4
0
        public bool Occluded(V3f rayOrigin, V3f rayDirection, float minT = 0.0f, float maxT = float.MaxValue, RTCFilterFunction filter = null)
        {
            // NOTE: rtcInitIntersectContext is an inline method -> do manually
            var ctx = new RTCIntersectContext()
            {
                instID = unchecked ((uint)-1),
                filter = filter != null?Marshal.GetFunctionPointerForDelegate(filter) : IntPtr.Zero,
            };

            var rtRay = new RTCRay()
            {
                org   = rayOrigin,
                dir   = rayDirection,
                tnear = minT,
                tfar  = maxT,
                flags = 0, // must be initialized with 0
                time  = 0,
                mask  = 0,
                id    = 0,
            };

            unsafe
            {
                var ctxPtr = &ctx;
                var rayPtr = &rtRay;
                EmbreeAPI.rtcOccluded1(Handle, ctxPtr, rayPtr);
            }

            // tfar set to -inf if intersection is found
            return(rtRay.tfar == float.NegativeInfinity);
        }
Exemple #5
0
 public void Write(V3f value)
 {
     for (int i = 0; i < 3; i++)
     {
         base.Write(Conversion.HostToNetworkOrder(value[i]));
     }
 }
        /// <summary>
        /// Decode the unsigned integer direction code.
        /// </summary>
        /// <param name="code"></param>
        /// <returns>A normalized direction.</returns>
        public V3f Decode(uint code)
        {
            if (code < m_edgeBasis) // face number is code
            {
                double u = Unwarp(code % m_r2Sub1);
                code /= m_r2Sub1;
                double v = Unwarp(code % m_r2Sub1);
                code /= m_r2Sub1;
                double scale = 1.0 / System.Math.Sqrt(1.0 + u * u + v * v);
                switch (code)
                {
                case 0: return(new V3f(-scale, u * scale, v * scale));

                case 1: return(new V3f(v * scale, -scale, u * scale));

                case 2: return(new V3f(u * scale, v * scale, -scale));

                case 3: return(new V3f(+scale, u * scale, v * scale));

                case 4: return(new V3f(v * scale, +scale, u * scale));

                case 5: return(new V3f(u * scale, v * scale, +scale));

                default: throw new ArgumentException();
                }
            }
            else if (code < m_cornerBasis)
            {
                code -= m_edgeBasis;
                double u = Unwarp(code % m_r2Sub1);
                code /= m_r2Sub1;      // edge number in code
                double scale = 1.0 / System.Math.Sqrt(2.0 + u * u);
                uint   edge  = code & 3; code >>= 2;
                V3f    dir   = new V3f(0, 0, 0); // init to make compiler happy
                dir[(int)code]     = (float)(u * scale);
                dir[s_uAxis[code]] = (float)(s_uSignOfEdge[edge] * scale);
                dir[s_vAxis[code]] = (float)(s_vSignOfEdge[edge] * scale);
                return(dir);

#if NEVERMORE
                float edgeOne = (code & 1) == 0 ? -scale : scale;
                float edgeTwo = (code & 2) == 0 ? -scale : scale;
                switch (code >> 2)
                {
                case 0: return(new V3f((float)(u * scale), edgeOne, edgeTwo));

                case 1: return(new V3f(edgeOne, (float)(u * scale), edgeTwo));

                case 2: return(new V3f(edgeOne, edgeTwo, (float)(u * scale)));

                default: throw new ArgumentException();
                }
#endif
            }
            else
            {
                return(s_vecToCornerTable[code - m_cornerBasis]);
            }
        }
Exemple #7
0
 /// <summary>
 /// Returns the matrix that transforms from the coordinate system
 /// specified by the basis into the world cordinate system.
 /// </summary>
 public static M44f FromBasis(V3f xAxis, V3f yAxis, V3f zAxis, V3f origin)
 {
     return(new M44f(
                xAxis.X, yAxis.X, zAxis.X, origin.X,
                xAxis.Y, yAxis.Y, zAxis.Y, origin.Y,
                xAxis.Z, yAxis.Z, zAxis.Z, origin.Z,
                0, 0, 0, 1));
 }
Exemple #8
0
 /// <summary>
 /// Constructs rkd-tree from points and kd-tree data.
 /// </summary>
 public static PointRkdTreeF <V3f[], V3f> ToKdTree(this V3f[] points, PointRkdTreeFData data)
 => new PointRkdTreeF <V3f[], V3f>(
     3, points.Length, points,
     (xs, i) => xs[(int)i], (v, i) => (float)v[i],
     (a, b) => V3f.Distance(a, b), (i, a, b) => b - a,
     (a, b, c) => VecFun.DistanceToLine(a, b, c), VecFun.Lerp, 1e-6f,
     data
     );
Exemple #9
0
        /// <summary></summary>
        public FilterNormalDirection(V3f direction, float epsInDegrees)
        {
            var e = (float)Math.Sin(Conversion.RadiansFromDegrees(Fun.Clamp(epsInDegrees, 0.0, 90.0)));

            Direction    = direction.Normalized;
            EpsInDegrees = epsInDegrees;
            m_eps        = e * e;
        }
        public void NormalsFromEmptyArray()
        {
            var ps = new V3f[0];
            var kd = ps.BuildKdTree();
            var ns = ps.EstimateNormalsAsync(16, kd).Result;

            Assert.IsTrue(ns.Length == 0);
        }
        public void NeigbourTest(uint raster)
        {
            var coder = new V3fCoder(raster);

            for (uint code = 0; code < coder.Count; code++)
            {
                uint[] neighbours = new uint[8];
                V3f    n          = coder.DecodeOnCube(code, false);
                uint   nCount     = coder.NeighbourCodes(code, neighbours);

                float min = float.MaxValue;
                float max = float.MinValue;
                for (uint nc = 0; nc < nCount; nc++)
                {
                    V3f   nv   = coder.DecodeOnCube(neighbours[nc], false);
                    float diff = (nv - n).Length;
                    if (diff < min)
                    {
                        min = diff;
                    }
                    if (diff > max)
                    {
                        max = diff;
                    }
                }

                if (min < 0.000001)
                {
                    Console.WriteLine("min too small");
                }
                if (max > 2.0 * min)
                {
                    Console.WriteLine("max too large");
                }

                if (raster < 3)
                {
                    Console.WriteLine("code {0} min {1} max {2}",
                                      code, min, max);
                }

                min *= 0.99f;

                for (uint nc0 = 0; nc0 < nCount; nc0++)
                {
                    V3f nv0 = coder.DecodeOnCube(neighbours[nc0], false);
                    for (uint nc1 = nc0 + 1; nc1 < nCount; nc1++)
                    {
                        V3f   nv1  = coder.DecodeOnCube(neighbours[nc1], false);
                        float diff = (nv1 - nv0).Length;
                        if (diff < min)
                        {
                            Console.Write("neighbours too close");
                        }
                    }
                }
            }
        }
Exemple #12
0
        public static V3f Transform(this Rot2f rot, V3f v)
        {
            float a = Fun.Cos(rot.Angle);
            float b = Fun.Sin(rot.Angle);

            return(new V3f(a * v.X + -b * v.Y,
                           b * v.X + a * v.Y,
                           v.Z));
        }
        public static V3f Multiply(Rot2f rot, V3f vec)
        {
            float ca = (float)System.Math.Cos(rot.Angle);
            float sa = (float)System.Math.Sin(rot.Angle);

            return(new V3f(ca * vec.X + sa * vec.Y,
                           -sa * vec.X + ca * vec.Y,
                           vec.Z));
        }
 /// <summary>
 /// Creates point rkd-tree.
 /// </summary>
 public static PointRkdTreeD <V3f[], V3f> BuildKdTree(this V3f[] self, double kdTreeEps = 1e-6)
 {
     return(new PointRkdTreeD <V3f[], V3f>(
                3, self.Length, self,
                (xs, i) => xs[(int)i], (v, i) => (float)v[i],
                (a, b) => V3f.Distance(a, b), (i, a, b) => b - a,
                (a, b, c) => VecFun.DistanceToLine(a, b, c), VecFun.Lerp, kdTreeEps
                ));
 }
Exemple #15
0
 /// <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
                ));
 }
Exemple #16
0
 /// <summary>
 /// Creates a inverse view tranformation from the given vectors.
 /// Transformation from view- into world-space.
 /// The implementation is the same as FromBasis(right, up, normal, location)
 /// </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 inverse view transformation</returns>
 public static M44f InvViewTrafo(V3f location, V3f right, V3f up, V3f normal)
 {
     return(new M44f(
                right.X, up.X, normal.X, location.X,
                right.Y, up.Y, normal.Y, location.Y,
                right.Z, up.Z, normal.Z, location.Z,
                0, 0, 0, 1
                ));
 }
Exemple #17
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;
        }
Exemple #18
0
        /// <summary>
        /// Calculates the sum for a given set of V3fs.
        /// </summary>
        public static V3f Sum(this IEnumerable <V3f> vectors)
        {
            V3f sum = V3f.Zero;

            foreach (var e in vectors)
            {
                sum += e;
            }

            return(sum);
        }
Exemple #19
0
        /// <summary>
        /// Estimates a normal vector for each point by least-squares-fitting a plane through its k nearest neighbours.
        /// </summary>
        public static V3f[] EstimateNormals(this V3f[] points, int k)
        {
            var kd = new PointRkdTreeD <V3f[], V3f>(
                3, points.Length, points,
                (xs, i) => xs[(int)i], (v, i) => (float)v[i],
                (a, b) => V3f.Distance(a, b), (i, a, b) => b - a,
                (a, b, c) => VecFun.DistanceToLine(a, b, c), VecFun.Lerp, 0
                );

            return(EstimateNormals(points, kd, k));
        }
Exemple #20
0
        /// <summary>
        /// Calculates the centroid for a given set of V3fs.
        /// </summary>
        public static V3f ComputeCentroid(this V3f[] vectors, int[] indices)
        {
            V3f sum = V3f.Zero;

            for (var i = 0; i < indices.Length; i++)
            {
                sum += vectors[indices[i]];
            }

            return(sum / (float)indices.Length);
        }
Exemple #21
0
        /// <summary>
        /// Calculates the centroid for a given set of V3fs.
        /// </summary>
        public static V3f ComputeCentroid(this V3f[] vectors)
        {
            V3f sum = V3f.Zero;

            for (var i = 0; i < vectors.Length; i++)
            {
                sum += vectors[i];
            }

            return(sum / (float)vectors.Length);
        }
Exemple #22
0
        /// <summary>
        /// Calculates the sum for a given set of V3fs.
        /// </summary>
        public static V3f Sum(this V3f[] vectors)
        {
            V3f sum = V3f.Zero;

            for (var i = 0; i < vectors.Length; i++)
            {
                sum += vectors[i];
            }

            return(sum);
        }
        /// <summary>
        /// Calculate all directions that are exactly encoded.
        /// </summary>
        /// <returns>An array of directions.</returns>
        public V3f[] GenerateTable()
        {
            uint dirCount = Count;

            V3f[] directionTable = new V3f[dirCount];
            for (uint dc = 0; dc < dirCount; dc++)
            {
                directionTable[dc] = Decode(dc);
            }
            return(directionTable);
        }
Exemple #24
0
        /// <summary>
        /// Calculates the centroid for a given set of V3fs.
        /// </summary>
        public static V3f ComputeCentroid(this IEnumerable <V3f> vectors)
        {
            V3f sum   = V3f.Zero;
            int count = 0;

            foreach (var e in vectors)
            {
                sum += e;
                count++;
            }

            return(sum / (float)count);
        }
 // 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));
     }
 }
Exemple #26
0
        /// <summary>
        /// Calculates a weighted centroid for a given array of V3fs.
        /// </summary>
        public static V3f ComputeCentroid(this V3f[] vectors, float[] weights)
        {
            V3f   sum       = V3f.Zero;
            float weightSum = 0;

            for (int i = 0; i < vectors.Length; i++)
            {
                sum       += weights[i] * vectors[i];
                weightSum += weights[i];
            }

            return(sum / weightSum);
        }
Exemple #27
0
        /// <summary>
        /// Creates an orthonormal basis from the given normal as z-axis.
        /// The resulting matrix transforms from the local to the global coordinate system.
        /// The normal is expected to be normalized.
        ///
        /// The implementation is based on:
        /// Building an Orthonormal Basis, Revisited, by Duff et al. 2017
        /// </summary>
        public static M33f NormalFrame(V3f n)
        {
            var sg = n.Z >= 0 ? 1 : -1; // original uses copysign(1.0, n.Z) -> not the same as sign where 0 -> 0
            var a  = -1 / (sg + n.Z);
            var b  = n.X * n.Y * a;

            // column 0: [1 + sg * n.X * n.X * a, sg * b, -sg * n.X]
            // column 1: [b, sg + n.Y * n.Y * a, -n.Y]
            // column 2: n
            return(new M33f(1 + sg * n.X * n.X * a, b, n.X,
                            sg * b, sg + n.Y * n.Y * a, n.Y,
                            -sg * n.X, -n.Y, n.Z));
        }
        public void CanEstimateNormalsAsync_FromZeroToThreePoints()
        {
            var r = new Random();

            for (var n = 0; n < 4; n++)
            {
                var ps = new V3f[n].SetByIndex(_ => new V3f(r.NextDouble(), r.NextDouble(), r.NextDouble()));

                var kd = ps.BuildKdTreeAsync().Result;

                var ns = Normals.EstimateNormalsAsync(ps, 16, kd).Result;
                Assert.IsTrue(ns.Length == n);
            }
        }
        /// <summary>
        /// Code generation.
        /// </summary>
        public void WriteCornerNeighbours(uint corner)
        {
            V3f v = s_vecToCornerTableNonNormalized[corner];

            string f = "    neighbourCodes[{0}] = ";
            float  s = (float)m_invDoubleRaster;

            Console.Write(f, 0); WriteCode(Encode(v + s * new V3f(-1, 0, 0)));
            Console.Write(f, 1); WriteCode(Encode(v + s * new V3f(0, -1, 0)));
            Console.Write(f, 2); WriteCode(Encode(v + s * new V3f(0, 0, -1)));
            Console.Write(f, 3); WriteCode(Encode(v + s * new V3f(1, 0, 0)));
            Console.Write(f, 4); WriteCode(Encode(v + s * new V3f(0, 1, 0)));
            Console.Write(f, 5); WriteCode(Encode(v + s * new V3f(0, 0, 1)));
        }
Exemple #30
0
        /// <summary>
        /// Calculates a weighted centroid for vectors and weights given by indices.
        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].
        /// </summary>
        public static V3f ComputeCentroid(this V3f[] vectors, float[] weights, int[] indices)
        {
            V3f   sum       = V3f.Zero;
            float weightSum = 0;

            for (int i = 0; i < indices.Length; i++)
            {
                var w = weights[indices[i]];
                sum       += w * vectors[indices[i]];
                weightSum += w;
            }

            return(sum / weightSum);
        }