martes, 23 de diciembre de 2014

Implementación de la cámara - segunda versión

Creo que este es el primer artículo sobre algo de desarrollo posterior a la presentación del juego en Julio. Trabajo fresco. Y es la segunda vuelta de tuerca sobre la cámara, y ya digo que no es la definitiva.



En el artículo sobre la implementación de la cámara ya expliqué que utilizaba splines para hacer una cámara sobre raíles, y en errores en la implementación de la cámara todo lo malo de esa primera versión, y que se resumen en este vídeo:



Una de las medidas es pasar a usar trozos de spline más cortos, con número fijo de nodos y separación constante entre nodos. Esto lo hago para intentar evitar que la cámara esté más lejos o cerca según el trozo de spline que nos toque. Por otras razones que vienen después, uso trozos de 5 nodos y separación de 10 unidades entre nodos.




Otra es la triangular por cada unión entre nodos y no por el trozo de spline completo. Es decir, en la versión anterior se calculaba la posición más cercana del spline de forma aproximada tomando la recta que unía primer y último trozo. Ahora mido la distancia del protagonista a cada nodo del spline y calculo la posición respecto a la recta que une esos nodos (con alguna comprobación extra). En teoría esto debería hacer que haya menos error entre la aproximación de la posición y el recorrido del spline, haciendo que la distancia al personaje sea más constante.



El siguiente añadido es hacer que los splines se superpongan, el final de uno con el principio del siguiente. De esta forma en las zonas de transición entre trozos de spline la posición será interpolada entre los dos splines. Es una de las razones por las que uso 5 nodos por spline, así cada trozo de spline tiene 4 espacios entre nodos. La parte 0-25% está compartida con el spline anterior, la parte 25%-75% es exclusiva del spline en curso y la parte 75%-100% se comparte con el spline siguiente. Además la posición es más cercana al primer spline cuando comienza el segundo y más cercana al segundo cuando el primero se va a terminar.



Empalme de splines

Por ejemplo en la posición 80% de un spline (y por lo tanto 5% del segundo), la posición será un 80% del primer spline y un 20% del segundo; si tomamos la posición 90% del primer spline (15% del segundo), entonces la posición final será de 60% el primer spline y 40% el segundo. Aquí cuando hablo de % de un spline me refiero a la variable paramétrica que recorre el spline (0-1) y cuando me refiero a porcentajes de uno u otro spline utilizados para la posición es literalmente a cuanto aporta la posición de cada spline a la posición final. Se ve mucho mejor en el dibujo, donde las líneas azul y roja son 2 trozos de spline y la línea negra que va por encima sería el recorrido final de la cámara. Podemos ver como en el trozo de transición la línea negra salta de forma suave de un spline al otro.



El primer error mostrado en el vídeo es que el control se tuerce al centrar la cámara al personaje pero ir sobre raíles. Y eso hace el manejo del personaje difícil y confuso. En la nueva versión la cámara va apuntando en la dirección de avance del spline y no al personaje. Eso hace que con el escenario actual el personaje pueda quedar fuera de plano, pero se reharán los escenarios para adecuarlos al sistema. En el vídeo siguiente dejo una demo de cómo funciona actualmente:






Todo así es muy bonito, una vez más el demonio está en los detalles. Lo primero problemas en los extremos del escenario, se arreglan, pero eso añade código extra para casos marginales. Orientar la cámara en la dirección del spline no es tan sencillo. Intento usar la posición anterior del jugador, y funciona relativamente bien cuando avanza hacia delante, pero si va hacia atrás en el escenario no funciona bien. Podría arreglarlo enfrentando el vector forward del personaje y de la cámara y teniendo en cuenta su producto escalar. Pero no era el único problema, había momentos que se volvía loco y no sabía hacia donde enfocar. Así que al final funciona tomando un segundo punto en una posición más avanzada. Es decir si la tiangulación me da que la posición del personaje es 0.45, pues pongo la cámara en 0.25 para que se vea el personaje y calculo su posición en coordenadas del mundo y también calculo las coordenadas en posición del mundo del 0.35, así la cámara estaría en el 0.25 pero mirando hacia el 0.35. Esto funciona bien, y con un par de comprobaciones para casos extremos funciona.



Otro problema y muy gordo es encontrarte con un bucle infinito, ouch!. Y esto pasa en algún punto raro de los empalmes de splines. Imaginemos un punto justo al extemo (el extremo será el 100% del primer spline y el 25% del segundo), pruebo para el primer spline y me da 100.04%, entonces como ya me paso del primer spline intento coger valor del segundo spline solo, y me da por el error de triangulación 24.95%, por debajo de 25% así que todavía tengo que volver al primer spline y hacer la mezcla de los 2, pero en el primero me vuelve a dar 100.04% etc etc etc. Fijándome un poco de donde vengo, puedo romper ese infinito. Si vengo de pasar de un spline al anterior, uso el primero y no vuelvo al segundo, aunque me pase del 100% ya que la función del spline extrapola bastante bien.



Hay un problema que no he encontrado la causa y es que a veces me da un error de un índice fuera de rango dentro del código de evaluación de splines (que es de la librería iTween), a lo mejor es alguna chorrada, como que he inicializado mal los índices de los nodos de un spline, pero no me he preocupado mucho todavía, ya que tengo motivos para hacer cambios más profundos en el sistema.



El mayor problema como se puede ver en el vídeo siguiente es el rendimiento. El juego con el sistema de cámara anterior funcionaba a unos 60 fps, solo cambiando la cámara (tengo ambos códigos funcionando y puedo comparar en las mismas condiciones), con el nuevo sistema funciona entre 20 y 30 fps. Cuando se acerca a 20 fps se hace desagradable jugar, se nota que no va fluido.



El tener que hacer la comprobación de distancias para ver entre que dos nodos triangular y no hacer directamente la de todo el spline es más caro. Y en el peor de los casos, en el caso de transición hay que hacerlo 2 veces, uno para cada spline, y a la hora de evaluar la posición del mundo que tiene ese valor de spline se puede hacer hasta 4 veces, 2 para la posición de cámara si está entre 2 splines y 2 para la dirección si pilla también entre splines.





Tengo que investigar si por la forma de hacer el código, o porque no se sacar rendimiento a c# o algo así tengo esa pérdida de rendimiento. Pero por ahora voy a intentar cosas como volver a la evaluación única por spline, pero con las normas de nodos adquiridas en a nueva versión, y a hacer una caché de posiciones del spline para no tener que hacer varias evaluaciones por frame. También a ver un poco el cambio entre splines, que a veces queda un poco brusco con el sistema actual, aunque no se vuelve loco como en el anterior.

No hay comentarios :

Publicar un comentario