Copy Link
Add to Bookmark
Report

SET 032 0x0C

  

-[ 0x0C ]--------------------------------------------------------------------
-[ HDM ]---------------------------------------------------------------------
-[ by FCA00000 ]-----------------------------------------------------SET-32--


En este artículo voy a contar los desvaríos de un amiguete mío llamado Antonio.
Yo soy simplemente el escritor de algunas partes de este artículo, y aunque le
ayudé un poco, todo el mérito es suyo. Le costó bastante esfuerzo hacer este
proyecto, y yo fuí espectador de ese trabajo.
Creo que se merece un poco de publicidad y sus 15 minutos de fama. Este es mi
homenaje a su labor.

Está contado como si hubiéramos hecho este proyecto juntos, pero no es cierto.
Me ha obligado él a escribirlo así.

He hubiera gustado incluir fotografías, pero el sistema está tan chapucero que
da un poco de vergüenza. Además el formato de SET no permite dibujos.

El chico ha hecho muchos programas de ordenador, y le gustan los gráficos en 3D.
Es por eso que hace tiempo se compro en eBay de segunda mano unas gafas que
contienen una pequeña pantalla en caja ojo.
Esto permite que la imagen sea distinta para cada ojo, lo que proporciona
imagenes estereoscópicas, con sensación de profundidad.
Tras probar unos cuantos juegos y ver que efectivamente se consigue una
impresión de inmersión en un mundo 3D, decidió que él también quería hacer algo
parecido.
Muchos de los programadores que hacen gráficos para ordenadores conocen los
algoritmos y trucos para convertir un escenario en 3D en algo que se pueda ver
la pantalla del ordenador. Yo simplemente los voy a describir.
Lo primero es tener el escenario -también conocido como "mundo"- organizado por
distancias. Los objetos más cercanos se dibujarán con todo detalle, y los más
lejanos se dibujan como simples bloques.

Esta distancia es relativa al punto de vista, es decir, dónde está situado el
observador. En el caso de imagenes estereoscópicas, hay 2 puntos de visión, uno
por cada ojo. Esto implica que hay que dibujar la imagen dos veces.
El tercer elemento es el plano de intersección. Para dibujar los objetos
primero se imagina una ventana, y se traza una línea desde el punto de visión
hasta el objeto más cercano. El punto donde se interceptan dicha línea y la
ventana, es el que se dibujará en pantalla.
En realidad sólo se calculan los vértices de los polígonos, y las superficies
de los objetos se dividen en triángulos, que son los elementos más simples que
se pueden dibujar. Existen múltiples métodos de triangulación, eligiendo un
punto interior a la superficie, y trazando líneas hasta los vértices.
Luego se rellena cada triángulo.

Estos cálculos se realizan con funciones trigonométricas, que frecuentemente se
realizan en un procesador dedicado, o bien la propia tarjeta gráfica es capaz
de hacerlo, incluyendo texturas y dibujado optimizado de triángulos.
Existe muchísima documentación al respecto, así que no comentaré más.

Las gafas estereoscópicas normalmente obtienen la señal de video desde la
tarjeta gráfica.
Podría pensarse que se conectan a la salida de monitor, pero esto obligaría a
que la señal digital generada por el procesador se conviertiera a analógica
para el monitor, y luego las gafas las deberían convertir a digital de nuevo.
Esto es una pérdida de tiempo que es mejor evitar.
Por eso lo mas normal es que se conecten a la salida digital de la tarjeta
gráfica, o, si no la hay, al llamado "bus de servicio" de la tarjeta, que es un
conector extra. En mi caso tiene 28 pins.

La resolución de las gafas (baratas) es muy inferior a VGA. Los modelos
i-Glasses y VFX1 tienen 180.000 pixels para caja ojo.
Pero la manera de medirlos tiene truco: cada pixel sólo puede representar un
color (rojo, verde, o azul), en una gama de 256 niveles. Por eso para dibujar
1 pixel a color real (16.000.000 de colores) hacen falta 3 pixels en las gafas.
Esto hace que en realidad solo haya 180.000/3 = 60.000 pixels a color total.
Esto da una resolución de 260x230, inferior incluso al antiguo estándar MCGA
(320x200)
Vamos a hacer un cálculo simple: 260 pixels permiten mostrar 30 líneas de texto
con un tipo de letra de 8 pixels de alto.
Esta resolución es sólo ligeramente superior a la de un ZX-Spectrum, y peor que
una PSP.

Para que la imagen de ambos ojos sea distinta, hay que dibujar en la pantalla 2
imágenes entrelazadas: una en las líneas impares que se verá en el ojo
izquierdo, y otra en las líneas pares que se verá en el ojo derecho.
Hay otro modo usado por otras gafas, y es alternar la imagen cada 1/60 de
segundo, pero eso es más complicado de programar.

Ahora es cuando explico el objetivo: intentamos que en las gafas se represente
el escritorio del ordenador, en un sistema como MS-Windows o Linux-KDE
Los objetos (iconos, ventanas, cursor, ...) se presentarán en distintos planos,
con aspecto 3D. Será posible mover los objetos y también el punto de visión,
para verlos desde otra istancia y desde otro ángulo.
Ya de antemano se entiende que con esta resolución tan ridícula va a ser
imposible conseguir mucho, pero la aventura es la aventura.
Imagínate el escritorio en tu pantalla de 15 pulgadas, por ejemplo a 1024x768.
Ahora quédate sólo con 1/4 de la pantalla, tanto a lo ancho como a lo alto. Eso
es lo que se puede ver con las gafas.
Haz la prueba: en una hoja de papel haz un hueco de 8x6 cm, y ponlo sobre la
pantalla, Ahora intenta usar tu ordenador viendo a través de este hueco.

A cambio tiene una cosa buena: mires donde mires, la pantalla siempre estará
delante de tus ojos.

Un sistema HMD-Head Mounted Display se compone de un visor, y algún mecanismo
de posicionamiento del usuario. Comunmente es un giróscopo o un medidor
magnético que se lleva sobre la cabeza.
Cuando giras la cabeza, el sistema sabe que pretendes mirar a otro sitio, y
puede mostrar una imagen diferente, dando la impresión de que estás inmerso en
un mundo completo, generado por el ordenador.
Si te mueves, el sistema sabe que te has desplazado y presenta la imagen tal
como se ve desde el nuevo punto de visión.
Estos sistemas pueden ser incluso más caros que las propias gafas. Sobre todo
porque no hay mucha gente que los compre. La publicidad de los comerciantes
muestran a ingenieros diseñando coches y edificios, médicos operando a
distancia, químicos alterando las moléculas, y militares desplegando sus tropas.
Debo decir que el único sistema comercial que he visto yo ha sido en una sala
de videojuegos y en una representación de arte "virtual".

