Beispiel #1
0
        public static void test_AABBTree_RayHit(int meshCase = 8)
        {
            DMesh3         mesh = MakeSpatialTestMesh(meshCase);
            DMeshAABBTree3 tree = new DMeshAABBTree3(mesh);

            tree.Build();
            tree.TestCoverage();

            AxisAlignedBox3d bounds = mesh.CachedBounds;
            Vector3d         ext    = bounds.Extents;
            Vector3d         c      = bounds.Center;
            double           r      = bounds.DiagonalLength / 4;

            Random rand = new Random(316136327);


            tree.FindNearestHitTriangle(
                new Ray3f(100 * Vector3f.One, Vector3f.One));


            // test rays out from center of box, and rays in towards it
            // (should all hit for standard test cases)
            int hits = 0;
            int N    = (meshCase > 7) ? 1000 : 10000;

#if true
            for (int ii = 0; ii < N; ++ii)
            {
                if (ii % 100 == 0)
                {
                    System.Console.WriteLine("{0} / {1}", ii, N);
                }

                Vector3d p   = (ii < N / 2) ? c : c + 2 * r * rand.Direction();
                Vector3d d   = (ii < N / 2) ? rand.Direction() : (c - p).Normalized;
                Ray3d    ray = new Ray3d(p, d);

                int tNearBrute = MeshQueries.FindHitTriangle_LinearSearch(mesh, ray);
                int tNearTree  = tree.FindNearestHitTriangle(ray);

                //System.Console.WriteLine("{0} - {1}", tNearBrute, tree.TRI_TEST_COUNT);

                if (tNearBrute == DMesh3.InvalidID)
                {
                    Debug.Assert(tNearBrute == tNearTree);
                    continue;
                }
                ++hits;

                IntrRay3Triangle3 qBrute = MeshQueries.TriangleIntersection(mesh, tNearBrute, ray);
                IntrRay3Triangle3 qTree  = MeshQueries.TriangleIntersection(mesh, tNearTree, ray);

                double dotBrute = mesh.GetTriNormal(tNearBrute).Dot(ray.Direction);
                double dotTree  = mesh.GetTriNormal(tNearTree).Dot(ray.Direction);

                Debug.Assert(Math.Abs(qBrute.RayParameter - qTree.RayParameter) < MathUtil.ZeroTolerance);
            }
            Debug.Assert(hits == N);
            System.Console.WriteLine("in/out rays: {0} hits out of {1} rays", hits, N);
#endif



            // random rays
            hits = 0;
            for (int ii = 0; ii < N; ++ii)
            {
                if (ii % 100 == 0)
                {
                    System.Console.WriteLine("{0} / {1}", ii, N);
                }

                Vector3d target = c + rand.PointInRange(r);
                Vector3d o      = c + rand.PointInRange(10 * r);
                Ray3d    ray    = new Ray3d(o, (target - o).Normalized);

                int tNearBrute = MeshQueries.FindHitTriangle_LinearSearch(mesh, ray);
                int tNearTree  = tree.FindNearestHitTriangle(ray);

                //System.Console.WriteLine("{0} - {1}", tNearBrute, tree.TRI_TEST_COUNT);

                if (tNearBrute == DMesh3.InvalidID)
                {
                    Debug.Assert(tNearBrute == tNearTree);
                    continue;
                }
                ++hits;

                IntrRay3Triangle3 qBrute = MeshQueries.TriangleIntersection(mesh, tNearBrute, ray);
                IntrRay3Triangle3 qTree  = MeshQueries.TriangleIntersection(mesh, tNearTree, ray);

                double dotBrute = mesh.GetTriNormal(tNearBrute).Dot(ray.Direction);
                double dotTree  = mesh.GetTriNormal(tNearTree).Dot(ray.Direction);

                Debug.Assert(Math.Abs(qBrute.RayParameter - qTree.RayParameter) < MathUtil.ZeroTolerance);
            }

            System.Console.WriteLine("random rays: hit {0} of {1} rays", hits, N);
        }
