-[ 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*