Pero mi amigo pretende suplir la falta de resolución con la disponibilidad de
espacio. Sólo puede ver 260x230 en cada ojo, pero dispone de 4 paredes de 3 x 2
metros. Ahora lo explicaré en detalle.
Las gafas tienen un FOV-Field Of View de 45 grados. Esto quiere decir que a una
distancia de 2 metros representa una ventana de 1.5 x 1 metros.
Así, una pared de 3 metros de ancho es capaz de contener 2 pantallas de 1.5
metros, lo que equivale a 2*260 pixels.
En otras palabras: sentado en el centro de su habitación, el escritorio de 1024
pixels de ancho le cabe en 2 paredes contiguas, lo que implica girar la cabeza
90 grados en cada sentido:
Cada pixel parece que mide 6 milimetros.

<--256 pixels--><--256 pixels-->
<-----------512 pixels--------->
<--------------3 metros ------->
<-- 1 pantalla-><-- 1 pantalla->
^
|
|
|
|
2 metros
|
|
|
v


Como he dicho, las líneas pares de la pantalla se dibujan en un ojo, y las
impares en el otro. Por supuesto que esto hace que no se vea bien en la
pantalla del ordenador, pero en las gafas queda realmente con efecto 3D.
La primera prueba que hicimos fue muy graciosa: pintamos las líneas pares de
color amarillo, y las impares de azul. El resultado es que el usuario ve la
pantalla de color verde, como cabía esperar.
Lo siguiente fue dibujar un objeto con propiedades 3D, y el más sencillo es un
cubo. No, no un cubo de fregar el suelo, sino un hexaedro. Haz el siguiente
experimento: toma un cubo de 20x20 centímetros, por ejemplo una caja de cartón.
Guiña un ojo y coloca el cubo a unos 20 cm. de manera que una de las aristas
apunte directamente al ojo abierto. Obviamente ves un cuadrado, pues el cerebro
no entiende que hay una parte posterior.
Esa es la imagen que dibujamos en las líneas pares.
Guiña el otro ojo, y ahora ves que el objeto tiene profundidad. Eso es lo que
dibujamos para el otro ojo. Al verlo con las gafas, daba un cierto aspecto de
3D. Tras añadir texturas, sombras, y un poco de antialiasing, el cubo ya tenía
mejor aspecto.
Ampliamos el programa para girar y desplazar el cubo en el espacio, y el efecto
era sorprendente.
Jugamos un rato variando la distancia entre los dos puntos de vista IPD
Inter-Pupillary Distance. La mayoría de las personas tienen entre 6 y 8
centímetros. Establecer 2 puntos de vista separados más de 9 centímetros hace
que los objetos parezcan curvados. Más de 11 centímetros y el cerebro no
entiende la imagen, que pasa a ser uni-focal. Es como si uno de los ojos se
desconectara.
Aunque estos experimentos sin duda son graciosos e interesantes, nuestro
objetivo es hacer un escritorio virtual, no estudios sobre la visión.
Todas las pruebas anteriores las hicimos con OpenGL, dentro de una ventana
dedicada. Ahora toca convertir el escritorio en 3D.

El primer intento lo hicimos sobre Linux. El sistema estándar de ventanas es
X-Window. Esto usa un modelo en el que el display actúa como servidor de
gráficos, y las aplicaciones son los clientes.
En X11R5 y XF86 se pueden definir varias resoluciones. Lo mínimo es VGA 640x480
pero existen drivers para resoluciones menores tales como Hércules, o 8510, que
sólo recordarán los más viejos del lugar. Lamentablemente no están soportados a
partir de la versión 4.0 , y los de la 3.4 son demasiado distintos como para
poder adaptarlos.

Nosotros queríamos que la resolución fuera parecida a la que tienen las gafas.
Si no, aparecerían problemas. Por ejemplo, sería posible mover el ratón a la
posición (400,400) y seguiría apareciendo en el monitor, pero no en las gafas.

Una posible solución sería establecer un area virtual. En X-window se puede
definir el tamaño a partir del cual la pantalla tiene que hacer scroll. Esto
impide que el ratón vaya más allá. Lamentablemente el área virtual debe ser
más grande que el área real, y no viceversa. Para los que se hayan perdido: si
el monitor sólo puede representar 640x480 entonces puedes definir un área
virtual de 1024x768, y la pantalla se desplazará automáticamente cuando muevas
el raton más allá del límite. Por supuesto no puedes ver toda la pantalla a la
vez, pero sí a cachitos.
Así que tuvimos que ver dónde y cómo se hacía el scroll. No fue difícil
adaptarlo para que lo hiciera cuando llegara más allá de 260x230.

Ahora lo malo es el tamaño. Los iconos más pequeños de KDE ocupan 48x48. Pones
4x4 iconos en pantalla, y ya la tenemos llena.
Y el cursor del ratón ocupa 16x16, es decir, 1/15 de pantalla. Haz la prueba de
definir un cursor de 1.5 cm. para tu pantalla de 15 pulgadas, y ya verás lo
grande que queda.
Por último quedaba la decoración de las ventanas. Los bordes, márgenes, barra
de título, ... ocupan demasiado y se comen casi todo el área de visualización.
Podíamos cambiar el driver para que dibujara sólo los pixels verticales pares,
es decir, comprimir la pantalla a lo ancho en un 50%. Fue sencillo de
programar, pero quedó realmente feo.
La segunda solución podría ser cambiar todos estos elementos, y hacerlos más
adecuados a nuestro espacio de visión. ?Quién necesita un cursor de 16x16, que
en las gafas parece ocupar 10 centímetros?
La otra solución era usar un escritorio más sencillo, como fvwm2. Entonces
tendríamos que cambiar los iconos, o al menos la manera de dibujarlos para que
aparezcan en 3D.

Por supuesto siempre podríamos adquirir otras gafas, como mayor resolución. No
sólo ganaríamos más área de dibujado, sino que más pixeles darían mayor
nitidez. Ya no veríamos esos puntos tan gordos en la pantalla virtual.
Pero eso tiene un coste. Y las gafas HMD no son un producto especialmente
popular, por lo que no hay muchos fabricantes, y los precios no bajan con la
misma velocidad que la de los lectores MP3.
Para una resolución de 640x480 hay que soltar al menos 1.000 euros, y nosotros
no estamos dispuestos a gastarnos todo eso en algo que sólo queremos para
jugar.
Sin embargo tomamos otra decisión, fruto sin duda de la desesperación y el
tequila: haríamos nuestras propias gafas.

Obviamente debían ser portátiles. La solución de poner en un arnés 2 monitores
a la altura de los ojos no era viable.
Tampoco valía un sistema de espejos que estuvieran conectados a los monitores.
La posibilidad de usar un proyector de diapositivas para proyectar la imagen en
la pared tampoco valía, pues no es un entorno virtual en el que moviendo la
cabeza veas una imagen distinta.
Colocar un GameBoy en cada ojo tampoco sirve, pues la resolución es incluso
menor.
Así que terminamos usando una pantalla TFT que adquirimos en eBay por 50 euros.
Como pesaba 3 kilos, desenganchamos la pantalla de su marco y le quitamos todo
el peso innecesario, dejando solamente el display y el cable que lo conecta a
la circuitería de la placa del monitor. Una vez que bajamos el peso hasta
500 gramos la fijamos a un casco de la construcción.
La pantalla queda en posición horizontal a 10 cm de los ojos.