Beispiel #2
0
    int[] insert_points(Vector3d[] points, DMesh3 mesh)
    {
        int[]         MapV = new int[points.Length];
        HashSet <int> newV = new HashSet <int>();

        for (int i = 0; i < points.Length; ++i)
        {
            MapV[i] = DMesh3.InvalidID;

            Vector3d pt = points[i];
            pt.Normalize();
            Ray3d ray = new Ray3d(Vector3d.Zero, pt);

            int hit_tid =
                MeshQueries.FindHitTriangle_LinearSearch(mesh, ray);
            if (hit_tid == DMesh3.InvalidID)
            {
                continue;
            }
            Index3i hit_tri = mesh.GetTriangle(hit_tid);

            IntrRay3Triangle3 intr =
                MeshQueries.TriangleIntersection(mesh, hit_tid, ray);
            Vector3d bary = intr.TriangleBaryCoords;
            bool     done = false;
            for (int j = 0; j < 3 && done == false; ++j)
            {
                if (bary[j] > 0.9)
                {
                    // hit-vertex case
                    if (newV.Contains(hit_tri[j]) == false)
                    {
                        MapV[i] = hit_tri[j];
                        newV.Add(MapV[i]);
                        done = true;
                    }
                }
                else if (bary[j] < 0.1)
                {
                    // hit-edge case
                    DMesh3.EdgeSplitInfo split_info;
                    MeshResult           splitResult = mesh.SplitEdge(hit_tri[(j + 1) % 3], hit_tri[(j + 2) % 3], out split_info);
                    if (splitResult == MeshResult.Ok)
                    {
                        MapV[i] = split_info.vNew;
                        newV.Add(MapV[i]);
                        mesh.SetVertex(split_info.vNew, points[i]);
                        done = true;
                    }
                }
            }
            if (done)
            {
                continue;
            }

            DMesh3.PokeTriangleInfo poke_info;
            MeshResult result = mesh.PokeTriangle(hit_tid, out poke_info);
            if (result == MeshResult.Ok)
            {
                MapV[i] = poke_info.new_vid;
                newV.Add(MapV[i]);
                mesh.SetVertex(poke_info.new_vid, points[i]);
            }
        }

        return(MapV);
    }
        // [RMS] this only tests some basic cases...
        public static void test_RayBoxIntersect()
        {
            Random rand = new Random(316136327);

            // check that box hit works
            for (int ii = 0; ii < 1000; ++ii)
            {
                // generate random triangle
                Triangle3d       t      = new Triangle3d(rand.PointInRange(10), rand.PointInRange(10), rand.PointInRange(10));
                AxisAlignedBox3d bounds = new AxisAlignedBox3d(t.V0);
                bounds.Contain(t.V1);
                bounds.Contain(t.V2);
                Vector3d c = (t.V0 + t.V1 + t.V2) / 3.0;
                for (int jj = 0; jj < 1000; ++jj)
                {
                    Vector3d d   = rand.Direction();
                    Ray3d    ray = new Ray3d(c - 100 * d, d);
                    IntrRay3AxisAlignedBox3 bhit = new IntrRay3AxisAlignedBox3(ray, bounds);
                    Debug.Assert(bhit.Find());
                    IntrRay3Triangle3 thit = new IntrRay3Triangle3(ray, t);
                    Debug.Assert(thit.Find());
                    Debug.Assert(bhit.RayParam0 < thit.RayParameter);
                }
            }

            int N = 100;

            for (int ii = 0; ii < N; ++ii)
            {
                // generate random boxes
                Vector3d         c     = rand.PointInRange(10);
                Vector3d         e     = rand.PositivePoint();
                AxisAlignedBox3d aabox = new AxisAlignedBox3d(c - e, c + e);
                Box3d            obox  = new Box3d(c, Vector3d.AxisX, Vector3d.AxisY, Vector3d.AxisZ, e);
                double           r     = aabox.DiagonalLength;

                // center-out tests
                for (int jj = 0; jj < N; ++jj)
                {
                    Ray3d ray = new Ray3d(c, rand.Direction());
                    assert_same_hit(aabox, obox, ray, true);
                }

                // outside-in tests
                for (int jj = 0; jj < N; ++jj)
                {
                    Vector3d p   = c + 2 * r * rand.Direction();
                    Ray3d    ray = new Ray3d(p, (c - p).Normalized);
                    assert_same_hit(aabox, obox, ray, true);
                }
            }



            // random rays
            int hits   = 0;
            int InnerN = 1000;

            for (int ii = 0; ii < N; ++ii)
            {
                // generate random boxe
                Vector3d c = rand.PointInRange(10);
                Vector3d e = rand.PositivePoint();

                // every tenth box, set an axis to degenerate
                if (ii % 10 == 0)
                {
                    e[rand.Next() % 3] = 0;
                }


                AxisAlignedBox3d aabox = new AxisAlignedBox3d(c - e, c + e);
                Box3d            obox  = new Box3d(c, Vector3d.AxisX, Vector3d.AxisY, Vector3d.AxisZ, e);
                double           r     = aabox.DiagonalLength;


                TrivialBox3Generator boxgen = new TrivialBox3Generator()
                {
                    Box = obox
                };
                boxgen.Generate();
                DMesh3 mesh = new DMesh3();
                boxgen.MakeMesh(mesh);

                for (int i = 0; i < InnerN; ++i)
                {
                    Vector3d target = c + rand.PointInRange(r);
                    Vector3d o      = c + rand.PointInRange(10 * r);
                    Ray3d    ray    = new Ray3d(o, (target - o).Normalized);
                    assert_same_hit(aabox, obox, ray, false);

                    int  hitT     = MeshQueries.FindHitTriangle_LinearSearch(mesh, ray);
                    bool bMeshHit = (hitT != DMesh3.InvalidID);
                    if (bMeshHit)
                    {
                        ++hits;
                    }
                    IntrRay3AxisAlignedBox3 aabbhit = new IntrRay3AxisAlignedBox3(ray, aabox);
                    Debug.Assert(aabbhit.Find() == bMeshHit);
                    Debug.Assert(aabbhit.Test() == bMeshHit);
                }
            }

            System.Console.WriteLine("hit {0} of {1} rays", hits, N * InnerN);
        }