es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Calcule la rotación en 3D de un plano dado 3 puntos y su posición relativa.

Estoy tratando de rotar un plano en 3D en Unity, dado tres puntos. Estos puntos no siempre son los mismos, pero siempre están en los puntos rojos en esta imagen.

Sé las posiciones absolutas de estos puntos, junto con su posición relativa al plano. Por ejemplo, podría saber que el punto (-5, 5) se encuentra en (10, -4, 13).

Sé que cuando los tres puntos están en línea (por ejemplo, (-5, 5), (0, 5) y (5, 5)), no es posible calcular la rotación completa, por lo que ya arrojo una excepción cuando este es el caso. Sin embargo, cuando los tres puntos no están en una sola línea, debería ser posible calcular la rotación completa.

Hasta ahora, he utilizado el siguiente código para rotar, pero esto pierde la rotación alrededor del eje y (el ejemplo utiliza el punto (-5, 5), (5, 5) y (-5, -5)).

Vector3 p1 = Point1.transform.position; // Posición absoluta del punto 1
Vector3 p1Relative = new Vector3(-5, 0, 5);
Vector3 p2 = Point2.transform.position; // Posición absoluta del punto 2
Vector3 p2Relative = new Vector3(5, 0, 5);
Vector3 p3 = Point3.transform.position; // Posición absoluta del punto 3
Vector3 p3Relative = new Vector3(-5, 0, -5);

Gizmos.DrawSphere(p1, .1f);
Gizmos.DrawSphere(p2, .1f);
Gizmos.DrawSphere(p3, .1f);

Vector3 normal = Vector3.Cross(p2 - p1, p3 - p1);
rotator.transform.up = normal;

¿Cómo podría expandir o cambiar este código para incluir la rotación alrededor del eje Y? Gracias de antemano.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para incluir la rotación alrededor del eje Y, puedes usar el método Quaternion.LookRotation() para calcular la rotación del plano basado en los tres puntos. Aquí te mostramos cómo modificar el código:

    Vector3 p1 = Point1.transform.position;// posición absoluta del punto 1
    Vector3 p1Relative = new Vector3(-5, 0, 5);
    Vector3 p2 = Point2.transform.position;// posición absoluta del punto 2
    Vector3 p2Relative = new Vector3(5, 0, 5);
    Vector3 p3 = Point3.transform.position;// posición absoluta del punto 3
    Vector3 p3Relative = new Vector3(-5, 0, -5);
    
    Gizmos.DrawSphere(p1, .1f);
    Gizmos.DrawSphere(p2, .1f);
    Gizmos.DrawSphere(p3, .1f);
    
    Vector3 normal = Vector3.Cross(p2 - p1, p3 - p1);
    rotator.transform.up = normal;
    
    if (!Vector3.Equals(normal.normalized, Vector3.up))
    {
        Vector3 forward = Vector3.Cross(normal, Vector3.up).normalized;
        Vector3 right = Vector3.Cross(forward, normal).normalized;
        rotator.transform.rotation = Quaternion.LookRotation(forward, normal) * Quaternion.Euler(0, 90, 0);
        // Ajustar la rotación basado en las posiciones relativas de los puntos
        Vector3 dir1 = Quaternion.AngleAxis(-90, Vector3.up) * (p1Relative.normalized);
        Vector3 dir2 = Quaternion.AngleAxis(-90, Vector3.up) * (p2Relative.normalized);
        Vector3 dir3 = Quaternion.AngleAxis(-90, Vector3.up) * (p3Relative.normalized);
        rotator.transform.rotation *= Quaternion.LookRotation(right * dir1.x + normal * p1Relative.y + forward * dir1.z, normal * p2Relative.y) * Quaternion.LookRotation(right * dir2.x + normal * p2Relative.y + forward * dir2.z, normal * p3Relative.y) * Quaternion.LookRotation(right * dir3.x + normal * p3Relative.y + forward * dir3.z, normal);
    }
    

    Aquí, primero se calcula el vector normal como antes y se utiliza para rotar el plano alrededor del eje Z. Pero si el vector normal no está apuntando hacia arriba (es decir, cuando los tres puntos no se encuentran en el mismo plano paralelo al plano del suelo), entonces se ajustan los vectores de dirección de las posiciones relativas para tener en cuenta la rotación alrededor del eje Y. Estos vectores de dirección ajustados dan la rotación alrededor del eje X y Y, que se combinan con la rotación alrededor del eje Z para dar la rotación final del plano.

Comments are closed.