Este es el esquema, visto desde arriba: cada "O" es un ojo, y "^" es la nariz.

----------- <-pantalla
O ^ O <-ojos

El invento queda estrambótico, pero funciona.
En una segunda fase suspendimos la pantalla de un muelle del techo. Esto
eliminaba mucho peso, pero impedía los movimientos por la habitación.

Ahora la manera de dibujar es mostrar una imagen en la parte izquierda de la
pantalla, y otra imagen en la sección derecha.
A una resolución de 1024x768, se usan 1024/2=512 pixels para cada ojo. Cada una
de estas partes las llamamos marco.
Como la pantalla está a unos 10 cm de los ojos, el FOV es 90 grados, es decir,
que 512 pixels ocupan 10 cm. de visión. En otras palabras, es como si vieras
una televisión de 2 metros de ancho a 1 metro de distancia, y cada pixel ocupa
2 milimetros.

Pero otro asunto es hacer que el escritorio se muestre correctamente.

Para recapitular: queremos que cada elemento del escritorio (ventanas, iconos,
puntero, barra de herramientas, ...) tenga una propiedad extra: profundidad.
Para dibujarlos hay que tener en cuenta su posición y su profundidad, y
dibujarlo dependiendo si la imagen se verá en un marco o en el otro.

Si un icono del escritorio está en un plano muy lejano, la imagen debe estar
en las mismas coordenadas en ambos marcos.
En cambio, si el icono está cercano, en el marco izquierdo debe tener una
coordenada X de valor menor que la del marco derecho. Piensa un momento sobre
esto: un objeto extremadamente cercano (2 cm.) al ojo izquierdo no se puede
ver con el ojo derecho porque lo tapa la nariz, y porque no puedes bizquear
tanto.
En X-window los objetos ya pueden incluir la propiedad de profundidad, pero en
KDE lo único que hay es el canal alfa, que se usa exclusivamente para
transparencias.

Al parecer en el próximo MS-Windows ya se incluye este concepto de entorno en
3D, lo que permite poner una aplicación en primer plano de visión, mientras que
a través de sus áreas transparentes puedes seguir viendo las que estan detrás.
Lo mismo se aplica a Mac-X (o como se llame ahora), pero ambos entornos no son
programables tanto como nosotros necesitamos.

Hacer que la misma imagen se muestre en ambos marcos fue fácil: le dijimos que
teníamos una pantalla de 512x768, con lo que X-Window solo usaba la parte
izquierda de la pantalla, es decir, el marco izquierdo. Luego parcheamos las
rutinas de dibujo para que pintase exactamente lo mismo en las coordenadas
(x,y) que (x+512,y)

Eso sí, también el cursor del ratón aparece 2 veces.

Ahora se trataba de darle profundidad a los objetos del escritorio. Usamos el
gestor de ventanas fvwm2 porque es simple y rápido.
Cada objeto contiene una estructura para localizarlo en el escritorio. Esta
estructura contiene las coordenaas X, Y, ademas de la anchura y la altura.
Añadimos un dato más para la profundidad.
Los dibujos de los objetos son siempre un mapa rectangular de bits plano. Para
convertirlo en un objeto 3D hay que convertirlo en una caja (mas correctamente,
un ortoedro).
Esto se consigue poniéndole un fondo y 4 caras.
Así, un icono con dibujo de 16x24 lo convertimos en un objeto con 6 caras de
profundidad 20, cada una con un dibujo.

+-----+
20 /|
+-16--+ +-16--+ |
| | | | |
24 | ---> 24 | |
| | | | +
+-----+ +-----+/

La tarjeta de video es capaz de dibujar los lados del cubo sin más que decirle
cual es la textura correspondiente. Luego veremos que esto lamentablemente no
se puede usar para al caso de visión estereoscópica.
Por supuesto el dibujo del fondo del cubo nunca es visible. Es más, sólo 3
caras del cubo son visibles por un mismo ojo. Pero puede que el otro ojo vea
otras caras del cubo. Haz la prueba: pon un dado de parchís a 3 cm de la punta
de tu nariz . Con el ojo izquierdo vez la cara superior, la frontal, y la
izquierda. Con el ojo derecho ves la cara superior, la frontal y la derecha.
Este es el efecto que queremos conseguir.
Para sólo un ojo ya lo hemos conseguido. Pero para conseguir vision
estereoscópica hay que dibujar otra imagen en el marco derecho. Aquí entra la
magia de X-window.
Como he comentado antes, X-window es una arquitectura en la que una aplicación
manda instrucciones para dibujar, y otra aplicación (el servidor de gráficos)
se encarga de dibujarlos.
A quien hay que engañar es al cliente, no al servidor. Hay que hacer que el
cliente calcule la imagen izquierda, la mande a dibujar, y luego calcule la
imagen derecha desde un punto de visión diferente, y la mande a dibujar.
El cliente es en nuestro caso el gestor de escritorio fvwm2. En la rutina
DrawObject se le pasa un puntero a un objeto gráfico, normalmente porque ha
cambiado su bitmap, o porque ha pasado a primer plano.
Esta rutina toma las coordenadas X, Y y el dibujo con el bitmap, y lo manda al
servidor de gráficos.
No resulta difícil modificarla para que considere las caras del ortoedro y
mande un bitmap de tamaño ligeramente más grande.
Un poquillo de matemáticas: si un ortoedro mide x,y,z , y se representa en
perspectiva caballera, ?cuál es el tamaño máximo de su proyección sobre el eje
Z ?
En otras palabras: ?cuánto crece el bitmap con el objeto en 3D? La respuesta es
z/sqrt(2) , esto es más o menos z/1.5
Así, el objeto 3D anterior de 24x16x20 necesita un bitmap 2D de (24+20/1.5) x
(16+20/1.5) = 38x30

Este dibujo necesita calcularse 2 veces, uno para cada marco. El resultado es
ligeramente diferente para cada marco, excepto cuando el objeto no tiene
profundidad, o ésta es muy pequeña respecto a la distancia. Esto sirve para
agilizar el proceso de dibujo: los objetos que no han sido transformados a
cubos (en una fase inicial empezamos sólo con los iconos, olvidándonos de
ventanas, puntero, ...) pueden usar el mismo dibujo en la misma posición+512
para ambos marcos.
Las rutinas típicas de X-window usadas para inicializar el modo de dibujo son:
XOpenWindow, XCreateGC, XMapWindow
Sin embargo fvwm2 también usa DisplayWidth, DisplayHeight que en nuestro caso
debemos cambiar para que usen siempre 512, en vez de 1024.
En todos los sitios donde llama a xxx_Draw_xxx hay que llamarlo 2 veces, uno
para cada marco.
Las primeras pruebas funcionaron bien: los iconos en 3D aparecían en ambos
marcos.
Un poco más difícil fue hacer que simularan tener distintas profundidades.
Aunque la tarjeta de video es capaz de dibujar objetos en 3D, no es capaz de
considerar 2 puntos de visión.
Por ello tuvimos primero que proyectarlos a 2D, y dibujar los polígonos (la
proyección de las caras son siempre rectángulos y romboides). La velocidad de
dibujado no era un problema.
Una vez funcionando los iconos, las ventanas representaban una nueva
dificultad: se podían solapar.
En 2D las ventanas son planas, por lo que el mayor problema sucede cuando una
ventana está cubierta por varias, como en el dibujo:

