Esempio n. 1
0
        static void CheckWide <TShape, TShapeWide>(ref RigidPoses poses, ref TShapeWide shapeWide, ref Vector3 origin, ref Vector3 direction, bool intersected, float t, ref Vector3 normal)
            where TShape : IConvexShape where TShapeWide : IShapeWide <TShape>
        {
            RayWide rayWide;

            Vector3Wide.Broadcast(origin, out rayWide.Origin);
            Vector3Wide.Broadcast(direction, out rayWide.Direction);

            shapeWide.RayTest(ref poses, ref rayWide, out var intersectedWide, out var tWide, out var normalWide);
            if (intersectedWide[0] < 0 != intersected)
            {
                Console.WriteLine($"Wide ray boolean result disagrees with scalar ray.");
            }
            if (intersected && intersectedWide[0] < 0)
            {
                if (Math.Abs(tWide[0] - t) > 1e-7f)
                {
                    Console.WriteLine("Wide ray t disagrees with scalar ray.");
                }
                if (Math.Abs(normalWide.X[0] - normal.X) > 1e-7f ||
                    Math.Abs(normalWide.Y[0] - normal.Y) > 1e-7f ||
                    Math.Abs(normalWide.Z[0] - normal.Z) > 1e-7f)
                {
                    Console.WriteLine("Wide ray normal disagrees with scalar ray.");
                }
            }
        }
