Una de las cosas más difíciles de pensar, quizás, sea la curva de bezier, y más si te cuestan las matemáticas. Si bien las mismas me gustan mucho, tampoco son mi fuerte, así que si yo lo pude sacar, cualquiera que esté leyendo esto puede hacerlo.

Por empezar… Para qué carajos podemos usar una curva de bezier? Veamos un ejemplo concreto:

luxor_s1

Luxor.

Zuma deluxe Screen Shot NO.2

Zuma Deluxe

En este tipo de juegos, en los cuales necesitamos que un objeto o conjunto de objetos avance sobre un camino curvado o sinuoso, pueden aplicarse estas “copadas” curvas de bezier. También podríamos usar un array de puntos, e ir de un punto a otro, el problema es que para tomar una curva lo suficientemente “curvada” necesitamos muchos puntos. Ni hablar de que ir corriéndolos de a uno es un golpe en la entre-pierna… Varias veces…

 

Analizando un Bezier.

Esto es un bezier simple, de 3 puntos, y nos sirve para hacer un movimiento curvo (entre otras cosas), cuando la curva no es sinuosa (básicamente que no tiene forma de S). Posee 3 puntos (por eso el nombre :P), en donde dos de esos puntos son INICIAL y FINAL y el del medio es una TANGENTE. Imaginen a la tangente como si agarraran una recta y la estiraran desde el medio como si fuera una bandita elástica. Esta parte es importante ya que va a definir la curva del mismo.

Un valor importante que se ve ahí, pero existe, es el valor “t“. El valor t es importante porque defíne en qué parte del bezier va a estar el objeto. Básicamente nos va a ayudar a obtener un punto dentro de nuestra curva. Se cumple que t ∈ [0, 1] (o sea que t está entre 0 y 1), donde [0 = P0]  y  [1 = P2]. En otras palabras: Si al poner el valor t en la ecuación (que veremos en breve, paciencia), resulta que t es igual a 0, la ecuación nos devuelve el P0; si t es 1, la ecuación nos devuelve P2; y si t es otro valor intermedio, nos devuelve el punto equivalente porcentualmente hablando (o sea que t = 0.5 nos devuelve exactamente la mitad de la curva).

Para este tipo de casos podríamos usar dos formas (fácil y difícil):

 

1) (FÁCIL)La “fruteada” y simple, pero poco escalable.

 

Esta forma consiste en hacer una interpolación entre el punto P0 y P1, mientras hacemos otra entre P1 y P2 …………………….

Y…………. BRAIN EXPLODE!

MOMENTO! Que no es tan difícil como suena. Sigamos…

La mayoría de los motores de juegos tienen algo llamado “Lerp”. Por ejemplo, en Unity3D existe

Vector3.Lerp(A, B, t);

 que lo que hace es, dado un valor t entre 0 y 1, devuelve un punto teniendo en cuenta que:

  • Si t = 0, se devuelve A.

  • Si t = 1, se devuelve B.

  • En todos los demas casos, devuelve un valor entre A y B (como el valor t del Bezier… Guiño… Guiño…).

Entonces… En Unity3D, el cálculo “fácil” sería:

 

Vector3.Lerp( Vector3.Lerp(P0, P1, t), Vector3.Lerp(P1, P2, t), t );

 

El punto P1 representaría la altura de la tangente. Así que… Si ponen un objeto a moverse en un Update y le asignan estos valores, recorrería el bezier. Veamos un ejemplo:

 

public GameObject target;
public Transform P0;
public Transform P1;
public Transform P2;
public float t = 0f;
void Update()
{
    target.transform.position = Vector3.Lerp( Vector3.Lerp(P0, P1, t), Vector3.Lerp(P1, P2, t), t );
    t += Time.deltaTime;
}

 

 

Como puede verse, con muy pocas líneas se consigue, con este método, una curva de bezier simple. El problema es que si quisiéramos que tuviera más puntos, deberíamos agregar muchos más niveles de profundidad a ese código. Si tan sólo pusiéramos un punto más a ese bezier tendríamos que agregar otros Lerps, dentro de otros Lerps, dentro de otros Lerps… Dentro de pofjap wofjapwoFJpa owjfpo…. Me explotó la cabeza a mí…

 

2) (DIFÍCIL)La original y compleja, pero precisa.

 

Esta forma consiste en utilizar la fórmula real de bezier, que es básicamente un Trinomio Cuadrado Perfecto. Vayamos directo al grano… La fórmula es:

B(t) = (1 – t)2P0 + 2t(1 – t)P1 + t2P2    =>    t ∈ [0, 1]

(esta última parte significa que t está entre 0 y 1).

BrainExplodeCombo

Brain Explode Combo!

Sí… Parece bastante más complicada, pero es cuestión de tomarle un poco de cariño a las matemáticas (sólo un poco). A mi criterio, una de las tantas ventajas que tiene usar la fórmula original cuando estás aprendiendo, es que es adaptable a cualquier lenguaje. Además, aprendiendo la fórmula original, se puede modificar, readaptar, etc, como para cada caso en particular.


 

 

Bezier de 4 puntos

Bezier_3_big

Curva Cúbica de Bezier.

BezierAndFlatness

Movimiento de las tangentes del Bezier.

En mi opinión, siempre que vayan a hacer caminos sinusoidales conviene usar este tipo de bezier.  Se llaman Curva Cúbica de Bézier La estructura de la fórmula no difiere mucho de la anterior:

 

 

B(t) = (1-t)3 * P0 + 3 * (1-t)2 *  t * P1 + 3 * (1-t) * t2 * P2  +  t3 *  P3    =>    t ∈ [0, 1]

Por supuesto… También hay curvas de Bezier más grandes, con más puntos. Se puede o estirar la fórmula para obtener más puntos, o cuardar cada segmento en un índice de un array y verificar a qué segmento se quiere acceder.

Vamos a explicar un poco este cálculo…

La realidad es que ese cálculo sale de algo mucho más corto, y es:

(a + b)3

Vamos a explicar un poco cómo es que sale desde esa diminuta fórmula, descomponiéndola un poco. Y se puede descomponer, en principio, de esta manera.

(a + b) * (a + b) * (a + b)

Ahora aplicamos DISTRIBUTIVA con los primeros paréntesis:

(a * a + a * b + b * a + b * b) * (a + b)

Dicha fórmula, la podemos COMPRIMIR:

(a2 + 2ab + b2) * (a + b)

Ahora aplicamos DISTRIBUTIVA con el paréntesis que falta. Tener en cuenta que 33 = 32*3. Considerando eso… Quedaría así:

(a3 + a2b + 2a2b + 2ab2 + b2a + b3)

COMPRIMIMOS todo de nuevo. Tener en cuenta que si tengo UN a2b + 2a2b, esto suma un 3a2b. Mirenlo como si tuvieran 2 elefantes y suman 1 elefante. Esto quiere decir que a2b = 1a2b:

(a3 + 3a2b + 3ab2 + b3)

Bien… Ahora les voy a dar los valores de “a” y “b” y ustedes reemplacen en papel (o lo que sea). Luego abran el indicador de spoiler.

a = (1-t)
b = t

Abran esto SÓLO cuando lo hayan hecho!

(1-t)3 + 3(1-t)2*t + 3(1-t)*t2 + t3

Bien! Es la misma fórmula! Lo único que tienen que hacer es multiplicar, ahora, CADA TÉRMINO (separen en términos), por cada uno de LOS PUNTOS que tienen. El bezier este tiene 4 puntos, así que cada término se multiplicaría por uno de ellos. Haganlo para probarlo!

Cualquier duda o mentario, avisen!