Exemple #1
0
        public ICollection <Vector2> ComputePositionsOnPlane(IEnumerable <Vector3D> positions)
        {
            if (positions == null)
            {
                throw new ArgumentNullException("positions");
            }

            IList <Vector2> positionsOnPlane = new List <Vector2>(CollectionAlgorithms.EnumerableCount(positions));

            foreach (Vector3 position in positions)
            {
                Vector3 intersectionPoint;

                if (IntersectionTests.TryRayPlane(Vector3.Zero, position.Normalize(), _normal, _d, out intersectionPoint))
                {
                    Vector3D v = intersectionPoint - _origin;
                    positionsOnPlane.Add(new Vector2D(_xAxis.Dot(v), _yAxis.Dot(v)));
                }
                else
                {
                    // Ray does not intersect plane
                }
            }

            return(positionsOnPlane);
        }
 /// <summary>
 /// Realiza los tests de colisión
 /// </summary>
 /// <param name="obj1">Objeto 1</param>
 /// <param name="obj2">Objeto 2</param>
 public static void TestCollision(IPhysicObject obj1, IPhysicObject obj2)
 {
     if ((obj1 != null) && (obj2 != null))
     {
         //if (obj1.BSph.Intersects(obj2.BSph))
         {
             if (IntersectionTests.BoxAndBox(obj1.TransformedOBB, obj2.TransformedOBB))
             {
                 obj1.Reaction(obj2);
                 obj2.Reaction(obj1);
             }
         }
     }
 }
        public void SphereAndTriTest()
        {
            bool intersect = false;

            CollisionSphere sphere = new CollisionSphere(1f, 1f);

            Triangle triangleHAU = new Triangle(new Vector3(0, 1, 10), new Vector3(-10, 1, -10), new Vector3(10, 1, -10));
            Triangle triangleHBU = new Triangle(new Vector3(0, 0, 10), new Vector3(-10, 0, -10), new Vector3(10, 0, -10));
            Triangle triangleHCU = new Triangle(new Vector3(0, -1, 10), new Vector3(-10, -1, -10), new Vector3(10, -1, -10));

            Triangle triangleHAD = new Triangle(new Vector3(0, 1, 10), new Vector3(10, 1, -10), new Vector3(-10, 1, -10));
            Triangle triangleHBD = new Triangle(new Vector3(0, 0, 10), new Vector3(10, 0, -10), new Vector3(-10, 0, -10));
            Triangle triangleHCD = new Triangle(new Vector3(0, -1, 10), new Vector3(10, -1, -10), new Vector3(-10, -1, -10));


            sphere.SetPosition(new Vector3(0, 2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAU);
            Assert.AreEqual(true, intersect, "Error en Triángulo sobre 0 normal UP, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, 0, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAU);
            Assert.AreEqual(true, intersect, "Error en Triángulo sobre 0 normal UP, contacto perfecto bajo plano");
            sphere.SetPosition(new Vector3(0, 1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAU);
            Assert.AreEqual(true, intersect, "Error en Triángulo sobre 0 normal UP, contacto en mitad de la esfera");
            sphere.SetPosition(new Vector3(0, 3, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAU);
            Assert.AreEqual(false, intersect, "Error en Triángulo sobre 0 normal UP, sin contacto sobre el plano");
            sphere.SetPosition(new Vector3(0, -1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAU);
            Assert.AreEqual(false, intersect, "Error en Triángulo sobre 0 normal UP, sin contacto bajo el plano");

            sphere.SetPosition(new Vector3(0, 2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAD);
            Assert.AreEqual(true, intersect, "Error en Triángulo sobre 0 normal DOWN, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, 0, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAD);
            Assert.AreEqual(true, intersect, "Error en Triángulo sobre 0 normal DOWN, contacto perfecto bajo plano");
            sphere.SetPosition(new Vector3(0, 1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAD);
            Assert.AreEqual(true, intersect, "Error en Triángulo sobre 0 normal DOWN, contacto en mitad de la esfera");
            sphere.SetPosition(new Vector3(0, 3, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAD);
            Assert.AreEqual(false, intersect, "Error en Triángulo sobre 0 normal DOWN, sin contacto sobre el plano");
            sphere.SetPosition(new Vector3(0, -1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHAD);
            Assert.AreEqual(false, intersect, "Error en Triángulo sobre 0 normal DOWN, sin contacto bajo el plano");



            sphere.SetPosition(new Vector3(0, 1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(true, intersect, "Error en Triángulo en 0 normal UP, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, -1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(true, intersect, "Error en Triángulo en 0 normal UP, contacto perfecto bajo plano");
            sphere.SetPosition(new Vector3(0, 0, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(true, intersect, "Error en Triángulo en 0 normal UP, contacto en mitad de la esfera");
            sphere.SetPosition(new Vector3(0, 2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en 0 normal UP, sin contacto sobre el plano");
            sphere.SetPosition(new Vector3(0, -2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en 0 normal UP, sin contacto bajo el plano");

            sphere.SetPosition(new Vector3(0, 1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBD);
            Assert.AreEqual(true, intersect, "Error en Triángulo en 0 normal DOWN, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, -1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBD);
            Assert.AreEqual(true, intersect, "Error en Triángulo en 0 normal DOWN, contacto perfecto bajo plano");
            sphere.SetPosition(new Vector3(0, 0, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBD);
            Assert.AreEqual(true, intersect, "Error en Triángulo en 0 normal DOWN, contacto en mitad de la esfera");
            sphere.SetPosition(new Vector3(0, 2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBD);
            Assert.AreEqual(false, intersect, "Error en Triángulo en 0 normal DOWN, sin contacto sobre el plano");
            sphere.SetPosition(new Vector3(0, -2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBD);
            Assert.AreEqual(false, intersect, "Error en Triángulo en 0 normal DOWN, sin contacto bajo el plano");



            sphere.SetPosition(new Vector3(0, 0, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCU);
            Assert.AreEqual(true, intersect, "Error en Triángulo en -1 normal UP, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, -2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCU);
            Assert.AreEqual(true, intersect, "Error en Triángulo en -1 normal UP, contacto perfecto bajo plano");
            sphere.SetPosition(new Vector3(0, -1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCU);
            Assert.AreEqual(true, intersect, "Error en Triángulo en -1 normal UP, contacto en mitad de la esfera");
            sphere.SetPosition(new Vector3(0, 1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal UP, sin contacto sobre el plano");
            sphere.SetPosition(new Vector3(0, -3, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal UP, sin contacto bajo el plano");

            sphere.SetPosition(new Vector3(0, 0, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCD);
            Assert.AreEqual(true, intersect, "Error en Triángulo en -1 normal DOWN, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, -2, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCD);
            Assert.AreEqual(true, intersect, "Error en Triángulo en -1 normal DOWN, contacto perfecto bajo plano");
            sphere.SetPosition(new Vector3(0, -1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCD);
            Assert.AreEqual(true, intersect, "Error en Triángulo en -1 normal DOWN, contacto en mitad de la esfera");
            sphere.SetPosition(new Vector3(0, 1, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCD);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal DOWN, sin contacto sobre el plano");
            sphere.SetPosition(new Vector3(0, -3, 0));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHCD);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal DOWN, sin contacto bajo el plano");


            sphere.SetPosition(new Vector3(-9, 0, 9));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal DOWN, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(9, 0, 9));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal DOWN, contacto perfecto sobre plano");
            sphere.SetPosition(new Vector3(0, 0, -12));
            intersect = IntersectionTests.SphereAndTri(sphere, triangleHBU);
            Assert.AreEqual(false, intersect, "Error en Triángulo en -1 normal DOWN, contacto perfecto sobre plano");
        }
Exemple #4
0
    // Since these physics are independent from Unity's doing physics in Update
    // as opposed to FixedUpdate is not a problem.
    void Update()
    {
        Vector3[] vertices = terrainMesh.vertices;
        foreach (Metaball ball in metaballs)
        {
            // Check if ball is instantiated.
            if (!ball.instantiated)
            {
                // If ball is not instantiated, check if it should be.
                if (framesSinceInstantiation > waterSpawnInterval)
                {
                    // Ball should be instantiated, reset framesSinceInstantiation.
                    framesSinceInstantiation = 0;
                    ball.instantiated        = true;
                    numInstantiatedBalls++;
                }
                else
                {
                    // Ball should not be instantiated, skip all physics.
                    continue;
                }
            }
            // Check if ball is within bounds.
            if (ball.transform.position.y < terrainBounds.min.y)
            {
                // Set new spawn position and reset velocity if ball is out of bounds.
                ball.transform.position = GetRandomSpawnPoint();
                ball.velocity           = Vector3.Lerp(Vector3.zero, waterInitialMaxVelocity, UnityEngine.Random.Range(0.0f, 1.0f));
            }

            // Calculate the cumulative acceleration.
            Vector3 totalAcceleration = gravityAcceleration * Vector3.down;
            foreach (Metaball otherBall in metaballs)
            {
                if (ball == otherBall || !otherBall.instantiated)
                {
                    continue;
                }

                // Force is like a spring force between each metaball and each other metaball.
                // The spring force is to keep balls at a minimum distance from eachother.
                // The force weakens the further away the balls are from eachother beyond the
                // minimum distance.

                Vector3 ballToOther = ball.transform.position - otherBall.transform.position;
                Vector3 springForce = ballSpringStiffness * (-ballToOther + Vector3.Normalize(ballToOther) * minimumDistance);

                // Force equation gives F = m * a, and with m = 1 for simplicity, we have F = a.
                // Scale by 0.5 because this is only one of the two balls.
                // If ball is outside maximumDistance of the equilibrium point, apply no force.
                if (ballToOther.magnitude - minimumDistance < maximumDistance)
                {
                    totalAcceleration += 0.5f * springForce;
                }
            }

            // Update velocity according to acceleration.
            ball.velocity += totalAcceleration * Time.deltaTime;

            // Update position according to velocity.
            ball.lastPosition        = ball.transform.position;
            ball.transform.position += ball.velocity * Time.deltaTime;

            // Check for intersection.
            int[] triangles;
            if (IntersectionTests.GetTriangles(ball.transform.position, rootNode, out triangles))
            {
                // Iterate through all found triangles.
                for (int i = 0; i < triangles.Length; i += 3)
                {
                    // Get triangle vertices.
                    Vector3[] triangle = new Vector3[] {
                        vertices[triangles[i]],
                        vertices[triangles[i + 1]],
                        vertices[triangles[i + 2]]
                    };

                    // Test for intersection.
                    Vector3 rayDirection = ball.transform.position - ball.lastPosition;
                    float   distance     = rayDirection.magnitude;
                    rayDirection = Vector3.Normalize(rayDirection);
                    Vector3?intersectionPoint;
                    // If intersection, compute new position and velocity.
                    if (IntersectionTests.RayTriangleTest(ball.lastPosition, rayDirection, distance, triangle, out intersectionPoint))
                    {
                        Vector3 point  = (Vector3)intersectionPoint;
                        Vector3 normal = Vector3.Normalize(
                            Vector3.Cross(triangle[2] - triangle[0], triangle[1] - triangle[0]));
                        // Get reflection direction.
                        Vector3 newDirection = Vector3.Normalize(2 * Vector3.Dot(-rayDirection, normal) * normal + rayDirection);
                        // Set dampened velocity.
                        ball.velocity = (1.0f - groundDamping) * ball.velocity.magnitude * newDirection;
                        // Update last position to the intersection point.
                        ball.lastPosition = point + constantOffset * Vector3.up;
                        // The new ball position is the distance traveled from the intersection point
                        // the distance traveled beyond the triangle, but adjusted for the new
                        // velocity and along the reflection direction.
                        ball.transform.position = point + constantOffset * Vector3.up + ball.velocity * Time.deltaTime;

                        // Break out of loop checking triangles after intersection was found.
                        break;
                    }
                }
            }
        }
        framesSinceInstantiation++;
    }