Esempio n. 2
0
 public unsafe override void Initialize(ContentArchive content, Camera camera)
 {
     {
         SphereTriangleTester tester;
         SphereWide           sphere = default;
         sphere.Broadcast(new Sphere(0.5f));
         TriangleWide triangle = default;
         var          a        = new Vector3(0, 0, 0);
         var          b        = new Vector3(1, 0, 0);
         var          c        = new Vector3(0, 0, 1);
         //var center = (a + b + c) / 3f;
         //a -= center;
         //b -= center;
         //c -= center;
         triangle.Broadcast(new Triangle(a, b, c));
         var margin = new Vector <float>(1f);
         Vector3Wide.Broadcast(new Vector3(1, -1, 0), out var offsetB);
         QuaternionWide.Broadcast(QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2), out var orientationB);
         tester.Test(ref sphere, ref triangle, ref margin, ref offsetB, ref orientationB, Vector <float> .Count, out var manifold);
     }
     {
         CapsuleTriangleTester tester;
         CapsuleWide           capsule = default;
         capsule.Broadcast(new Capsule(0.5f, 0.5f));
         TriangleWide triangle = default;
         var          a        = new Vector3(0, 0, 0);
         var          b        = new Vector3(1, 0, 0);
         var          c        = new Vector3(0, 0, 1);
         //var center = (a + b + c) / 3f;
         //a -= center;
         //b -= center;
         //c -= center;
         triangle.Broadcast(new Triangle(a, b, c));
         var margin = new Vector <float>(2f);
         Vector3Wide.Broadcast(new Vector3(-1f, -0.5f, -1f), out var offsetB);
         QuaternionWide.Broadcast(QuaternionEx.CreateFromAxisAngle(Vector3.Normalize(new Vector3(-1, 0, 1)), MathHelper.PiOver2), out var orientationA);
         QuaternionWide.Broadcast(QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), 0), out var orientationB);
         tester.Test(ref capsule, ref triangle, ref margin, ref offsetB, ref orientationA, ref orientationB, Vector <float> .Count, out var manifold);
     }
     {
         BoxTriangleTester tester;
         BoxWide           shape = default;
         shape.Broadcast(new Box(1f, 1f, 1f));
         TriangleWide triangle = default;
         var          a        = new Vector3(0, 0, 0);
         var          b        = new Vector3(1, 0, 0);
         var          c        = new Vector3(0, 0, 1);
         //var center = (a + b + c) / 3f;
         //a -= center;
         //b -= center;
         //c -= center;
         triangle.Broadcast(new Triangle(a, b, c));
         var margin = new Vector <float>(2f);
         Vector3Wide.Broadcast(new Vector3(-1f, -0.5f, -1f), out var offsetB);
         QuaternionWide.Broadcast(QuaternionEx.CreateFromAxisAngle(Vector3.Normalize(new Vector3(-1, 0, 1)), MathHelper.PiOver2), out var orientationA);
         QuaternionWide.Broadcast(QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), 0), out var orientationB);
         tester.Test(ref shape, ref triangle, ref margin, ref offsetB, ref orientationA, ref orientationB, Vector <float> .Count, out var manifold);
     }
     {
         TrianglePairTester tester;
         TriangleWide       a = default, b = default;
Esempio n. 3
0
        public static void Test <TShape, TShapeWide, TTester>() where TShape : IConvexShape where TTester : IRayTester <TShape> where TShapeWide : IShapeWide <TShape>
        {
            const int shapeIterations     = 1000;
            const int transformIterations = 100;
            const int outsideToInsideRays = 100;
            const int insideRays          = 10;
            const int outsideRays         = 100;
            const int outwardPointingRays = 100;

            const float volumeInnerMargin = 1e-4f;

            const float positionBoundsSpan = 100;
            const float positionMin        = positionBoundsSpan * -0.5f;

            const float outsideMinimumDistance = 0.02f;
            const float outsideDistanceSpan    = 1000;

            const float tangentMinimumDistance      = 0.02f;
            const float tangentDistanceSpan         = 10;
            const float tangentCentralExclusionMin  = 0.01f;
            const float tangentCentralExclusionSpan = 10;
            const float tangentSourceSpanMin        = 0.01f;
            const float tangentSourceSpanSpan       = 1000f;

            const float outwardPointingSpan = 1000f;

            var        tester    = default(TTester);
            Random     random    = new Random(5);
            TShapeWide shapeWide = default;

            for (int shapeIteration = 0; shapeIteration < shapeIterations; ++shapeIteration)
            {
                tester.GetRandomShape(random, out var shape);
                shapeWide.Broadcast(shape);
                for (int transformIteration = 0; transformIteration < transformIterations; ++transformIteration)
                {
                    RigidPose pose;
                    pose.Position = new Vector3(positionMin) + positionBoundsSpan * new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble());
                    GetUnitQuaternion(random, out pose.Orientation);
                    Matrix3x3.CreateFromQuaternion(pose.Orientation, out var orientation);
                    RigidPoses poses;
                    Vector3Wide.Broadcast(pose.Position, out poses.Position);
                    QuaternionWide.Broadcast(pose.Orientation, out poses.Orientation);
                    for (int rayIndex = 0; rayIndex < outsideToInsideRays; ++rayIndex)
                    {
                        tester.GetSurface(random, ref shape, out var pointOnSurface, out var normal);
                        var localSourcePoint = pointOnSurface + normal * (outsideMinimumDistance + (float)random.NextDouble() * outsideDistanceSpan);
                        tester.GetPointInVolume(random, volumeInnerMargin, ref shape, out var localTargetPoint);

                        Matrix3x3.Transform(localSourcePoint, orientation, out var sourcePoint);
                        sourcePoint += pose.Position;
                        var directionScale = (0.01f + 2 * (float)random.NextDouble());
                        var localDirection = (localTargetPoint - localSourcePoint) * directionScale;
                        Matrix3x3.Transform(localDirection, orientation, out var direction);

                        bool intersected;
                        if (intersected = shape.RayTest(pose, sourcePoint, direction, out var t, out var rayTestedNormal))
                        {
                            //If the ray start is outside the shape and the target point is inside, then the ray impact should exist on the surface of the shape.
                            var hitLocation      = sourcePoint + t * direction;
                            var localHitLocation = hitLocation - pose.Position;
                            Matrix3x3.TransformTranspose(localHitLocation, orientation, out localHitLocation);
                            if (!tester.PointIsOnSurface(ref shape, ref localHitLocation))
                            {
                                Console.WriteLine("Outside->inside ray detected non-surface impact.");
                            }
                        }
Esempio n. 4
0
        public static void Test()
        {
            var random = new Random(4);
            var timer  = new Stopwatch();
            var symmetricVectorSandwichTime        = 0.0;
            var symmetricWideVectorSandwichTime    = 0.0;
            var triangularWideVectorSandwichTime   = 0.0;
            var symmetricWide2x3SandwichTime       = 0.0;
            var triangularWide2x3SandwichTime      = 0.0;
            var symmetricSkewSandwichTime          = 0.0;
            var symmetricWideSkewSandwichTime      = 0.0;
            var triangularWideSkewSandwichTime     = 0.0;
            var symmetricRotationSandwichTime      = 0.0;
            var symmetricWideRotationSandwichTime  = 0.0;
            var triangularWideRotationSandwichTime = 0.0;
            var symmetricInvertTime      = 0.0;
            var symmetricWideInvertTime  = 0.0;
            var triangularWideInvertTime = 0.0;

            for (int i = 0; i < 1000; ++i)
            {
                var axis = Vector3.Normalize(new Vector3((float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1));
                Vector3Wide.Broadcast(axis, out var axisWide);
                var           rotation = Matrix3x3.CreateFromAxisAngle(axis, (float)random.NextDouble());
                Matrix3x3Wide rotationWide;
                Vector3Wide.Broadcast(rotation.X, out rotationWide.X);
                Vector3Wide.Broadcast(rotation.Y, out rotationWide.Y);
                Vector3Wide.Broadcast(rotation.Z, out rotationWide.Z);

                var m2x3Wide = new Matrix2x3Wide()
                {
                    X = axisWide, Y = new Vector3Wide {
                        X = -axisWide.Y, Y = axisWide.Z, Z = axisWide.X
                    }
                };

                var triangular = new Symmetric3x3
                {
                    XX = (float)random.NextDouble() * 2 + 1,
                    YX = (float)random.NextDouble() * 1 + 1,
                    YY = (float)random.NextDouble() * 2 + 1,
                    ZX = (float)random.NextDouble() * 1 + 1,
                    ZY = (float)random.NextDouble() * 1 + 1,
                    ZZ = (float)random.NextDouble() * 2 + 1,
                };
                Symmetric3x3Wide triangularWide;
                triangularWide.XX = new Vector <float>(triangular.XX);
                triangularWide.YX = new Vector <float>(triangular.YX);
                triangularWide.YY = new Vector <float>(triangular.YY);
                triangularWide.ZX = new Vector <float>(triangular.ZX);
                triangularWide.ZY = new Vector <float>(triangular.ZY);
                triangularWide.ZZ = new Vector <float>(triangular.ZZ);

                var symmetric = new Matrix3x3
                {
                    X = new Vector3(triangular.XX, triangular.YX, triangular.ZX),
                    Y = new Vector3(triangular.YX, triangular.YY, triangular.ZY),
                    Z = new Vector3(triangular.ZX, triangular.ZY, triangular.ZZ),
                };
                Matrix3x3Wide symmetricWide;
                Vector3Wide.Broadcast(symmetric.X, out symmetricWide.X);
                Vector3Wide.Broadcast(symmetric.Y, out symmetricWide.Y);
                Vector3Wide.Broadcast(symmetric.Z, out symmetricWide.Z);

                var symmetricVectorSandwich = new SymmetricVectorSandwich()
                {
                    v = axis, symmetric = symmetric
                };
                var symmetricWideVectorSandwich = new SymmetricWideVectorSandwich()
                {
                    v = axisWide, symmetric = symmetricWide
                };
                var triangularWideVectorSandwich = new TriangularWideVectorSandwich()
                {
                    v = axisWide, triangular = triangularWide
                };
                var symmetricWide2x3Sandwich = new SymmetricWide2x3Sandwich()
                {
                    m = m2x3Wide, symmetric = symmetricWide
                };
                var triangularWide2x3Sandwich = new TriangularWide2x3Sandwich()
                {
                    m = m2x3Wide, triangular = triangularWide
                };
                var symmetricSkewSandwich = new SymmetricSkewSandwich()
                {
                    v = axis, symmetric = symmetric
                };
                var symmetricWideSkewSandwich = new SymmetricWideSkewSandwich()
                {
                    v = axisWide, symmetric = symmetricWide
                };
                var triangularWideSkewSandwich = new TriangularWideSkewSandwich()
                {
                    v = axisWide, triangular = triangularWide
                };
                var symmetricSandwich = new SymmetricRotationSandwich()
                {
                    rotation = rotation, symmetric = symmetric
                };
                var symmetricWideSandwich = new SymmetricRotationSandwichWide()
                {
                    rotation = rotationWide, symmetric = symmetricWide
                };
                var triangularWideSandwich = new TriangularRotationSandwichWide()
                {
                    rotation = rotationWide, triangular = triangularWide
                };
                var symmetricInvert = new SymmetricInvert()
                {
                    symmetric = symmetric
                };
                var symmetricWideInvert = new SymmetricInvertWide()
                {
                    symmetric = symmetricWide
                };
                var triangularWideInvert = new TriangularInvertWide()
                {
                    triangular = triangularWide
                };


                const int innerIterations = 100000;
                symmetricVectorSandwichTime        += TimeTest(innerIterations, ref symmetricVectorSandwich);
                symmetricWideVectorSandwichTime    += TimeTest(innerIterations, ref symmetricWideVectorSandwich);
                triangularWideVectorSandwichTime   += TimeTest(innerIterations, ref triangularWideVectorSandwich);
                symmetricWide2x3SandwichTime       += TimeTest(innerIterations, ref symmetricWide2x3Sandwich);
                triangularWide2x3SandwichTime      += TimeTest(innerIterations, ref triangularWide2x3Sandwich);
                symmetricSkewSandwichTime          += TimeTest(innerIterations, ref symmetricSkewSandwich);
                symmetricWideSkewSandwichTime      += TimeTest(innerIterations, ref symmetricWideSkewSandwich);
                triangularWideSkewSandwichTime     += TimeTest(innerIterations, ref triangularWideSkewSandwich);
                symmetricRotationSandwichTime      += TimeTest(innerIterations, ref symmetricSandwich);
                symmetricWideRotationSandwichTime  += TimeTest(innerIterations, ref symmetricWideSandwich);
                triangularWideRotationSandwichTime += TimeTest(innerIterations, ref triangularWideSandwich);
                symmetricInvertTime      += TimeTest(innerIterations, ref symmetricInvert);
                symmetricWideInvertTime  += TimeTest(innerIterations, ref symmetricWideInvert);
                triangularWideInvertTime += TimeTest(innerIterations, ref triangularWideInvert);

                Compare(symmetricVectorSandwich.result, ref symmetricWideVectorSandwich.result);
                Compare(symmetricVectorSandwich.result, ref triangularWideVectorSandwich.result);
                Compare(ref symmetricWide2x3Sandwich.result, ref triangularWide2x3Sandwich.result);
                Compare(ref symmetricSkewSandwich.result, ref symmetricWideSkewSandwich.result);
                Compare(ref symmetricSkewSandwich.result, ref triangularWideSkewSandwich.result);
                Compare(ref symmetricSandwich.result, ref symmetricWideSandwich.result);
                Compare(ref symmetricSandwich.result, ref triangularWideSandwich.result);
                Compare(ref symmetricInvert.result, ref symmetricWideInvert.result);
                Compare(ref symmetricInvert.result, ref triangularWideInvert.result);
            }

            Console.WriteLine($"Symmetric vector sandwich:       {symmetricVectorSandwichTime}");
            Console.WriteLine($"Symmetric wide vector sandwich:  {symmetricWideVectorSandwichTime}");
            Console.WriteLine($"Triangular wide vector sandwich: {triangularWideVectorSandwichTime}");
            Console.WriteLine($"Symmetric wide 2x3 sandwich:  {symmetricWide2x3SandwichTime}");
            Console.WriteLine($"Triangular wide 2x3 sandwich: {triangularWide2x3SandwichTime}");
            Console.WriteLine($"Symmetric skew sandwich:       {symmetricSkewSandwichTime}");
            Console.WriteLine($"Symmetric wide skew sandwich:  {symmetricWideSkewSandwichTime}");
            Console.WriteLine($"Triangular wide skew sandwich: {triangularWideSkewSandwichTime}");
            Console.WriteLine($"Symmetric rotation sandwich:       {symmetricRotationSandwichTime}");
            Console.WriteLine($"Symmetric wide rotation sandwich:  {symmetricWideRotationSandwichTime}");
            Console.WriteLine($"Triangular wide rotation sandwich: {triangularWideRotationSandwichTime}");
            Console.WriteLine($"Symmetric invert:       {symmetricInvertTime}");
            Console.WriteLine($"Symmetric wide invert:  {symmetricWideInvertTime}");
            Console.WriteLine($"Triangular wide invert: {triangularWideInvertTime}");
        }