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"); }
// 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++; }