+--------+
| |
| |---------+
| | |
| | +-------+
+--------+ | |
| +-------+
| |
+--------------+

Pero en 3D un problem adicional sucede cuando una cara de una ventana solapa a
otra:
+---------+
/ /|
/ / |
/ / /+---+
+---------+ / /|
| | +----+ |
| | | B | /
| | +----+/
| A | |
| | +
| | /
| | /
+---------+/
Más o menos se puede ver que el objeto B está más atrás que A, pero sin embargo
lo solapa.
No se puede dibujar primero B y luego A porque no se vería medio B.
La solución en este caso es pintar primero A y luego B. Pero esto es ilógico,
puesto que A está delante de B.
Y si lo piensas un poco, ésto vale para el ojo derecho. El izquierdo es posible
que ni siquera vea B, pues quizás A lo tapa.
Lo que hicimos es pintar primero la parte superior, luego la cara derecha,
despues la inferior, la izquierda y finalmente la cara anterior. O sea, en el
sentido de las agujas del reloj. Esto para el ojo derecho.
Para el ojo izquierdo el orden es: superior, izquierda, abajo, derecha, y
anterior. O sea, en sentido contrario a las agujas del reloj.
Esto garantiza que las caras cubren lo que tienen que cubrir. Obviamente
algunas zonas se pintan 2 veces, pero no más, gracias a que también usamos la
profundidad para dibujar primero los objetos más lejanos.
La solución más exacta habría sido usar uno de los algoritmos de representación
en 3D, pero para octoedros el algoritmo usado funciona perfectamente y es más
rápido.

Repito que no es posible pintar esferas ni objetos que no tengan 6 caras, pero
para un escritorio ésto es más que suficiente.
Un paso más allá sería usar transparencias. Por ejemplo, los iconos siempre se
inscriben en un rectángulo, pero comúnmente tienen areas que son transparentes,
tomando formas no rectangulares, imagínate la letra T en 3D:
_____________
/ /|
+------------+ |
| | /
+----+ +---+/
| | |
| | |
| | |
| | |
| | /
+---+/
En este caso no hay sólo 4 lados, sino que cada lado se compone de varios
rectángulos. Este caso no lo hemos implementado.

Ya podíamos pintar iconos y ventanas. El siguiente paso era la decoración de
las ventanas: barra de título, marco de ventana, barra de scroll, botón para
minimizar y cerrar.
Estos elementos se llaman widgets. En X-window existen varios conjuntos de
widgets. El inicial era Athena, bastante simple, formado por simples
rectángulos de 1 único color.
Luego surgieron Motif (y Lesstif), KDE, Gt, y otros muchos que no tuvieron
tanta aceptación y cayeron en el olvido.
En concreto fvwm2 usa unos widgets definidos específicamente. También son
bastante simples, en general un rectángulo con un marco, y una línea superior
y otra lateral para dar aspecto de tridimensionalidad.
Existen varios módulos en http://fvwm-themes.sourceforge.net/ para hacer que
parezcan como NeXT, Win95, Mac, ...

Por ejemplo el icono de cerrar una ventana es algo así:

1234567890123456

1 *OOOOOOOOOOOOOO%
2 ...............@
3 ...X.......X...@
4 .....X...X.....@
5 .......X.......@
6 .....X...X.....@
7 ...X.......X...@
8 ...............@

que usa 5 colores, en una trama de 16x8 pixels
Este dibujo simula que el widget ocupa 15x7 y deja una linea horizontal
superior y otra vertical a la derecha para simular la profundidad. Pero en
realidad es 16x8 .
Este pixel extra que da sensación de profundidad se llama Gravity y se calcula
en geometry.c en la función gravity_get_offsets. El valor es 0, 1 ó -1.

Para nuestro caso lo cambiamos por un cubo en 3D de 16x8 con una profundidad de
1 pixel. Aunque luego lo cambiamos a 5 pixels de profundidad, para dar más
sensación de 3D. El dibujo ocupa a lo ancho un total de 16 + 5/sqrt(2) = 16+4 =
20 cuando está a una distancia equivalente a 1 metro.
O sea, que tenemos que eliminar la "gravedad" y sustituirla por un dibujado más
sofisticado.

Dado que el area original y la nuestra ambas ocupan 16x8 pixels, podemos
pinchar el ratón en cualquier punto interior a esa área para cerrar la ventan.
El uso del ratón no cambia.
Notar que cuando se pincha el ratón en un pixel entre 0 y 15, el widget queda
seleccionado por su cara frontal. En cambio, si pinchamos en un pixel entre 16
y 20, equivale a pichar en la cara lateral derecha, por lo que el widget no se
selecciona.

Gracias a la estructura orientada a widgets que usa fvwm2 es sencillo cambiar
todos los widgets.
En unas horas ya teníamos un entorno realmente estereoscópico.
Es francamente excitante ver cómo las ventanas que están delante, pero muy a
la izquierda, aparecen como ladrillos de mucha profundidad. Los objetos más
lejanos no tienen aspecto de tridimensionalidad.

La limitación es ahora que no podemos cambiar el punto de visión: el escritorio
es siempre el mismo.

El siguiente paso es conseguir movilidad. Imagínate que cuelgas 20 monitores
del techo de la habitación, y en cada monitor muestras una parte distinta del
escritorio. Puedes moverte hacia adelante para ver con más nitidez un monitor
alejado, o puedes girar la cabeza para leer otro monitor que antes veías con el
rabillo del ojo. No sólo eso, sino que queremos que sea posible mover las
aplicaciones entre los monitores y cambiar su distribución.
Para esto necesitamos un sistema de posicionamiento.
Con un HMD comercial suele venir incluido un dispositivo que detecta el giro de
la cabeza, y la posición de ésta. En total intervienen 6 coordenadas: X, Y, Z,
giro horizontal (como cuando dices NO moviendo la cabeza), giro vertical (como
cuando dices SI) y giro axial (como cuando ladeas la cabeza).
El primer intento era detectar los giros. La primera idea (no te rías) era atar
un hilo a la punta de la nariz y con 2 poleas unirlo a la ruedecilla del ratón
que detecta movimiento vertical:

techo
__________
O O <-polea V1
p | |
a | |
r | | <-hilo
e XXX |
d XXX | ____
XXX | / \
^ | O | <-usuario
| +-< |
raton |_/ |
\ /

Así, al girar la cabeza en sentido vertical (como para decir SI) el ratón
detectaría el movimiento.
Un dispositivo similar serviría para el giro vertical.
Como cada ratón tiene 2 ruedecillas, sólo necesitamos 3 ruedecillas para todos
los giros; es decir, 2 ratones.
Lo más difícil fué encontrar las fórmulas matemáticas para calcular la posición
de la cabeza. Si haces un giro horizontal, la ruedecilla horizontal cambia,
pero también la vertical, pues la distancia desde la nariz hasta la polea V1
cambia según el ángulo de giro.

