Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: CoLSoN2 en 12 de Diciembre de 2004, 01:20:24 AM

Título: Colisión 2d: Rotated Rectangle - Rotated Rectangle
Publicado por: CoLSoN2 en 12 de Diciembre de 2004, 01:20:24 AM
 Teniendo el código de si dos rectángulos colisionan (alineados con los ejes X e Y), ¿sabeis cómo puedo saber si dos rectángulos con una cierta rotación colisionan o no?  (algo como una oriented bounding box en 2D, supongo)
Título: Colisión 2d: Rotated Rectangle - Rotated Rectangle
Publicado por: martiño en 12 de Diciembre de 2004, 01:56:43 AM
 Supongamos que tenemos 2 rectangulos R y S. Con 4 vertices (ya rotados) cada uno: R0, R1, R2, R3, S0, S1, S2 y S3.

Haciendo el producto escalar: (R0-S0) * (S1-S0) y mirando el signo puede saber en que lado de la arista (S0, S1) esta R0.

Haciendo asi para todas las aristas puedes saber si R0 esta dentro de S o no.

Haciendo lo mismo para todos los vertices de R y S puedes saber si colisionan o no los rectangulos.
Título: Colisión 2d: Rotated Rectangle - Rotated Rectangle
Publicado por: CoLSoN2 en 12 de Diciembre de 2004, 12:48:57 PM
Cita de: "martiño"...
Gracias por la respuesta, y más o menos es lo mismo que un código que he encontrado y que testearé en cuanto pueda. Por si a alguien le interesa:



Citarbool Wml::TestIntersection (const Box2& rkBox0,
    const Box2& rkBox1)
{
    // convenience variables
    const Vector2* akA = rkBox0.Axes();
    const Vector2* akB = rkBox1.Axes();
    const Real* afEA = rkBox0.Extents();
    const Real* afEB = rkBox1.Extents();

    // compute difference of box centers, D = C1-C0
    Vector2 kD = rkBox1.Center() - rkBox0.Center();

    Real aafAbsAdB[2][2], fAbsAdD, fRSum;
   
    // axis C0+t*A0
    aafAbsAdB[0][0] = Math::FAbs(akA[0].Dot(akB[0]));
    aafAbsAdB[0][1] = Math::FAbs(akA[0].Dot(akB[1]));
    fAbsAdD = Math::FAbs(akA[0].Dot(kD));
    fRSum = afEA[0] + afEB[0]*aafAbsAdB[0][0] + afEB[1]*aafAbsAdB[0][1];
    if ( fAbsAdD > fRSum )
        return false;

    // axis C0+t*A1
    aafAbsAdB[1][0] = Math::FAbs(akA[1].Dot(akB[0]));
    aafAbsAdB[1][1] = Math::FAbs(akA[1].Dot(akB[1]));
    fAbsAdD = Math::FAbs(akA[1].Dot(kD));
    fRSum = afEA[1] + afEB[0]*aafAbsAdB[1][0] + afEB[1]*aafAbsAdB[1][1];
    if ( fAbsAdD > fRSum )
        return false;

    // axis C0+t*B0
    fAbsAdD = Math::FAbs(akB[0].Dot(kD));
    fRSum = afEB[0] + afEA[0]*aafAbsAdB[0][0] + afEA[1]*aafAbsAdB[1][0];
    if ( fAbsAdD > fRSum )
        return false;

    // axis C0+t*B1
    fAbsAdD = Math::FAbs(akB[1].Dot(kD));
    fRSum = afEB[1] + afEA[0]*aafAbsAdB[0][1] + afEA[1]*aafAbsAdB[1][1];
    if ( fAbsAdD > fRSum )
        return false;

    return true;
}
Título: Colisión 2d: Rotated Rectangle - Rotated Rectangle
Publicado por: Loover en 16 de Diciembre de 2004, 12:03:51 PM
 Ya se habló hace tiempo de algo parecido:

http://www.stratos-ad.com/forums/index.php...ulos+orientados

Y aquí están 4 métodos de colisión que tengo implementados: por envolvente rectangular, por círculo, por arista y por el teorema visto en el link al post. Están documentados, forman parte de la libreria 2d que estoy haciendo. Los métodos matriciales son de D3D pero puede portarse facilmente usando tu propia clase de matrices, lo mismo te son útiles:

http://galeon.com/loover/colisiones.cpp

Un saludo!