jueves, 19 de diciembre de 2013

Configuración de pantallas múltiples en Unity3D

Configuración paso a paso
A continuación se describe el proceso de configuración de los múltiples monitores en una aplicación de Unity paso a paso.

  1. Creación de un escenario y un jugador conteniendo 4 camaras con Unity3D.
Primero se crea una escena con un plano y un objeto. Ambos están prefabricados y simplemente se colocan en la escena. En el caso del auto, fue descargado del Asset Store de Unity, de donde se pueden descargar objetos prefabricados de numerosas librerías gratuitas.
Imagen 3: Objeto Player en el plano visto desde arriba.


  1. Creación de objeto vacío Cameras
Se crea un objeto Cameras y se le asignan 4 objetos Camera: cámara izquierda, cámara derecha, cámara principal y cámara trasera en distintos ángulos.
Imagen 4: Objeto Cameras con 4 objetos Camera asignados.


  1. Creación de script que asigna el objeto Cameras al Player.
Unity trabaja con C# o JavaScript, para la aplicación se eligió C#. El Script se le asigna al objeto Player.
Se crea un script CameraScript.cs y se crean las variables a utilizar para el manejo de las cámaras.

public class CameraScript : MonoBehaviour
{
public Camera camaraIzquierda;
public Camera camaraFrontal;
public Camera camaraDerecha;
public Camera camaraTrasera;
private GameObject myCamera;
private Transform cameraHeadTransform;

La variable myCamera es del tipo GameObject, la clase base de todas las entidades en Unity. Se utiliza para manejar al objeto Cameras. La variable cameraHeadTransform es del tipo  Transform, esta clase maneja los atributos de posición, rotación y escala de un objeto o GameObject. Se utiliza para guardar la posición de la Camera de Player.

Luego, se asigna el objeto Cameras a la variable myCamera y la Camera de Player (cuyo nombre es “CameraHead”) a la variable cameraHeadTransform en el método de inicialización Start().
void Start ()
{
myCamera = GameObject.Find ("Cameras");
cameraHeadTransform = transform.FindChild ("CamaraHead");
}

Este método es llamado una sola vez antes de que el método Update() sea llamado por primera vez. El método Update() en cambio, se llama una vez por cada frame cuando la aplicación está corriendo.
A continuación le asignamos al objeto Cameras la posición de la cámara del Player y a cada una de las cámaras contenidas en Cameras la rotación de la cámara del mismo. El resultado es que  la posición de las cámaras se actualizará y seguirá al Player cada vez que se actualice un frame.

// Update is called once per frame
void Update ()
{
myCamera.transform.position = cameraHeadTransform.position;
foreach (Transform child in myCamera.transform) {
child.transform.rotation = cameraHeadTransform.rotation;
}

  1. Cálculo de los campos de visión de cada cámara.
Dado que se representará la visión del usuario dividida en cuatro partes (visión frontal, trasera, a izquierda y derecha) debe ajustarse el campo de visión horizontal de las cámaras ya que normalmente están configuradas suponiendo que el usuario utiliza una sola a la vez. Esto se traduce en disminuir la variable del campo de visión de cada objeto Camera, quitándoles parte de la vista periférica para que no se superpongan entre ellas.

El cálculo para determinar el valor de ajuste del campo de visión horizontal (horizontal FOV) se puede obtener si se conoce el campo de visión vertical. Se calcula utilizando la siguiente fórmula:


Donde H es el campo de visión horizontal, V es el campo de visión vertical, w es el ancho de la pantalla y h la altura de la misma. El equivalente en el script es:

float fov=2f * Mathf.Rad2Deg * Mathf.Atan(Mathf.Tan(.5f * Mathf.Deg2Rad * 90) / camaraDerecha.aspect);

El atributo aspect de una Camera es el equivalente a calcular los datos de la pantalla en la fórmula. Luego simplemente se asigna el valor del campo de visión horizontal resultante a cada cámara.
camaraDerecha.fieldOfView=fov;
camaraIzquierda.fieldOfView=fov;
camaraFrontal.fieldOfView=fov;
camaraTrasera.fieldOfView=fov;

  1. Asignar ángulos de visión diferentes a cada cámara.
Por más que cada cámara ya tiene un ángulo diferente, se debe asegurar que estén bien alineadas. Ya que son 4 cámaras, la variación en la rotación de cada cámara será cada 90º.

Figura 1: Esquema del campo de visión de una cámara para una aplicación con 4 cámaras.

Se asignan entonces los ángulos a cada cámara.

camaraFrontal.transform.eulerAngles = new Vector3 (0
, camaraFrontal.transform.eulerAngles.y + 315, 0);
camaraIzquierda.transform.eulerAngles = new Vector3 (0
, camaraIzquierda.transform.eulerAngles.y + 225,0);
camaraDerecha.transform.eulerAngles = new Vector3 (0
, camaraDerecha.transform.eulerAngles.y + 45, 0);
camaraTrasera.transform.eulerAngles = new Vector3 (0
, camaraTrasera.transform.eulerAngles.y + 135, 0);

El resultado de los últimos dos pasos se puede observar en la siguientes imagen.

Imagen 5: Objeto Cameras con las 4 cámaras configuradas correctamente.


  1. División de pantalla en 4 subpantallas utilizando Normalized ViewPort Rectangles.
En este último paso se modifican los valores del ancho y de la posición en X de cada cámara en la pantalla.
Se modifica el ancho de cada cámara para ajustarlo a 1/4 del espacio de la pantalla principal, por lo que sus valores en W serán de 0.25. Finalmente se modifica la posición en X de cada cámara para que queden alineadas una al lado de la otra en la pantalla. Es decir, la cámara izquierda tendrá la posición 0, la principal 0.25, la derecha 0.5 y la trasera 0.75.

El resultado final de configuración de cada cámara se puede ver reflejado en las siguientes imágenes.

Imagen 6: Vista de la cámara principal y sus atributos.

Imagen 7: Vista de la cámara trasera y sus atributos.

Imagen 8: Vista de la cámara izquierda y sus atributos.

Imagen 9: Vista de la cámara derecha y sus atributos.

La imagen final de la aplicación corriendo muestra las cuatro cámaras en simultáneo.




De izquierda a derecha: cámara izquierda, cámara frontal, cámara derecha, cámara trasera



Fuentes:

No hay comentarios:

Publicar un comentario