Olvídate por un momento de los giros anteriores: vamos a trabajar sólo con el
movimiento en 3D. Toma una esquina de tu habitación como coordenadas (0,0,0)
Para simplificar, suponte que la habitación mide 1 metro en las 3 dimensiones.
Cualquier punto del cuarto tiene coordenadas X,Y,Z todas >=0 y <=1
ahora pones 3 poleas en los puntos (0,0,1) , (0,1,0) y (1,0,0)

| (0,1,0)
|Y
|
0___X__ (1,0,0)
/
Z/
/
/(0,0,1)

En cada polea pones una cuerda, y atas las tres a la punta de un bolígrafo.
En el otro extremo pones un peso y entre el peso y la polea pones una vuelta
alrededor de la ruedecilla del ratón:

__________
O O <-polea
| \
| \
@ <-rueda \
| x <-boligrafo
|
XXXXX
XXXXX <-peso
XXXXX

Ahora puedes mover el bolígrafo en 3D y las ruedecillas de los ratones girarán.
Para saber cuál es la posición de la punta del bolígrafo hay que saber lo que
ha girado cada rueda, por ejemplo x1, y1, z1.
Ahora se trata de calcular el punto x0,y0,z0 tal que:
-la distancia entre (x0,y0,z0) y (1,0,0) es igual a x1
-la distancia entre (x0,y0,z0) y (0,1,0) es igual a y1
-la distancia entre (x0,y0,z0) y (0,0,1) es igual a z1

Esto es una simple matriz de 3x3 con solución única.

Notar que ésto sólo resuelve el movimiento pero no el giro: si mueves el
bolígrafo manteniendo fija la punta, las ruedecilas no detectan movimiento.

Ahora bien, para combinar el movimiento y el giro necesitamos 3+3 ruedecillas,
o sea, 3 ratones.
Los más avispados se habrán dado cuenta de que una solución aparentemente
equivalente es atar 3 cuerdas a la punta del bolígrafo, y otras 3 al otro
extremo. Pero en este caso nos dejamos un movimiento: el giro sobre el eje
longitudinal (el que va desde un extremo al otro).
Pero también se habrán dado cuenta de que en realidad 2 de las ruedecillas son
redundantes, pues la distancia entre los extremos del bolígrafo es siempre
constante.
Decir que el experimento funcionó tras un poco de deducción trigonométrica, y
en un par de días ya teníamos hecho un programa que mostraba en la pantalla
una cabeza moviéndose.
En vez de atar los hilos a la punta de la nariz los atamos a la pantalla y al
casco que le servía de arnés.

Tras hacer unas cuantas pruebas surgió otra idea interesante: ya que en 3D los
objetos más lejanos aparecen más pequeños, dándole la vuelta al argumento, los
objetos que aparecen pequeños es porque están lejanos.
Me explico: imagínate que tomas una foto digital de un balón que está a 10
metros. La imagen del balón mide 30x30 pixels. Acerca el balón hasta 5 metros.
Ahora la imagen mide 60x60 pixels.
Toma un vídeo de un balón acercandose: cada vez la imagen es mayor.

Coloca la cámara en una esquina de la habitación, y sitúa una pelota de tenis
sobre tu cabeza. A medida que te acerques a la cámara, la imagen de la pelota
aparece más grande.
Ahora coloca 3 camaras en 3 esquinas, y la pelota en el centro. La imagen
aparece de 20x20 pixels en las 3 cámaras. A medida que acercas la pelota a una
de las cámaras, aparece más grande.
Esto da una idea d eque es posible calcular la posición y la distancia, basada
en el tamaño fotografiado.

Con esto nos evitamos todo el lio de hilos por toda la habitación. A cambio
necesitábamos 3 cámaras digitales conectadas al ordenador y capaces de
transmitir vídeo, pero esto resultó más barato de lo que pensábamos, porque
encontramos a gente que tenía modelos antiguos.
Ahora se trataba de hacer un programa que tomara la imagen digital, ubicara la
pelota dentro de la imagen, y calculara su tamaño y posición.

