示例#1
0
        static void TestSchmitzVertexFromHermiteData()
        {
            while (true)
            {
                HermiteData hermite = new HermiteData(new List <Microsoft.Xna.Framework.Vector3>(), new List <Microsoft.Xna.Framework.Vector3>());

                Console.WriteLine("Enter position 1:");
                string pos1str = Console.ReadLine();
                Console.WriteLine("Enter normal 1:");
                string normal1str = Console.ReadLine();
                Console.WriteLine("Enter position 2:");
                string pos2str = Console.ReadLine();
                Console.WriteLine("Enter normal 2:");
                string normal2str = Console.ReadLine();
                Console.WriteLine("Enter position 3:");
                string pos3str = Console.ReadLine();
                Console.WriteLine("Enter normal 3:");
                string normal3str = Console.ReadLine();

                string[] pos1parts    = pos1str.Split(',');
                string[] normal1parts = normal1str.Split(',');
                string[] pos2parts    = pos2str.Split(',');
                string[] normal2parts = normal2str.Split(',');
                string[] pos3parts    = pos3str.Split(',');
                string[] normal3parts = normal3str.Split(',');

                Vector3 pos1    = new Vector3(Single.Parse(pos1parts[0].Trim()), Single.Parse(pos1parts[1].Trim()), Single.Parse(pos1parts[2].Trim()));
                Vector3 normal1 = new Vector3(Single.Parse(normal1parts[0].Trim()), Single.Parse(normal1parts[1].Trim()), Single.Parse(normal1parts[2].Trim()));
                Vector3 pos2    = new Vector3(Single.Parse(pos2parts[0].Trim()), Single.Parse(pos2parts[1].Trim()), Single.Parse(pos2parts[2].Trim()));
                Vector3 normal2 = new Vector3(Single.Parse(normal2parts[0].Trim()), Single.Parse(normal2parts[1].Trim()), Single.Parse(normal2parts[2].Trim()));
                Vector3 pos3    = new Vector3(Single.Parse(pos3parts[0].Trim()), Single.Parse(pos3parts[1].Trim()), Single.Parse(pos3parts[2].Trim()));
                Vector3 normal3 = new Vector3(Single.Parse(normal3parts[0].Trim()), Single.Parse(normal3parts[1].Trim()), Single.Parse(normal3parts[2].Trim()));
                normal1.Normalize();
                normal2.Normalize();
                normal3.Normalize();

                Console.WriteLine("Position 1: {0}", pos1);
                Console.WriteLine("Normal 1: {0}", normal1);
                Console.WriteLine("Position 2: {0}", pos2);
                Console.WriteLine("Normal 2: {0}", normal2);
                Console.WriteLine("Position 3: {0}", pos3);
                Console.WriteLine("Normal 3: {0}", normal3);

                hermite.Add(pos1, normal1);
                hermite.Add(pos2, normal2);
                //hermite.Add(pos3, normal3);

                Stopwatch sw = new Stopwatch();

                sw.Start();
                Vector3 pos = DualContouring.SchmitzVertexFromHermiteData(hermite, 0.001f, 100);
                sw.Stop();

                Console.WriteLine("Out: {0}", pos);
                Console.WriteLine("Took {0}ms", sw.ElapsedMilliseconds);
            }
        }
        private void ProcessBlock(HashSet <Edge> intersectingEdges, List <VertexPositionNormalColorLight> vertices, Dictionary <Vector3I, short> positionToIndex, Chunk c, GridPoint min, Vector3I worldPosition, Vector3I localPosition)
        {
            int lX = localPosition.X;
            int lY = localPosition.Y;
            int lZ = localPosition.Z;

            GridPoint XYZ          = min;
            GridPoint XMaxYZ       = c.PointAt(lX + 1, lY, lZ);
            GridPoint XYMaxZ       = c.PointAt(lX, lY + 1, lZ);
            GridPoint XYZMax       = c.PointAt(lX, lY, lZ + 1);
            GridPoint XMaxYMaxZ    = c.PointAt(lX + 1, lY + 1, lZ);
            GridPoint XMaxYZMax    = c.PointAt(lX + 1, lY, lZ + 1);
            GridPoint XYMaxZMax    = c.PointAt(lX, lY + 1, lZ + 1);
            GridPoint XMaxYMaxZMax = c.PointAt(lX + 1, lY + 1, lZ + 1);

            Tuple <HermiteData, Edge[]> data = CubeInfo(c, localPosition, XYZ, XMaxYZ, XYMaxZ, XYZMax, XMaxYMaxZ, XMaxYZMax, XYMaxZMax, XMaxYMaxZMax);

            HermiteData hermite = data.Item1;

            // If there are no intersections, this is an interior point.  Therefore, don't build any vertices.
            if (hermite.IntersectionPoints.Count == 0)
            {
                return;
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            // investigate possible optimization by using AddRange, since it re-allocates the list only once.
            List <Edge> edges = new List <Edge>();

            for (int i = 0; i < data.Item2.Length; i++)
            {
                if (!intersectingEdges.Contains(data.Item2[i]))
                {
                    edges.Add(data.Item2[i]);
                }
            }

            intersectingEdges.UnionWith(edges);

            Vector3 minimizingVertex = DualContouring.SchmitzVertexFromHermiteData(hermite, 0.001f, DualContouring.MAX_ITERATIONS);

            float light = (XYZ.Metadata[0] + XMaxYZ.Metadata[0] + XYMaxZ.Metadata[0] + XYZMax.Metadata[0] + XMaxYMaxZ.Metadata[0] + XMaxYZMax.Metadata[0] + XYMaxZMax.Metadata[0] + XMaxYMaxZMax.Metadata[0]);

            light /= 8;  // average
            light /= 15; // out of maximum value of 15

            vertices.Add(new VertexPositionNormalColorLight(c.Position.ToVector3() + minimizingVertex, Vector3.Zero, Color.Green, light));
            positionToIndex.Add(localPosition, (short)(_vertices[c].Count - 1));

            //_positionToQEF.Add(localPosition, new CubeInfo(minimizingVertex, data.Item2));
        }
        private Tuple <HermiteData, Edge[]> CubeInfo(Chunk c, Vector3I min, GridPoint XYZ, GridPoint XMaxYZ, GridPoint XYMaxZ, GridPoint XYZMax, GridPoint XMaxYMaxZ, GridPoint XMaxYZMax, GridPoint XYMaxZMax, GridPoint XMaxYMaxZMax)
        {
            HermiteData hermiteData = new HermiteData(new List <Vector3>(), new List <Vector3>());

            // get edge table index
            int cubeIndex = 0;

            if (XYZ.Density < _minimumSolidDensity)
            {
                cubeIndex += 1;
            }
            if (XMaxYZ.Density < _minimumSolidDensity)
            {
                cubeIndex += 2;
            }
            if (XMaxYMaxZ.Density < _minimumSolidDensity)
            {
                cubeIndex += 4;
            }
            if (XYMaxZ.Density < _minimumSolidDensity)
            {
                cubeIndex += 8;
            }
            if (XYZMax.Density < _minimumSolidDensity)
            {
                cubeIndex += 16;
            }
            if (XMaxYZMax.Density < _minimumSolidDensity)
            {
                cubeIndex += 32;
            }
            if (XMaxYMaxZMax.Density < _minimumSolidDensity)
            {
                cubeIndex += 64;
            }
            if (XYMaxZMax.Density < _minimumSolidDensity)
            {
                cubeIndex += 128;
            }

            GridPoint[][][] lookupTable = new GridPoint[][][]
            {
                new GridPoint[][]
                {
                    new GridPoint[]
                    {
                        XYZ,
                        XYZMax,
                    },
                    new GridPoint[]
                    {
                        XYMaxZ,
                        XYMaxZMax,
                    }
                },
                new GridPoint[][]
                {
                    new GridPoint[]
                    {
                        XMaxYZ,
                        XMaxYZMax,
                    },
                    new GridPoint[]
                    {
                        XMaxYMaxZ,
                        XMaxYMaxZMax,
                    }
                },
            };

            int edge = _edgeTable[cubeIndex];

            List <Edge> xEdges = new List <Edge>();

            // loop through all the edges
            for (int i = 0; i < 12; i++)
            {
                // if this edge contains no intersection, skip it
                if ((edge & (1 << i)) == 0)
                {
                    continue;
                }

                int[] corner1Offset = _intersections[i][0];
                int[] corner2Offset = _intersections[i][1];

                Vector3I corner1 = min;
                Vector3I corner2 = min;

                corner1.X += corner1Offset[0];
                corner1.Y += corner1Offset[1];
                corner1.Z += corner1Offset[2];

                corner2.X += corner2Offset[0];
                corner2.Y += corner2Offset[1];
                corner2.Z += corner2Offset[2];

                GridPoint corner1Point = lookupTable[corner1Offset[0]][corner1Offset[1]][corner1Offset[2]];
                GridPoint corner2Point = lookupTable[corner2Offset[0]][corner2Offset[1]][corner2Offset[2]];

                Vector3I  delta = (corner2 - corner1) * (corner1Point.Density < _minimumSolidDensity ? -1 : 1); // negate if corner1 is less than the isovalue because we assume corner2 at first.
                Direction dir   = GetDirectionFromDelta(delta);

                xEdges.Add(new Edge(corner1, corner2, dir));

                Vector3 intersectionPoint = DualContouring.InterpolateIntersectionPoint(_minimumSolidDensity, corner1.ToVector3(), corner2.ToVector3(),
                                                                                        corner1Point.Density,
                                                                                        corner2Point.Density);

                Vector3I  minCorner = Vector3I.Min(corner1, corner2);
                GridPoint minPoint  = (minCorner == corner1) ? corner1Point : corner2Point;

                Vector3   naturalNormal           = _densityGradientFunction.df(intersectionPoint.X, intersectionPoint.Y, intersectionPoint.Z);
                Vector3F8 compressedNaturalNormal = new Vector3F8(naturalNormal);

                Vector3 normal = compressedNaturalNormal.ToVector3();
                //normal = naturalNormal;

                switch (dir)
                {
                case Direction.XIncreasing:
                case Direction.XDecreasing:
                    normal = minPoint.XPositiveNormal;

                    if (normal == Vector3.Zero)
                    {
                        GridPoint withNormal = new GridPoint(minPoint);

                        withNormal.XPositiveNormal = naturalNormal;

                        c.SetPoint(minCorner.X, minCorner.Y, minCorner.Z, withNormal, true);
                    }
                    break;

                case Direction.YIncreasing:
                case Direction.YDecreasing:
                    normal = minPoint.YPositiveNormal;

                    if (normal == Vector3.Zero)
                    {
                        GridPoint withNormal = new GridPoint(minPoint);

                        withNormal.YPositiveNormal = naturalNormal;

                        c.SetPoint(minCorner.X, minCorner.Y, minCorner.Z, withNormal, true);
                    }
                    break;

                case Direction.ZIncreasing:
                case Direction.ZDecreasing:
                    normal = minPoint.ZPositiveNormal;

                    if (normal == Vector3.Zero)
                    {
                        GridPoint withNormal = new GridPoint(minPoint);

                        withNormal.ZPositiveNormal = naturalNormal;

                        c.SetPoint(minCorner.X, minCorner.Y, minCorner.Z, withNormal, true);
                    }
                    break;
                }

                if (normal == Vector3.Zero)
                {
                    normal = naturalNormal;
                }

                normal.Normalize();

                hermiteData.Add(intersectionPoint, normal);
            }

            Tuple <HermiteData, Edge[]> ret = new Tuple <HermiteData, Edge[]>(hermiteData, xEdges.ToArray());

            return(ret);
        }