Beispiel #1
0
        /// <summary>
        /// Duplicate of the inlined version!!!!!! DANGEROUS
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="signs"></param>
        /// <param name="cube"></param>
        /// <returns></returns>
        public static Vector3 calculateQefPoint(AbstractHermiteGrid grid, bool[] signs, Point3 cube)
        {
            //TODO: this can be optimized probably!
            var changingEdges = grid.GetAllEdgeIds().Where(e =>
            {
                var ids = grid.GetEdgeVertexIds(e);
                return(signs[ids[0]] != signs[ids[1]]);
            }).ToArray();


            var positions = changingEdges.Select(e => grid.GetEdgeIntersectionCubeLocal(cube, e)).ToArray();
            var normals   = changingEdges.Select(e => grid.GetEdgeNormal(cube, e)).ToArray();

            var meanIntersectionPoint = positions.Aggregate((a, b) => a + b) * (1f / positions.Length);
            var leastsquares          = QEFCalculator.CalculateCubeQEF(normals, positions, meanIntersectionPoint);

            var qefPoint = new Vector3(leastsquares[0], leastsquares[1], leastsquares[2]);

            if (qefPoint[0] < 0 || qefPoint[1] < 0 || qefPoint[2] < 0 ||
                qefPoint[0] > 1 || qefPoint[1] > 1 || qefPoint[2] > 1)
            {
                qefPoint = meanIntersectionPoint; // I found someone online who does this too: http://ngildea.blogspot.be/2014/11/implementing-dual-contouring.html
                //TODO: should probably fix the QEF, maybe by removing singular values

                //ERROR!
                //throw new InvalidOperationException("QEF returned solution outside of cube");
            }
            return(qefPoint);
        }
        public void TestQEF_UnderDetermined()
        {
            var normals = new[] { Vector3.UnitX, Vector3.UnitY, Vector3.UnitX, Vector3.UnitY };
            var posses  = new[] { Vector3.UnitX * 2, Vector3.UnitY * 2, Vector3.UnitX * 2 + Vector3.UnitZ * 2, Vector3.UnitY * 2 + Vector3.UnitZ * 2 };
            var result  = QEFCalculator.CalculateCubeQEF(normals, posses, new Vector3(1, 1, 1)).ToArray();

            result.Print();
            CollectionAssert.AreEqual(new float[] { 2, 2, 1 }, result);
        }
        public void TestQEF_Simple()
        {
            var normals = new[] { Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ };
            var posses  = new[] { Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ };
            var result  = QEFCalculator.CalculateCubeQEF(normals, posses, new Vector3(1, 1, 1)).ToArray();

            result.Print();
            CollectionAssert.AreEqual(new float[] { 1, 1, 1 }, result);
        }
        public void TestQEF_Complex()
        {
            var p1 = new Vector3(0.4191761f, 1, 0);
            var p2 = new Vector3(0.8585715f, 1, 1);
            var p3 = new Vector3(1, 0.1983433f, 0);
            var p4 = new Vector3(1, 0.5505102f, 1);
            var n1 = new Vector3(-1, 0, 0);
            var n2 = new Vector3(-0.8926786f, -0.25f, -0.375f);
            var n3 = new Vector3(0, -1, 0);
            var n4 = new Vector3(-0.875f, -0.3061862f, -0.375f);

            var qef = QEFCalculator.CalculateCubeQEF(new Vector3[] { n1, n2, n3, n4 }, new Vector3[] { p1, p2, p3, p4 },
                                                     new Vector3[] { p1, p2, p3, p4 }.Aggregate((a, b) => a + b) / 4f);
            var v = new Vector3(qef[0], qef[1], qef[2]);

            Console.WriteLine(v);
            //TODO: this should be inside of cube but isnt!
        }
Beispiel #5
0
        private static void createQEFVertices(List <Vector3> vertices, AbstractHermiteGrid grid, Dictionary <Point3, int> vIndex)
        {
            var cubeSigns = new bool[8];

            var edgeVertexIds = grid.GetAllEdgeIds().Select(e => grid.GetEdgeVertexIds(e)).ToArray();
            var edgeOffsets   = grid.GetAllEdgeIds().Select(e => grid.GetEdgeOffsets(e)).ToArray();

            int changingEdgeCount = 0;

            int[]     changingEdges = new int[12];
            Vector3[] positions     = new Vector3[12];
            Vector3[] normals       = new Vector3[12];

            grid.ForEachCube(curr =>
            {
                grid.GetCubeSigns(curr, cubeSigns);
                bool allTrue  = true;
                bool allFalse = true;
                for (int i = 0; i < 8; i++)
                {
                    var sign = cubeSigns[i];
                    allTrue  = sign && allTrue;
                    allFalse = !sign && allFalse;
                }
                if (allTrue || allFalse)
                {
                    return;                         // no sign changes
                }
                //if ( cubeSigns.All( v => v ) || !cubeSigns.Any( v => v ) ) return; // no sign changes

                changingEdgeCount = 0;
                for (int i = 0; i < edgeVertexIds.Length; i++)
                {
                    var ids = edgeVertexIds[i];
                    if (cubeSigns[ids[0]] == cubeSigns[ids[1]])
                    {
                        continue;
                    }

                    changingEdges[changingEdgeCount] = i;
                    changingEdgeCount++;
                }

                for (int i = 0; i < changingEdgeCount; i++)
                {
                    var iEdgeId      = changingEdges[i];
                    var iEdgeOffsets = edgeOffsets[iEdgeId];
                    var iEdgeData    = grid.getEdgeData(curr, iEdgeId);
                    positions[i]     = Vector3.Lerp(iEdgeOffsets[0], iEdgeOffsets[1], iEdgeData.W);
                    normals[i]       = iEdgeData.TakeXYZ();
                }


                var meanIntersectionPoint = new Vector3();
                for (int i = 0; i < changingEdgeCount; i++)
                {
                    meanIntersectionPoint = meanIntersectionPoint + positions[i];
                }
                meanIntersectionPoint = meanIntersectionPoint * (1f / changingEdgeCount);

                var leastsquares = QEFCalculator.CalculateCubeQEF(normals, positions, changingEdgeCount, meanIntersectionPoint);

                var qefPoint1 = new Vector3();
                qefPoint1     = new Vector3(leastsquares[0], leastsquares[1], leastsquares[2]);

                if (qefPoint1[0] < 0 || qefPoint1[1] < 0 || qefPoint1[2] < 0 ||
                    qefPoint1[0] > 1 || qefPoint1[1] > 1 || qefPoint1[2] > 1)
                {
                    qefPoint1 = meanIntersectionPoint;     // I found someone online who does this too: http://ngildea.blogspot.be/2014/11/implementing-dual-contouring.html
                    //TODO: should probably fix the QEF, maybe by removing singular values

                    //ERROR!
                    //throw new InvalidOperationException("QEF returned solution outside of cube");
                }

                vIndex[curr] = vertices.Count;
                vertices.Add(qefPoint1 + (Vector3)curr.ToVector3());
            });
        }