Esempio n. 1
0
 /// <summary>
 /// Establece que la primitiva actual ha sido contactada por otra primitiva de colisión
 /// </summary>
 /// <param name="primitive">Primitiva de colisión que ha contactado con la actual</param>
 public virtual void PrimitiveContacted(CollisionPrimitive primitive)
 {
     if (OnPrimitiveContacted != null)
     {
         OnPrimitiveContacted(primitive);
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Aplica la fuerza del amortiguador al objeto especificado
        /// </summary>
        /// <param name="obj">Objeto</param>
        /// <param name="duration">Duración</param>
        public override void UpdateForce(ref IPhysicObject obj, float duration)
        {
            // Obtener el cuerpo del objeto
            CollisionPrimitive primitive = obj.Primitive;

            if (primitive != null)
            {
                // Calculate the two ends in world space
                Vector3 lws = primitive.GetPointInWorldSpace(m_ConnectionPoint);
                Vector3 ows = m_Other.GetPointInWorldSpace(m_OtherConnectionPoint);

                // Calculate the vector of the spring
                Vector3 force = lws - ows;

                // Calculate the magnitude of the force
                float magnitude = force.Length();
                magnitude  = Math.Abs(magnitude - m_RestLength);
                magnitude *= m_SpringConstant;

                // Calculate the final force and apply it
                force.Normalize();
                force *= -magnitude;
                primitive.AddForceAtPoint(force, lws);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Genera los contactos requeridos para restaurar la unión si ha sido violada
        /// </summary>
        /// <param name="contactData">Información de contactos</param>
        /// <param name="limit">Límite de contactos a generar</param>
        /// <returns>Devuelve el número de contactos generados</returns>
        /// <remarks>Tan solo generará un contacto o ninguno</remarks>
        public override int AddContact(ref CollisionData contactData, int limit)
        {
            if (contactData.HasFreeContacts())
            {
                CollisionPrimitive objectOne = null;
                if (this.m_BodyOne != null)
                {
                    objectOne = this.m_BodyOne.Primitive;
                }

                CollisionPrimitive objectTwo = null;
                if (this.m_BodyTwo != null)
                {
                    objectTwo = this.m_BodyTwo.Primitive;
                }

                Vector3 positionOne      = this.m_RelativePointOne;
                Vector3 positionOneWorld = this.m_RelativePointOne;
                if (objectOne != null)
                {
                    positionOne      = objectOne.Position;
                    positionOneWorld = objectOne.GetPointInWorldSpace(this.m_RelativePointOne);
                }

                Vector3 positionTwo      = this.m_RelativePointTwo;
                Vector3 positionTwoWorld = this.m_RelativePointTwo;
                if (objectTwo != null)
                {
                    positionTwo      = objectTwo.Position;
                    positionTwoWorld = objectTwo.GetPointInWorldSpace(this.m_RelativePointTwo);
                }

                float currentLen = Vector3.Distance(positionOneWorld, positionTwoWorld);

                if (Math.Abs(currentLen) > this.m_Length)
                {
                    Contact contact = contactData.CurrentContact;

                    contact.Bodies[0]     = objectOne;
                    contact.Bodies[1]     = objectTwo;
                    contact.ContactNormal = Vector3.Normalize(positionTwoWorld - positionOneWorld);
                    contact.ContactPoint  = (positionOneWorld + positionTwoWorld) * 0.5f;
                    contact.Penetration   = currentLen - this.m_Length;
                    contact.Friction      = 1.0f;
                    contact.Restitution   = 0;

                    contactData.AddContact();

                    return(1);
                }
            }

            return(0);
        }
        /// <summary>
        /// Detecta la colisión entre dos objetos
        /// </summary>
        /// <param name="obj1">Objeto primero</param>
        /// <param name="obj2">Objeto segundo</param>
        /// <param name="data">Información de colisión</param>
        /// <returns>Devuelve verdadero si ha habido colisión</returns>
        public static bool BetweenObjects(ref CollisionPrimitive primitive1, ref CollisionPrimitive primitive2, ref CollisionData data)
        {
            if (primitive1 != null && primitive2 != null)
            {
                if (primitive1 is CollisionBox)
                {
                    if (primitive2 is CollisionBox)
                    {
                        return(BoxAndBox((CollisionBox)primitive1, (CollisionBox)primitive2, ref data));
                    }
                    else if (primitive2 is CollisionSphere)
                    {
                        return(BoxAndSphere((CollisionBox)primitive1, (CollisionSphere)primitive2, ref data));
                    }
                    else if (primitive2 is CollisionPlane)
                    {
                        return(BoxAndHalfSpace((CollisionBox)primitive1, (CollisionPlane)primitive2, ref data));
                    }
                    else if (primitive2 is CollisionTriangleSoup)
                    {
                        return(BoxAndTriangleSoup((CollisionBox)primitive1, (CollisionTriangleSoup)primitive2, ref data));
                    }
                }
                else if (primitive1 is CollisionSphere)
                {
                    if (primitive2 is CollisionBox)
                    {
                        return(BoxAndSphere((CollisionBox)primitive2, (CollisionSphere)primitive1, ref data));
                    }
                    else if (primitive2 is CollisionSphere)
                    {
                        return(SphereAndSphere((CollisionSphere)primitive1, (CollisionSphere)primitive2, ref data));
                    }
                    else if (primitive2 is CollisionPlane)
                    {
                        return(SphereAndHalfSpace((CollisionSphere)primitive1, (CollisionPlane)primitive2, ref data));
                    }
                    else if (primitive2 is CollisionTriangleSoup)
                    {
                        return(SphereAndTriangleSoup((CollisionSphere)primitive1, (CollisionTriangleSoup)primitive2, ref data));
                    }
                }

                throw new Exception("Tipo de colisión no controlada");
            }

            return(false);
        }
Esempio n. 5
0
        /// <summary>
        /// Añade los contactos necesarios para mantener unidos mediante la barra a los cuerpos
        /// </summary>
        /// <param name="contactData">Datos de colisión</param>
        /// <param name="limit">Límite de contactos a añadir</param>
        /// <returns>Devuelve el número de contacos añadidos</returns>
        /// <remarks>Sólo añade un contacto o ninguno</remarks>
        public override int AddContact(ref CollisionData contactData, int limit)
        {
            if (contactData.HasFreeContacts())
            {
                CollisionPrimitive objectOne = null;
                if (this.m_BodyOne != null)
                {
                    objectOne = this.m_BodyOne.Primitive;
                }

                CollisionPrimitive objectTwo = null;
                if (this.m_BodyTwo != null)
                {
                    objectTwo = this.m_BodyTwo.Primitive;
                }

                // Encontrar la longitud actual
                Vector3 positionOne      = this.m_RelativePointOne;
                Vector3 positionOneWorld = this.m_RelativePointOne;
                if (objectOne != null)
                {
                    positionOne      = objectOne.Position;
                    positionOneWorld = objectOne.GetPointInWorldSpace(this.m_RelativePointOne);
                }

                Vector3 positionTwo      = this.m_RelativePointTwo;
                Vector3 positionTwoWorld = this.m_RelativePointTwo;
                if (objectTwo != null)
                {
                    positionTwo      = objectTwo.Position;
                    positionTwoWorld = objectTwo.GetPointInWorldSpace(this.m_RelativePointTwo);
                }

                float currentLen = Vector3.Distance(positionOneWorld, positionTwoWorld);

                // Comprobar si estamos en extensión correcta
                if (currentLen != m_Length)
                {
                    // Rellenar el contacto
                    Contact contact = contactData.CurrentContact;

                    contact.Bodies[0]    = objectOne;
                    contact.Bodies[1]    = objectTwo;
                    contact.ContactPoint = (positionOneWorld + positionTwoWorld) * 0.5f;

                    // Calcular la normal
                    Vector3 normal = Vector3.Normalize(positionTwo - positionOne);

                    // La normal de contacto depende de si hay que extender o contraer para conservar la longitud
                    if (currentLen > m_Length)
                    {
                        contact.ContactNormal = normal;
                        contact.Penetration   = currentLen - m_Length;
                    }
                    else
                    {
                        contact.ContactNormal = Vector3.Negate(normal);
                        contact.Penetration   = this.m_Length - currentLen;
                    }

                    // Siempre restitución 0
                    contact.Restitution = 0f;

                    contactData.AddContact();

                    return(1);
                }
            }

            return(0);
        }
Esempio n. 6
0
        /// <summary>
        /// Calcula la fuerza y la aplica al objeto especificado
        /// </summary>
        /// <param name="obj">Objeto</param>
        /// <param name="duration">Duración</param>
        public override void UpdateForce(ref IPhysicObject obj, float duration)
        {
            // Obtener el cuerpo del objeto
            CollisionPrimitive primitive = obj.Primitive;

            if (primitive != null)
            {
                // Detectar la fase de la explosión en la que estamos
                if (this.m_TimePassed <= this.ImplosionDuration)
                {
                    // Fase de implosión

                    float distance = Vector3.Distance(primitive.Position, this.DetonationCenter);
                    if (distance > this.ImplosionMinRadius && distance <= this.ImplosionMaxRadius)
                    {
                        // El cuerpo está en el área de implosión. Aplicar las fuerzas
                        float max            = this.ImplosionMaxRadius - this.ImplosionMinRadius;
                        float curr           = distance - this.ImplosionMinRadius;
                        float forceMagnitude = curr / max;

                        Vector3 force = Vector3.Normalize(this.DetonationCenter - primitive.Position) * this.ImplosionForce * forceMagnitude;

                        primitive.AddForce(force);
                    }
                }
                else if (this.m_TimePassed <= (this.ImplosionDuration + this.ConcussionDuration))
                {
                    // Honda expansiva

                    // Intervalo actual de máxima acción de la honda
                    float min = this.ShockwaveSpeed * this.m_TimePassed;
                    float max = this.ShockwaveSpeed * (this.m_TimePassed + duration);

                    // Distancia al centro del objeto
                    float distance = Vector3.Distance(primitive.Position, this.DetonationCenter);

                    float totalDuration = this.ConcussionDuration + this.ImplosionDuration;
                    float maxDuration   = this.ConcussionDuration;
                    float maxDistance   = (this.ShockwaveSpeed * maxDuration) + this.ShockwaveThickness;

                    float forceMagnitude = 0f;
                    if (distance >= min && distance <= max)
                    {
                        // En plena honda expansiva. Se aplican las fuerzas atenuadas sólo por la duración
                        float relativeTime = 0f;
                        if (m_TimePassed < totalDuration)
                        {
                            relativeTime = 1f - (this.m_TimePassed / totalDuration);
                        }

                        forceMagnitude = this.PeakConcussionForce * relativeTime;
                    }
                    else if (distance < min)
                    {
                        // El objeto ha sido sobrepasado por la honda expansiva. Fuerza mínimamente atenuada
                        float relativeTime = 0f;
                        if (this.m_TimePassed < totalDuration)
                        {
                            relativeTime = 1f - (this.m_TimePassed / totalDuration);
                        }

                        forceMagnitude = this.PeakConcussionForce * relativeTime;
                    }
                    else if (distance > max && distance <= maxDistance)
                    {
                        // El objeto no ha sido alcanzado por la honda expansiva. Fuerza atenuada por el tiempo y la distancia
                        float relativeDistance = 0f;
                        if (distance < maxDistance)
                        {
                            relativeDistance = 1f - (distance / maxDistance);
                        }

                        float relativeTime = 0f;
                        if (this.m_TimePassed < totalDuration)
                        {
                            relativeTime = 1f - (this.m_TimePassed / totalDuration);
                        }

                        forceMagnitude = this.PeakConcussionForce * relativeDistance * relativeTime;
                    }

                    if (forceMagnitude > 0f)
                    {
                        Vector3 force = Vector3.Normalize(primitive.Position - this.DetonationCenter) * forceMagnitude;

                        primitive.AddForce(force);
                    }
                }
                else
                {
                    // Fin de la explosión
                    this.m_ExplosionActive = false;
                }
            }

            this.m_TimePassed += duration;
        }