Para esto hubo que entender los programas de captura de imágenes. Nuestras
cámaras son QuickCam-Pro-3000 . Con una resolución 640x480, es ideal para
nuestros propósitos. Sólo se consiguen 5 imagenes por segundo de vídeo, pero
como apenas hay cambios en la imagen capturada, la compresión realizada
internamente por la cámara resulta ser bastante eficaz.
La conexión es USB por lo que necesitamos 3 puertos.
Lo malo es que el driver que hay que usar es pwc Philips USB
(http://www.smcc.demon.nl/webcam) para un kernel 2.4 pero parece haber un
problemadebido a las licencias de uso. También usamos otros drivers
(http://www.saillard.org/linux/pwc) para el kernel 2.6 que funcionan de miedo.

Como las cámaras estaban fijas, pudimos calcular la posición de la pelota.
La pelota es esférica, así que era imposible saber cuándo se habia realizado
un giro sin movimiento. Una solución era usar 2 pelotas, pero otra más sencilla
era usar un cubo, con cada una de las caras de un color distinto.

Usamos para ello colores puros y brillantes para cada cara: rojo, verde, azul,
amarillo, azul claro, rosa.
-Tomamos una imagen de cada cámara.
-Hacemos que encuentre el cubo (de 10x10x10 cm, colocado a 10 cm. de la cabeza)
-Localiza las 3 caras visibles (cada cámara sólo puede ver 3 lados del cubo)
-Encuentra las esquinas, con lo que ya tenemos su posición.
-Localiza el punto medio de las caras.
-Calcula la distancia a las esquinas, y deduce el tamaño.


Colocamos una cámara en cada eje, apuntando a las paredes px, py, pz

| (0,1,0)
|Y pz
|
px 0___X__ (1,0,0)
/
Z/ py
/
/(0,0,1)


De nuevo, basta combinar los datos de las 3 cámaras y unos cálculos
trigonométricos que tansforman los datos anteriores en coordenadas 3D.
La siguiente idea fue todavia mejor: en vez de poner el cubo sobre la cabeza,
construimos un cubo mayor, de 25x25x25 centímetros y metimos la cabeza dentro.
Al ser el cubo mayor, los cálculos eran más exactos. Las cámaras podían ubicar
rápidamente el cubo tomando un muestreo cada 20 pixels, y dentro de la caja la
única luz proviene de la pantalla TFT, con lo que no hay interferencias con el
mundo real.
Eso sí, resulta muy gracioso ver a un tipo con una caja de colores en la cabeza
moviéndose por la habitación.

Tras la diversión, el trabajo. Ahora teníamos que conseguir coordinar el
escritorio con la posición de la cabeza, y la dirección de la mirada.
El entorno de trabajo pasa a ser una esfera con 360 grados en caja eje.
Teníamos que decirle a fvwm2 que desplazara el escritorio hacia los lados y
hacia arriba y abajo. Como cada objeto (icono, ventana, ...) tiene unas
coordenadas x,y de tipo int, podemos poner un valor máximo de 32768 y hacer un
escritorio virtual de hasta 32768 pixels.

Cada marco puede dibujar 512 pixels a una distancia a los ojos de 10 cm, lo que
implica que cada pixel parece que ocupa 2 mm si se viera a 1 metro de
distancia, que es bastante buena resolución.
Una esfera de 1 metro de radio tiene un perímetro de 2*3.14*1 = 6.28 metros lo
que dividido por 2 milimetros da un total de 3140 pixels. Un escritorio de
3000x3000 es bastante grande, ?no crees?

Para hacer que se desplazara el escritorio de acuerdo con el movimiento de la
cabeza hay que investigar las rutinas que se encargan de mover todas las
ventanas en fvwm2. Descubrimos que ya estaba incorporada la posibilidad de
disponer de un escritorio virtual, y simplemente hay que mover la "ventana" a
través de la cual se ve el área adecuada.
Moviendo el ratón cerca de los bordes, el escritorio se desplaza. En nuestro
caso hubo que sustituir el movimiento del ratón por las coordenadas de
situación de la caja, dadas mediante las cámaras. El algoritmo es algo así:
-encontrar el centro de la caja, y la posición de los ojos
-encontrar las esquinas de la caja, y la dirección en la que miran los ojos
-convertir las coordenadas x,y,z en 2 ángulos dentro de la esfera de radio 1.
Un ángulo para el giro vertical y otro para el horizontal
-encontrar la "página" que corresponde a estas coordenadas esféricas
-dibujar los objetos dentro de esta ventana. Equivalentemente, mostrar el trozo
de mega-escritorio incluido en esta ventana.
-dibujar en el otro marco los objetos vistos por el otro ojo


En la nomenclatura de fvwm2, existen varios Desktops, cada uno de MxN páginas,
cada una del tamaño de la pantalla física, la cual actúa como un "viewport" de
una de las páginas:

Desk 0 Desk 1
+----------+----------+ +----------+----------+
| | | | | |
| Page 0 0 | Page 1 0 | | | |
| | | | | |
| | | | | |
+----------+----------+ +----------+----------+
|+--------+| | | | |
||Page 0 1|| Page 1 1 | | | |
|| || | | | |
|+--------+| | | | |
+----------+----------+ +----------+----------+


Nuestros cambios deben afectar al modo como se dibujan las páginas.
Todo esto lo implementamos en la rutina MoveViewport del módulo virtual.c del
paquete fvwm2.
Esto se encarga de redibujar todos los elementos a una nueva posición
(x+delta_x, y+delta_y). Nosotros debemos añadir una nueva variable global
(marco_x,marco_y) y sumarla a los anteriores valores.
Internamente esto usa XMoveWindow con las nuevas coordenadas, o invoca a
BroadcastPacket para aquellos elementos que no son ventanas.
En el fondo se llaman a comandos ICCCM, que es un estandar definido para
gestores de ventanas en X-Window. Esto hace que otros gestores como twm, mwm,
uwm, ... funcionen todos igual.

Cada objeto del escritorio adquiere unas coordenadas x,y entre 0 y 3000 dada
inicialmente por el gestor de ventanas fvwm2. En un entorno 3D, la coordenada
Z es nueva, y el fvwm2 no sabe cómo manejarla. Decidimos que el valor estaría
entre 0 y 3000, siendo por defecto el valor 1000 correspondiente a una
distancia de 1 metro.
Objetos con z>2500 estarían muy lejos, y aquellos con valores z<50 estarían a
menos de 5 cm, con lo que solo serán visibles para un ojo.

Los iconos y ventanas inicialmente se ponen con profundidad 1000 pero hicimos
una aplicación para poder moverlos hacia adelante y hacia atrás. No es todavía
posible girarlos; siempre están mirando hacia el usuario. Matemáticamente esto
quiere decir que el vector normal siempre pasa por (0,0,0)

El objeto del que todavía no hemos hablado resultó ser el más complicado de
manejar: el ratón.
En un entorno 2D es muy fácil, pues el ratón se puede mover también en sólo 2
dimensiones. Pero para mover un objeto hacia adelante o hacia atrás hace falta
otro control. Nosotros lo solucionamos con la rueda que suelen incorporar entre
los botones, y que normalmente se usa para avanzar páginas o hacer scroll
rápidamente.
Simplemente pinchar en un objeto, y esta rueda lo acercaba o alejaba, con lo
que se visualizaba más grande o más pequeño. El comportamiento de esta rueda
no está gobernado por fvwm, sino que X-window lo trata como un dispositivo
independiente del ratón, mapeándolo a la tecla página-arriba y página-abajo.
Así que hicimos una aplicación que siempre se estuviera ejecutando, y que
capture esas teclas. Luego se trata de reenviarlas a fvwm2, y ampliarlo para
que al recibir estas teclas aumente o disminuya la profundidad del objeto
seleccionado.

Pudimos haber usado las extensiones XKB que están perfectamente soportadas por
X-window, pero esto suponía re-compilar las X, lo cual tarda bastante. Más
sencillo era modificar el módulo del kernel que captura el ratón, y mandar los
datos de la rueda a un nuevo dispositivo, que se puede leer con un simple pipe.
Luego con xmodmap se puede mapear a cualquier tecla, y fvwm2 permite ejecutar
una acción cualquiera cuando se pulsa una tecla.

Esto funciona bien, expecto un detalle importante: el ratón hay que apoyarlo en
alguna parte, con lo cual no nos podemos separar mucho de él. Y resulta
bastante incómodo manejar el ratón de espaldas cuando estás mirando en la
dirección opuesta.
La solución es un ratón 3D. Este cacharro consiste en un mando a distancia, y
un receptor en la esquina de la habitación. El dispositivo tiene 2 emisores con
2 rendijas, una horizontal y otra vertical. El receptor tiene 2 sensores.
Cuando apuntas directamente al receptor, la señal es muy nítida, y lo
interpreta como (0,0) . A medida que apuntas más lejos del receptor, la señal
es más difusa y en función de la intensidad recibida sabe más o menos a dónde
estás apuntando.
Esto funciona bien pero hay que apuntar a un sitio cerca del receptor. Si pones
el receptor en una pared, y apuntas a la pared opuesta, no capta nada.

Lo que se nos ocurrió fue hacer algo parecido a lo de la caja y las cámaras de
video. Pintamos un dedal de color naranja fosforescente, y mediante las 3
camaras lo ubicamos. Pero el dedal es pequeño, por lo que el tamaño no cambia
ostensiblemente. A pesar de ello logramos hacer una triangulación bastante
aceptable.

Una mejora de esto fue poner una pequeña bombilla de luz roja en lugar del
dedal. Ahora podíamos medir la luminosidad para intentar calcular la distancia.
Lamentablemente esto obligaba a apagar las luces de la habitación, con lo que
las cámaras no verían la caja de la cabeza.
El dedal pintado de naranja también tenía un inconveniente: si en la habitacion
hay algun objeto naranja en la pared, las camaras pueden confundirse.

Por eso mantuvimos la idea de la luz, pues era más facil de localizar que el
dedal. Una pequeña bombilla alimentada por una pila colocada en el antebrazo,
que decidimos llamar dedo-luz. En inglés, finger-light, pronunciado
"fingerlai".
Con las 3 cámaras podíamos detectar exactamente la posición, pero no el giro.
Esto no importa nada, pues el puntero es, como su nombre indica, un objeto
puntual.
El algoritmo de búsqueda de esta luz lo mejoramos haciendo la siguiente
suposición: si en un tiempo t0 la posición es (x0,y0,z0) entonces en un tiempo
t+dt la posición no puede estar muy lejana de la anterior. Esto impone una
limitación a la velocidad con la que podíamos mover el dedo-luz, pero el
resultado era satisfactorio.

Voy a explicarlo con más detalle: Primero supongamos una habitacion de 1 metro
de lado.
Colocamos una cámara en una esquina del techo, apuntando a la pared opuesta.
Ajustamos el foco para que capture exactamente toda el área de la pared.
Así, si pones el dedo-luz pegado a la pared en el punto (x,y) , esta cámara
también lo ve en la posicion (x,y)
Cuando lo mueves directamente hacia la cámara, ésta no detecta cambios. Pero
hay otras cámaras que sí lo detectan.
Un punto (x,y,z) se ve:
-en la camara X, en el punto { y+sin(x/y), z+sin(x/z) }
-en la camara Y, en el punto { x+sin(y/x), z+sin(y/z) }
-en la camara Z, en el punto { x+sin(z/x), y+sin(z/y) }

Para encontrar (x,y,z) a partir de las imágenes de las cámaras, solo hay que
resolver el sistema inverso de 3 ecuaciones con 3 incógnitas.

El inconveniente es que hay algunos puntos ciegos que no están detectados por
ninguna cámara. El caso peor es el punto (1,1,1) pero como es una esquina en el
suelo, es altamente improbable que el dedo-luz esté en esa posición.

Ahora bien, en el ratón existen al menos 2 botones. ?Cómo simularlos con el
dedo-luz? Pues cerrando un circuito eléctrico.
Colocamos el dedo-luz en el pulgar de la mano derecha. Además le colocamos un
cable (de 1 hilo) conectado al ordenador, y una placa metálica en el punto 1.
En el dedo índice pusimos otra placa metálica 2 conectada al ordenador mediante
otro cable.
Enviamos electricidad por el cable 1. Cuando el pulgar y el dedo índice se
tocan, las placas 1 y 2 entran en contacto y el circuito se cierra, con lo que
la corriente llega al ordenador a través del cable del dedo índice.
Los mismo hacemos para el dedo corazón. Ya tenemos 2 pulsadores ... digitales.


indice corazon
__ __
2/* \ 3/ \
luz-> XX |* | | |
pulgar /--\1 |* | | |
| *| |* | | |
\ *\ |* | | |
\ *\__|* | | |
\_ * * |__| |
* *
cable emisor* *cable receptor


Para leer los datos enviados por el dedo-pulsador hay que conectarlo al
ordenador de alguna manera. Podíamos haber usado el puerto paralelo, pero fué
más sencillo usar el microfono de las webcams. Para ello sacamos el cable de la
cámara y lo conectamos a los dedo-pulsadores con una resistencia. Cuando los
dedos se juntan, la webcam cree que está oyendo un sonido, lo cual se codifica
y se transmite por el cable USB hasta el ordenador. Modificamos el módulo pwc
para leer también este dato, y lo metemos en otro pipe para que fvwm2 lo pueda
leer.

Ahora sí:
-acercamos el pulgar a una ventana o un icono
-juntar el dedo índice y el pulgar para seleccionarla ("pinchar")
-mover el pulgar (y toda la mano, claro) para arrastrarla a la nueva posición
-separar los dedos para dejarla allí

Y ahora resulta incluso más gracioso ver a un tipo con la caja en la cabeza,
con una luz en un dedo como ET, juntando y separando los dedos como si
estuviera cazando mosquitos.

Otra solución que no hemos investigado es mandar la información mediante
ultrasonidos. Seguro que habéis visto las llaves electrónicas que sirven para
abrir el coche desde 5 metros. Lo que hacen es enviar un ultrasonido, que es
detectado por un sensor dentro del coche. Pues bien, podemos poner una llave en
el dedo índice, y otra en el corazón. Cuando se apriete el pulsador con el dedo
pulgar, lo podríamos detectar. Es un tema no investigado pero plausible.

Por fin teníamos algo real para un mundo virtual.
Hicimos un cursor en 3D que se moviera de acuerdo con el dedo-luz. Esto fue
fácil, usando XWrapPointer en X-window.
El cursor podía estar fuera del campo de visión, aunque ésto no implicaba que
el escritorio tuviera que desplazarse.
Así que hubo que decirle a fvwm2 que no desplazara el escritorio cuando el
ratón se acercase a los bordes, sino cuando cambiase el punto de visión de la
cabeza.

También cambiaba de tamaño según la distancia al observador. Incluso le hicimos
un modelado en 3D para el cursor. Todos los demás objetos eran simples
ortoedros, pero el cursor realmente es un cono. Cuando lo ponías cercano a los
ojos aparecía grande y majestuoso: un auténtico conazo.
Había un problema cuando el dedo-luz estaba tapado por la caja o el cuerpo del
usuario. La solución habría sido poner más cámaras, con lo cual se aumentaría
la exactitud del sistema. Pero no queríamos gastar más dinero, así que
intentamos tener cuidado para que el dedo-luz nunca esté cubierto por otro
elemento físico.

Todavía falta otro elemento: el teclado. Al movernos por la habitación es
imposible acceder al teclado, a no ser que tengas un teclado inalámbrico y te
lo cuelques al cuello. Esto no es adecuado. Así que recordamos a Johñ Mnemonic
y decidimos hacer un teclado virtual, algo parecido al que incorpora la Palm.
Esto no es más que una aplicación que siempre ocupa la parte central de la
pantalla, y dibuja teclas con fondo transparente. Pones el pulgar (en realidad
su representacion virtual en la pantalla) para seleccionar la tecla que deseas
pulsar, y juntándolo con el índice se produce la pulsación. Fácil y simple,
pero más complicado de usar de lo que parece. Sobre todo porque a veces
necesitas 2 dedos para teclear. La solución estaba al alcance de la mano. De
la mano izquierda para ser preciso.

Montamos otro dedo-luz con una luz de color verde para el pulgar izquierdo, y
cables para cerrar el circuito formado por el dedo índice y el pulgar. También
para el corazon-pulgar.
Al igual que antes, las cámaras encuentran rápidamente la luz verde, convierten
sus coordenadas en una dirección 3D, y cuando detectan una "pulsación" meten la
tecla en el pipe.
Un poco más fácil fue sustituir el pipe por llamadas apropiadas a X-Window. En
particular usamos XSendEvent para engañar a fvwm2 y hacerle creer que se había
pulsado una tecla.
Para ello seguimos el ejemplo de un driver llamado Maguellan que se usa para un
HMD profesional. Ojalá pudiéramos echarle un ojo y ver cómo funciona, aunque
creemos que sólo sirve para aplicaciones desarrolladas específicamente para 3D
(como diseño de coches, aviones, ...) y no para un escritorio 3D.

Lo bueno es que ahora teníamos a un individuo en medio de la habitación cazando
mosquitos !con las dos manos!

Una vez con el prototipo en marcha nos dedicamos a modificar los programas que
queríamos usar. El escritorio estaba aceptablemente completo, pero no hay
muchas aplicaciones que permitan usar 3D. Por supuesto que modificamos un
programa para representar estadisticas en 3D con curvas y gráficos de barras.
Tambien hemos modificado XMRM-2.0 para hacer morphing en 3D, pero los cambios
han sido simplemente para probar.
Si hubiera un buen programa de diseño de arquitectura, quizás lo podriamos
adaptar.
Todavía no nos hemos atrevido a convertir juegos tales como Doom a un entorno
auténtico de 3D.

Una de las últimas mejoras ha sido el sistema de posicionamiento de la caja y
las cámaras.
En vez de poner la caja en la cabeza y las cámaras en las paredes, hemos puesto
una cámara sobre la cabeza, y dibujado marcas en las paredes formando una
rejilla.
La cámara está sobre la cabeza, apuntando en la misma dirección que los ojos.
En cada pared tenemos marcas cada 2 cm, con la etiqueta AB donde A indica la
altura desde 0 hasta 2 metros, y B indica el giro, desde 0 hasta 360-1 grados.
Los que tengan estudios habrán identificado esto con la latitud y la longitud.
-La marca más cercana al centro de la imagen capturada identifica la dirección
en la que estamos mirando.
-La marca visible más lejana determina la distancia desde la cámara hasta la
pared.
-La diferencia en pixels horizontales entre una marca y otra se usa para
averiguar la inclinación de la cabeza.
Con esto se reduce el sistema a 1 única camara, aunque hay que conectarla
mediante unos cables largos desde la cableza hasta el ordenador, lo cual
aumenta el peso que hay que llevar sobre la cabeza.
Ademas hay que elegir una cámara que tenga buena resolución a una distancia
entre 1 y 3 metros, para que identifique correctamente las marcas de la pared.
Y hay que dibujar marcas en toda la habitación. En realidad la prueba la
hicimos con post-it.

Ya que no teníamos las cámaras de la pared había que inventar otro sistema en
lugar del dedo-luz. Probamos con un puntero láser. La luz del láser que incide
sobre la pared es detectada por la cámara de la cabeza siempre que estemos
mirando en esa dirección, que suele ser lo habitual. Nadie apunta a un sitio al
que no mira.
El problema es que sabemos el punto de incidencia en la pared, pero no el
ángulo:

rayo1
\ |
\ | <-pared
\ |
\|
-------| <-punto de incidencia
rayo2

Como se ve en el esquema, tanto rayo1 como rayo2 tienen el mismo punto de
incidencia.
La posible solución es tener otra cámara en la espalda que encuentre el otro
extremo del rayo. Pero los punteros láser sólo emiten luz en una dirección, no
en los dos sentidos. Claro que podríamos poner 2 punteros de distintos colores,
separados por 45 grados. Los colocamos en un guante-luz, pero resultó ser
demasiado incomodo para manejarlo.
O bien mantener una de las cámaras de la pared. Posiblemente necesitaríamos 2
cámaras.

Como esto suponía un gran cambio con nuevas dificultades, no le dimos más
vueltas y nos quedamos con el modelo antiguo de la cabeza dentro de la caja de
colores.

Otra idea que se ha quedado por el camino ha sido la utilizacion de sonido. Si
bien creemos que ayuda a dar sensación de inmersión, apenas contribuye a la
tridimensionalidad, además de que no parece que tenga mucho que ver con un
escritorio virtual. Quizás para juegos sí que valga.
Por otro lado está el hecho de que mi amigo es sordo.

Ya que tenemos un sistema estereoscópico que muestra imágenes, hemos
implementado otro para capturar imágenes estereoscópicas. Para ello se
necesitan 2 cámaras de vídeo colocadas a la misma distancia de los ojos (8 cm.
entre cada objetivo) y el foco a 1 metro. Esto es lo más difícil de conseguir
porque la mayoría de las cámaras digitales tiene ajuste de foto automático, y
la distancia mínima suele ser 1.5 o 2 metros. Para hacerlo todavía más
espectacular grabamos vídeo y luego lo mostramos en nuestros 2 marcos. El
resultado no fue todo lo satisfactorio que esperabamos y posiblemente
necesitemos investigar sobre este asunto. Nos atrae el tema de grabar imagenes
reales y luego vectorizarlas para convertirlas en imagenes virtualizadas.
Quizás entonces podríamos superponer imágenes reales con virtuales, o
superponer información digital sobre imágenes reales, al estilo de Robocop y lo
que se ve en los aviones de combate.

Ahora trabajamos en un guante 3D. Hemos cogido un guante negro, y pintado rayas
blancas horizontales y verticales en una trama de 2 centímetros. Con 2 cámaras
de alta resolución tomamos imágenes, pasamos la rejilla a 3D, y las convertimos
a un entorno virtual.
Lo malo es que la resolución no es lo bastante buena si usamos video en tiempo
real. Y obviamente no podemos tomar fotos cada 5 segundos.
Hay un sistema que se basa en llevar un traje con puntos de colores en las
rodillas, caderas, cintura, codos, ..
Esos puntos se captan en una cámara, se transforman en 3D, y pueden saber cómo
es el movimiento de una persona.
Se usa para hacer películas de dibujos animados en las que los movimientos son
bastante humanoides.
Sin duda, un tema interesante.

También estamos haciendo un tetris en 3D. El usuario empuja con el dedo-luz los
bloques que le caen del techo, mientras que en el suelo están (virtualmente, se
entiende) los bloques apilados.

Intentaremos hacer un simulador de vuelo de estilo Superman, aunque por ahora
más bien parece Superlópez.
Hemos encontrado muchas colecciones de objetos virtuales para diseñar un mundo
virtual, aunque por ahora no le vemos utilidad para nosotros.

Segun nos han comentado, un museo de cultura egipcia ofrece paseos virtuales:
te pones unas gafas HMD y te paseas por una habitación y ves los muebles que
tenían los egipcios. Al parecer hay una silla real. Cuando la ves con las gafas
parece que tiene 3000 años, pero te puedes sentar en ella. Otra buena idea.

El objetivo de tener un escritorio virtual está cumplido. Ahora bien, tanto mi
amigo como yo somos programadores, y la herramienta que más usamos es un editor
de texto, que sinceramente no necesita de 3D. Pero tener un escritorio de
3000x3000 es agradable para programar.
Dado que estamos muy iusionados con nuestro desarrollo, cabe la posibilidad de
adquirir unas gafas reales. El punto débil de nuestro sistema es el visor
físico, y existen soluciones de calidad que solucionan este problema. Ahora
esperamos a que bajen de precio.
Mira en http://www.stereo3d.com/hmd.htm para ver una lista de los sistemas
disponibles.

Mucha más información en
http://vresources.jump-gate.com/articles/vre_articles/analyhmd/analysis.htm

Quien sabe, quizás no esté tan lejos el holodeck de StarTrek.

*EOF*

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT