manual vrml 2012

227
MANUAL DE MUNDOS VIRTUALES-VRML Referencia: http://wwwdi.ujaen.es/~rsegura/igai/vrml/documentos/tema1.htm Tema 1 : Introducción a VRML 2.0 Visualizadores VRML : Es posible visualizar ficheros VRML mediante dos tipos de aplicaciones diferentes: Mediante visualizadores VRML especificos. Mediante plug-ins instalados en visualizadores HTML. La segunda de las opciones es la más común. De este modo, el Netscape Communicator 4.01 incorpora como plug-in de VRML el Cosmo Player de Silicon Graphics. Para averiguar que plug-ins se encuentran instalados en el Netscape basta con desplegar el menú Help/About plug-ins. En el caso de no disponer del Cosmo Player, se podría obtener como aplicación shareware a través de internet. Una vez obtenido el programa, se ejecutaría, instalándose automáticamente dentro del Netscape o del Explorer. Documentos VRML : Como se ha mencionado anteriormente, VRML es un lenguaje de descripción de escenas en el que cada escena se compone de un número de objetos. Los objetos pueden ser formas sólidas situados y orientados de determinada forma u elementos intangibles que afectan a la escena como

Upload: gabriel-crispin-silva

Post on 27-Oct-2015

438 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Manual Vrml 2012

MANUAL DE MUNDOS VIRTUALES-VRML    Referencia: http://wwwdi.ujaen.es/~rsegura/igai/vrml/documentos/tema1.htm

Tema 1 : Introducción a VRML 2.0

Visualizadores VRML:          Es posible visualizar ficheros VRML mediante dos tipos de aplicaciones diferentes: 

Mediante visualizadores VRML especificos. 

Mediante plug-ins instalados en visualizadores HTML.         La segunda de las opciones es la más común. De este modo, el Netscape Communicator 4.01 incorpora como plug-in de VRML el Cosmo Player de Silicon Graphics. Para averiguar que plug-ins se encuentran instalados en el Netscape basta con desplegar el menú Help/About plug-ins. 

     En el caso de no disponer del Cosmo Player, se podría obtener como aplicación shareware a través de internet. Una vez obtenido el programa, se ejecutaría, instalándose automáticamente dentro del Netscape o del Explorer. 

   

 Documentos VRML: 

       Como se ha mencionado anteriormente, VRML es un lenguaje de descripción de escenas en el que cada escena se compone de un número de objetos. Los objetos pueden ser formas sólidas situados y orientados de determinada forma u elementos intangibles que afectan a la escena como luces, sonido y  distintos puntos de vista. Para crear estos mundos de realidad virtual se utilizan ficheros de texto, cuya extensión será siempre .wrl, los cuales pueden ser desarrollados mediante cualquier editor o procesador de textos. Además existe la posibilidad de utilizar programas de diseño gráfico, los cuales generan automáticamente ficheros en formato VRML. 

Page 2: Manual Vrml 2012

     Todo documento VRML está compuesto por los siguientes elementos: 

CabeceraComentariosNodos

 

Cabecera:

     La cabecera de todo fichero VRML es siempre la misma: 

#VRML V2.0 utf8

donde VRML V2.0 indica el estándar empleado y utf8 autoriza el uso de caracteres internacionales. 

     Es importante resaltar que no debe existir ningún espacio en blanco entre el símbolo "#" y la palabra "VRML".   

Comentarios:

     En VRML un comentario se escribe en una sola línea, la cual comienza con el símbolo #. Se pueden tener tantas líneas de comentarios como se desee.   

Nodos:

     Un nodo es la estructura mínima indivisible de un fichero VRML y tiene como misión la de definir las características de un objeto o bien las relaciones entre distintos objetos. La mayoría de los nodos pueden repetirse tantas veces como sea necesario en una escena, salvo una serie de nodos especiales como los que definen la

Page 3: Manual Vrml 2012

niebla o la panorámica del mundo virtual que aparecen un sola vez. 

     Por otra parte, no todos los nodos afectan al aspecto visual del mundo. Por ejemplo, existen nodos que actúan como sensores que detectan acciones del usuario e informan de ellas a otros objetos y otros que se encargan de modelar los sonidos. 

     Los nodos a su vez contienen campos que describen propiedades. Todo campo tiene un tipo determinado y no se puede inicializar con valores de otro tipo. De este modo, cada tipo de nodo tiene una serie de valores predeterminados para todos sus campos, de forma que cuando lo utilicemos en una escena sólo debemos indicar aquellos campos que se quieran modificar. 

     Los campos pueden ser simples o campos que indiquen a vectores u otros nodos.     

 

Estilo de escritura de los programas:

VRML es un lenguaje sensible a mayúsculas y minúsculas, lo cual ha de ser tenido en cuenta a la hora de asignar nombres. 

Todos los nodos han de comenzar siempre con letra mayúscula. 

Los campos de los nodos deben comenzar siempre con letra minúscula. 

Los campos de los nodos deben comenzar siempre con letra minúscula. 

Los números se escriben en punto flotante. 

Utilizar una línea distinta para cada nodo, para cada campo

Page 4: Manual Vrml 2012

y para cada valor de cada campo.  

Indentar cada línea, según su jerarquía.  

Colocar cada símbolo de cierre en el nivel de indentación que le corresponda.  

Poner las líneas de comentario necesarias al mismo nivel que lo que se comenta.  

Poniendo nombres propios a los nodos

 

 

Un ejemplo de programa VRML sería el siguiente: 

#VRML V2.0 utf8  #Esto es una línea de comentarios  Shape{     appearance Appearance{        material Material{}     }     geometry Cylinder{         height 2.0         radius 1.5     }  }

Tema 2 : Construcción de formas primitivas

         Las formas (Shapes) son los elementos que nos permiten visualizar los objetos en los mundos VRML. La sintaxis del nodo Shape es la siguiente: 

Page 5: Manual Vrml 2012

Shape{     appearance ...     geometry ...  }

     El campo appearance especifica las propiedades en cuanto a textura, material, etc del objeto que se describe en el campo geometry. 

     Hablamos de formas primitivas cuando Shape utiliza nodos geométricos primitivos para construir una figura. Los nodos geométricos primitivos son los siguientes:   

Box            (Caja)Cone          (Cono)Cylinder     (Cilindro)Sphere      (Esfera)

       Mediante la combinación de estas formas geométricas básicas se pueden obtener otras formas de mayor complejidad. 

 

Nodo primitivo Box: 

  Sintaxis:

Box{        size anchura altura profundidad   }

Ejemplo:Box{        size 2.0 0.5 3.0   }

     Las dimensiones que se manejan en VRML son dimensiones abstractas pero lo normal es suponer que la unidad de medida es el metro. De esta forma, en el ejemplo anterior estaríamos

Page 6: Manual Vrml 2012

definiendo una caja de 2 metros de ancho, 0.5 metros de alto y 3 metros de profundidad. 

 

Nodo primitivo Cone: 

Sintaxis:

Cone{        height               altura        bottomRadius   radio_de_la_base       bottom               valor_lógico       side                    valor_lógico  }

     Mediante los campos bottom y side se indica si se desea dibujar la base y la superfice lateral respectivamente. Por defecto estos campos toman el valor TRUE, lo cual indica que se dibuja el cono completo. 

Ejemplo: 

Cone{        height  3.0        bottomRadius .75   }

   

 

Nodo primitivo Cylinder: 

 

Page 7: Manual Vrml 2012

Sintaxis:

Cylinder{        height                altura        radius                radio        bottom               valor_lógico       side                    valor_lógico       top                     valor_lógico  }

        Mediante los campos bottom, side y top se indica si se desea dibujar la base inferior,la superfice lateral y la base superior del cilindro. Por defecto estos campos toman el valor TRUE, lo cual indica que se dibuja el cilindro completo. 

Ejemplo:

Cylinder{        height 2.0        radius 1.5   }

   

 

Nodo primitivo Sphere: 

  Sintaxis:

Sphere{        radius radio   }

  Ejemplo:

Sphere{        radius 1.0   }

 

 

Page 8: Manual Vrml 2012

     Sin embargo, la definición de un nodo primitivo implica la definición de un objeto, pero no su visualización. Es por ello por lo que se han de englobar dentro de un nodo Shape, el cual determina la apariencia de estos objetos.

Ejemplo: 

#VRML V2.0 utf8

Shape{      appearance Appearance{         material Material {}      }      geometry Cylinder{         height 2.0         radius 1.5      }   }

A este fichero podríamos darle el nombre de " cilindro.wrl " .

Tema 3 : Construcción de formas de texto

   

Page 9: Manual Vrml 2012

     En los mundos virtuales será a menudo necesario utilizar textos para guiar al visitante Para ello existe un nodo específico, el nodo Text. Una de las principales características de los textos es que son planos, es decir, no tienen profundidad.    

Nodo Text: 

        Como en cualquier procesador de textos, se nos permitirá indicar el tipo de fuente, su estilo, su tamaño, el espaciado entre caracteres, justificación de los parrafos, etc.

Sintaxis:

    Text {          string ["linea_texto 1",                     "linea_texto 2",                                 .                                 .                                 .                        "linea_texto N",]

         fontStyle FontStyle {                                              family "Nombre_Fuente",                                              style "Estilo_Fuente",                                              size Tamaño_Fuente                                              spacing espaciado_entre_caracteres                                              justify "justificación_del_texto"                                            }      } 

     Como se puede apreciar el nodo Text posee dos campos:

string:

     Aquí se introduce el texto que se desea visualizar. 

fontStyle:

     Este segundo campo es opcional, de forma que si se omite, el texto tendrá el estilo de la fuente por defecto.

Page 10: Manual Vrml 2012

Siempre que aparezca este campo tomará como valor el nodo llamado FontStyle. 

   

Nodo FontStyle: 

  Sintaxis:

FontStyle {                      family "Nombre_Fuente",                      style "Estilo_Fuente",                      size Tamaño_Fuente                      spacing espaciado_entre_caracteres                      justify "justificación_del_texto"                    }  

     Los posibles valores de los campos del nodo FontStyle son los que se muestran a continuación: 

family:       Determina la fuente que se va a utilizar para el texto. Se puede escoger entre "SERIF", "SANS" o "TYPEWRITER". Obsérvese que los nombres están en mayúsculas.  

style:        Se puede escoger entre "BOLD" (negrita), "ITALIC" (cursiva), "BOTH" (negrita y cursiva) o "NONE" (tipo de letra normal).  

size:        Determina el tamaño de la fuente, pero en unidades VRML.  

spacing:        Determina la separación entre líneas, también en unidades VRML.  

Page 11: Manual Vrml 2012

justify:       Determina la justificación del texto. Puede ser "BEGIN" (Alinear a la izquierda), "MIDDLE" (centrar el texto) o "END" (Alinear a la derecha).  

Otros:       Que pensados para idiomas exóticos, como el chino (escritura en vertical), el árabe (escritura de derecha a izquierda), etc. Para la lista completa, se puede consultar la RFC 1766.  

Todos estos campos son opcionales.   

Ejemplo:

    Text {

         string ["Esta es la primera fila de texto",                       "esta es la segunda fila",                       "etc."]

         fontStyle FontStyle {                    family "SERIF",                    style "BOLD",                    size 1.0                    spacing 1.0                    justify "BEGIN"            }       }

     De igual forma que con los nodos geométricos primitivos, mediante el nodo Text lo único que se consigue es definir la estructura del texto, sin embargo no se puede visualizar, ya que no hemos indicado como se ha de presentar en el mundo virtual. Para conseguir esto, se integra en el nodo Shape, de la misma manera que se hacía con los nodos primitivos:   

Shape {  

Page 12: Manual Vrml 2012

         appearance ...            geometry Text { ... }       }

           Una vez que  el texto se encuentra en el mundo virtual se puede manipular como cualquier otro objeto (girándolo, etc.), ya que lo único que lo diferencia de los nodos primitivos es que posee dos dimensiones en lugar de tres.  

Ejemplo: 

#VRML V2.0 utf8

Shape{      appearance Appearance{         material Material {}      }      geometry Text {

         string ["Esta es la primera fila de texto",                       "esta es la segunda fila",                       "etc."]

         fontStyle FontStyle {                    family "SERIF",                    style "BOLD",                    size 1.0                    spacing 1.0                    justify  "BEGIN"                    }

    }   }

 A este fichero podríamos darle el nombre de " texto.wrl " .

Tema 4 : Agrupación de nodos   

     Hasta ahora hemos visto los objetos aisladamente. Veamos

Page 13: Manual Vrml 2012

ahora cómo podemos agruparlos para conseguir formas más complejas. Existen diversos nodos que nos permiten agrupar objetos:

Nodo GroupNodo TransformNodo SwitchNodo Billboard

   

Nodo Group: 

       El nodo Group permite unir un conjunto de nodos de forma que actúen como una entidad única, pero sin efectuar ninguna transformación en ellos. La principal característica de este tipo de grupo es que los objetos son creados todos en el mismo punto (en el centro del escenario de realidad virtual). 

Sintaxis:

    Group {           children [ ... ]      }

 

     El campo children contiene la lista de los objetos que se quieren agrupar, representados por sus nodos Shape respectivos:  

Ejemplo:

    Group {           children [                   Shape { ... },                   Shape { ... },                   ...           ]      }

Page 14: Manual Vrml 2012

    Ejemplo: 

 #VRML V2.0 utf8   #Ejemplo de agrupación de una caja y un cono

 Group {       children [           #Aquí empieza la caja:           Shape {               appearance Appearance {                   material Material {   }               }               geometry Box {                   size 2.0 0.5 3.0               }           },           #Aquí empieza el cono:           Shape {               appearance Appearance {                   material Material {   }               }               geometry Cone {                   height 3.0                   bottomRadius 0.75               }            }       ]   }

El fichero asociado a este ejemplo es "group.wrl" 

   

Nodo Transform: 

      Por defecto todos los objetos (Shapes) se construyen en el centro del escenario virtual. El nodo transform nos va a permitir evitar esto, indicando la posición, orientación y tamaño de los diferentes objetos que va a crear.  

Page 15: Manual Vrml 2012

Sintaxis:

Transform{     translation  Eje_X  Eje_Y  Eje_Z     rotation      Eje_X  Eje_Y  Eje_Z  Ángulo     scale          Eje_X  Eje_Y  Eje_Z     children[...]  } 

     Cada grupo creado mediante el nodo Transform va a poseer su propio sistema de coordenadas, cuyos atributos se determinan a través de los campos translation, rotation y scale, los cuales son optativos. 

     El campo translation permite indicar la posición del origen del nuevo sistema de coordenadas perteneciente al grupo dentro del sistema de coordenadas de nodo que lo engloba (nodo padre). A través del siguiente ejemplo esta idea quedará más clara: 

Ejemplo:

Transform{      # Ejes:         X   Y   Z      translation 2.0 0.0 0.0      children [...]  } 

     Mediante este ejemplo se consigue que el grupo creado tenga un sistema de coordenadas idéntico a sistema de coordenadas principal, con la única salvedad de que su origen se encontraría desplazado dos unidades sobre el eje X del sistema principal. También es posible apreciar en este ejemplo que sólo se han de contemplar los campos que interesen, ignorándose el resto. 

Gráficamente los pasos serían los siguientes: 

     I) Partimos del sistema de coordenadas del nodo padre: 

Page 16: Manual Vrml 2012

           II) Realizamos la translación del sistema de coordenadas del grupo: 

  

     Un ejemplo sería el siguiente: 

Page 17: Manual Vrml 2012

     El campo rotation nos permite girar el sistema de coordenadas del grupo alrededor de uno de los ejes del sistema de coordenadas del nodo padre. Para ello, además de indicar sobre que eje se desea realizar el giro, se ha de hacer referencia al grado de inclinación de dicho giro (en radianes). 

Ejemplo:

Transform{  # Ejes:    X   Y   Z    Ángulo  rotation 0.0 0.0 1.0   0.52  children [...]  } 

     Con este ejemplo se pretende hacer girar el sistema de coordenadas del grupo sobre el eje Z 0.52 radianes. Nótese que solamente uno de los ejes puede tomar un valor (que ha de ser forzosamente la unidad) mientras el resto ha de permanecer a cero. De esta forma sólo hay tres combinaciones posibles con las que rellenar los ejes del campo rotation:   

Rotación sobre el eje X

1.0 0.0 0.0

Rotación sobre el eje Y

0.0 1.0 0.0

Rotación sobre el eje Z

0.0 0.0 1.0

 

     Gráficamente los pasos serían los siguientes: 

     I) Partimos del sistema de coordenadas del nodo padre: 

Page 18: Manual Vrml 2012

     II) Realizamos la rotación del sistema de coordenadas del grupo:

 

     Un ejemplo sería el siguiente: 

     A través del campo scale podemos aumentar o reducir el tamaño de los ejes del sistema de coordenadas del grupo utilizando factores

Page 19: Manual Vrml 2012

de escala que toman como referencia los ejes de coordenadas del sistema del nodo padre. De esta forma aumentamos o disminuimos el tamaño de los objetos que se crean. 

Ejemplo:

Transform{  # Ejes:    X   Y   Z   scale      0.5 0.5 0.5  children [...]  } 

     El ejemplo anterior hace que los ejes del sistema de coordenadas del grupo sean un 50% (0.5) más pequeños que los ejes del sistema principal y por lo tanto el objeto diseñado en estos ejes reducirá su tamaño a la mitad. Si se hubiese querido que fuesen el doble de grandes, el ejemplo hubiese sido el siguiente: 

Ejemplo:

Transform{  # Ejes:    X   Y   Z   scale      2     2    2  children [...]  }

     Gráficamente los pasos serían los siguientes: 

     I) Partimos del sistema de coordenadas del nodo padre: 

 

Page 20: Manual Vrml 2012

     II) Realizamos la translación del sistema de coordenadas del grupo: 

 

     Un ejemplo sería el siguiente: 

       Por último, se muestra un ejemplo en el que se unen las diferentes modificaciones sobre el sistema de coordenadas de un grupo: 

Ejemplo:

Transform{  # Ejes:     X    Y   Z     Ángulo   translation 2.0 0.0 0.0 

Page 21: Manual Vrml 2012

rotation 0.0 0.0 1.0   0.52  scale       0.5 0.5 0.5  children [...]  }

     Gráficamente si se realizasen estas tres operaciones sobre un cilindro obtendríamos los siguiente: 

     Un ejemplo completo se encuentra en el fichero "arcos.wrl". 

   

Nodo Switch: 

       La principal característica de un nodo Switch es la de mostrar únicamente uno de los nodos hijos del nodo, el cual ha debido ser seleccionado previamente.Se pueden utilizar para conectar o desconectar los efectos de una determinada propiedad o para alternar entre propiedades diferentes. 

    El campo whichChild especifica el hijo choice que se va activar, siendo el 0 el del primer hijo. Su valor por defecto es -1, lo cual indica que ninguno de los hijos está seleccionado. 

     El campo whichChild es una entrada y por lo tanto puede ser modificado por otro nodo. 

Page 22: Manual Vrml 2012

Sintaxis:

Switch{     whichChoice 0     choice[...]      ...     choice[...]  }

 

   

Nodo Billboard: 

       El nodo Billboard permite crear un grupo con un sistema de coordenadas especiales, ya que a través del campo axisOfRotation (eje de rotación) indicamos el eje sobre el que a de girar el objeto, de forma que, siempre esté de cara al espectador: 

Page 23: Manual Vrml 2012

     Todos los hijos agrupados mediante este nodo serán visualizados. 

Sintaxis:

Billboard{      axisOfRotation  Eje_X  Eje_Y  Eje_Z      children[...]   }  

     Al igual que para el campo rotate del nodo transform, únicamente uno de los ejes puede tomar como valor la unidad, permaneciendo el resto a cero:   

Rotación sobre el eje X

1.0 0.0 0.0

Rotación sobre el eje Y

0.0 1.0 0.0

Rotación sobre el eje Z

0.0 0.0 1.0

Un ejemplo completo se encuentra en el fichero "robobill.wrl".

    Poniendo nombres propios a los nodos:         Hay una solución prevista para simplificar las repeticiones de

Page 24: Manual Vrml 2012

objetos dentro de un escenario virtual. Esta solución consiste en asignar un nombre arbitrario al nodo que se piensa repetir en el código. 

     Supongamos, por ejemplo, que se van a utilizar repetidamente en un escenario unos cilindros exactamente iguales (que podrían ser las columnas de una casa).Dichos cilindros tendrán el siguiente código:  

 Shape {        appearance Appearance {             material Material { }        }        geometry Cylinder {             height 2.0             radius 0.5        }   }

(Este es el código de un cilindro con la apariencia por defecto, de 2 unidades de alto y una base de radio 0.5)  

     Se puede definir, para el ámbito de un documento VRML, que este tipo de cilindro tenga un nombre arbitrario, por ejemplo ColumnaRepetida (o como se desee, con tal de que comience por mayúscula), de la siguiente manera:    

 DEF ColumnaRepetida Shape {        appearance Appearance {             material Material { }        }        geometry Cylinder {             height 2.0             radius 0.5        }   }

     Entonces, cada vez que se quiera usar este nodo en otra parte

Page 25: Manual Vrml 2012

del documento, basta con poner lo siguiente:

 USE ColumnaRepetida

     En el ejemplo anterior de la caja y el cono, aparece el nodo Appearance repetido. Vamos a definirlo, en la primera ocasión que se utiliza con el nombre, "PorDefecto" y la segunda vez que se usa lo invocaremos mediante el comando USE:

 #VRML V2.0 utf8   #Ejemplo de agrupación de una caja y un cono,   #haciendo uso de los comandos DEF y USE.

 Group {      children [         Shape {            appearance DEF PorDefecto Appearance {               material Material {   }            }            geometry Box {               size 2.0 0.5 3.0            }         },         Shape {            appearance USE PorDefecto            geometry Cone {               height 3.0               bottomRadius 0.75            }          }      ]   }

     En este caso concreto, la simplificación no ha sido muy grande (sólo un par de líneas menos de código), pero ha servido para ilustrar el concepto.

Tema 5 : El color de los objetos   

Page 26: Manual Vrml 2012

      Anteriormente se ha comentado que el nodo Shape contenía dos campos, appearance y geometry, de los cuales el segundo indicaba el tipo de objeto a representar y del que se ha hablado ya ampliamente. Sin embargo la misión del campo appearance apenas se ha comentado, por lo que procederemos a analizarla con más detalle en este punto. 

    El campo appearance va a permitir seleccionar el color y la textura del objeto que va a ser representado dentro del escenario virtual. Este campo toma como valor un nodo de  tipo Appearance, el cual a su vez, posee un campo denominado material que toma como valor un nodo de tipo Material.  

      El nodo Material es el que controla las propiedades del color (selección del color, del brillo, del grado de transparencia, etc.) que se van a dar al objeto.    

     Los colores que se le dan a los objetos son colores RGB, es decir, vienen dados por tres valores en coma flotante, cada uno de los cuales representa uno de los colores primarios (Red, Green, Blue ) [ Rojo,Verde y Azul]. El valor 0.0 representa la ausencia de color y el 1.0 la máxima intensidad.  

     Muchos programas de dibujo darán un valor para cada color RGB en un formato 256x256x256. Para poder utilizar estos colores en  VRML es preciso convertirlos, dividiendo cada valor por 256 y colocando el resultado en su campo correspondiente dentro del nodo Material. 

   

Nodo Material: 

       Con este nodo vamos a determinar el color y grado de transparecia de los objetos.      

Page 27: Manual Vrml 2012

Sintaxis:

Shape{      appearance Appearance{         material Material{            diffuseColor           color_RGB            emissiveColor        color_RGB            specularColor        color_RGB           ambientIntensity   valor            transparency         valor            shininess               valor         }      }      geometry ...   }

     Cada uno de los seis campos del nodo Material tiene su propio efecto específico sobre un objeto.Todos son opcionales. 

     diffuseColor:

    El campo diffuseColor representa  lo que la mayoría de los usuarios llamarían como el color del objeto. 

    emissiveColor:

     El campo emissiveColor se utiliza para fijar el color del brillo del objeto, cuando dicho objeto necesite ser visible en la oscuridad. De esta forma se consigue un efecto en donde la figura representada parece iluminada desde el interior mediante una luz de un determinado color. 

     La configuración por defecto de este campo es el negro, ya que la mayoría de los objetos normalmente no brillan. 

Page 28: Manual Vrml 2012

    specularColor:

     El campo specularColor es un parámetro avanzado que permite indicar qué color de luz refleja el objeto. Por ejemplo, una cama roja no refleja un color rojo, pero una olla rojiza  si puede reflejar su color. 

    ambientIntensity:

     Este campo es otro parámetro avanzado que indica la cantidad de luz ambiental (producida por los diferentes focos de luz del escenario virtual) es reflejada por el objeto. 

     Toma valores en coma flotante entre 0.0 y 1.0. 

    shininess:

     El campo shininess controlan el brillo de un objeto. Toma valores en coma flotante entre 0.0 y 1.0.   

    transparency:

     El campo transparency indica el nivel de transparencia del objeto. Toma valores en coma flotante entre 0.0 y 1.0, siendo el 1.0 el nivel máximo de transparencia (objeto invisible) y el 0.0 el nivel

Page 29: Manual Vrml 2012

mínimo (objeto totalmente opaco).

     El valor por defecto es el 0.0.           Los ficheros "colores1.wrl" y "colores2.wrl" contienen ejemplos completos sobre como cambiar el aspecto de los objetos.

Tema 6 : Objetos almacenados en ficheros

         Para facilitar el diseño de mundos virtuales habrá ocasiones en las que convendrá almacenar cada objeto en su propio fichero. De este modo, si por ejemplo se deseara modelar una habitación, los diferentes elementos que van a aparecer dentro de ella: paredes, puertas, mesas, sillas, etc, son objetos independientes entre si pero que se engloban dentro de un mismo espacio y, que además, pueden aparecer varias veces en el diseño de todo mundo virtual. Es por ello por lo que sería de interés crear un fichero donde almacenar el objeto mesa ("mesa.wrl"), otro fichero para el objeto silla ("silla.wrl"), etc. 

    En el fichero "comedor.wrl" se realizan llamadas tanto al fichero que contiene la silla como al que contiene la mesa.

Nodo Inline:     El nodo Inline va a permitir crear un grupo en donde los hijos, almacenados en distintos ficheros VRML, son recuperados indicando su dirección URL. 

Sintaxis:

Inline{     url"dirección_url"  }

Page 30: Manual Vrml 2012

Ejemplo:

...  Inline{     url"mesa.wrl"  },

...

Transform{     translation ...     children [       Inline{url"silla.wrl"}     ]  }  ...

Tema 7 : Adición de enlaces en el mundo virtual

   

Nodo Anchor: 

       El nodo Anchor crea un grupo especial ya que seleccionando cualquier objeto perteneciente a dicho grupo se salta hacia otro lugar del escenario virtual o hacia otro mundo virtual almacenado en un fichero VRML (al cual accedemos a través de su dirección URL). Cualquier objeto o grupo de objetos se puede convertir en un enlace. 

     Estos enlaces son los equivalentes en el mundo tridimensional a los enlaces existentes en las páginas Web realizadas mediante HTML.

     Además, todo nodo Anchor posee un campo denominado description en el que mediante una cadena de texto se describe brevemente el objeto. 

Sintaxis:

Page 31: Manual Vrml 2012

Anchor{     url"dirección_URL"     description "descripción_del_enlace"     children[...]   }

Ejemplo:

Anchor{     url"escalera.wrl"     description "Escaleras Flotantes"     children[...]   }  

     En el fichero "enlace.wrl" se muestra como crear un enlace, el cual va a tener forma de escalera. Este enlace nos llevará hasta el cilindro creado en el tema 2.

Tema 8 : Construcción de formas complejas

         Se ha visto en temas anteriores como mediante la superposición y unión de diferentes nodos geométricos básicos es posible construir objetos más complejos. Sin embargo, si la única manera de generar formas complejas fuese ésta, la construcción de mundos virtuales será bastante ardua. Es por ello por lo que aparecen una serie de nuevos nodos, los cuales, además de facilitar el diseño (al tener más control sobre ellos y al ser más flexibles), generan mundos VRML de una forma más eficiente. 

     Lo más recomendable a la hora de diseñar un objeto es describir su geometría en dos pasos aislados:  

Especificación de las coordenadasCreación de la forma geométrica

Page 32: Manual Vrml 2012

   

Especificación de las coordenadas: 

     En este paso se ha de indicar mediante el nodo Coordinate la posición de los puntos  que se van a utilizar para construir el objeto. Estos puntos no son visibles en el escenario virtual. 

   

Nodo Coordinate: 

Sintaxis:

Coordinate {          point [               Eje_x  Eje_Y  Eje_Z,               Eje_x  Eje_Y  Eje_Z,               ...               Eje_x  Eje_Y  Eje_Z          ]      }

     El campo point puede poseer varios puntos, cuyas coordenadas están separadas por comas.  

Ejemplo:

Coordinate {          point [               12.0 11.0 17.1,               20.5 13.8 5.3,               14.0 6.1 22.9          ]      }

Page 33: Manual Vrml 2012

   

Creación de la forma geométrica:     Una vez definidos los puntos que forman el esqueleto del objeto, se han de conectar. Existen tres maneras de unir estos puntos, cada una de las cuales está asociada a un nodo diferente:   

Nodo PointSetNodo IndexedLineSetNodo IndexedFaceSet

     Estos tres nodos poseen un campo denominado coord que acepta como valor un nodo Coordinate. 

 Nodo PointSet: 

       Representa un conjunto de puntos situados en las coordenadas índicadas dentro del sistema de coordenadas del nodo padre. 

Sintaxis:

PointSet {         coord Coordinate {             point [ . . . ]         }         color Color {             color [ . . . ]         }     }

Page 34: Manual Vrml 2012

"puntos.wrl"

     El campo coord  toma como valor un nodo de tipo Coordinate, el cual define los puntos que se desean representar. 

     El campo color sirve para definir el color de cada uno de los puntos. Este campo toma  como valor un nodo Color, que a su vez contiene un campo de tipo color de nuevo. Este último campo describe una lista de colores RGB, de forma que el primer color corresponde al primer punto descrito por el nodo Coordinate del campo coord ; el segundo color corresponde al segundo punto y así sucesivamente. 

Ejemplo:

PointSet {             coord Coordinate {                 point [                      12.0 11.0 17.1,  #1º punto                     20.5 13.8 5.3,   #2º punto                     14.0 6.1 22.9    #3º punto                  ]              }              color Color {                  color [                      1.0 0.0 0.0, # 1º punto rojo                      0.0 1.0 1.0, # 2º punto verde                      1.0 1.0 0.0  # 3º punto amarillo                 ]              }          }

Page 35: Manual Vrml 2012

     Si se incluyese este código, tal como está, en un documento VRML, no podríamos ver ninguno de estos puntos, ya que como se ha visto anteriormente, para crear un objeto visible se debe utilizar el nodo Shape. 

     Obsérvese que se ha prescindido del campo appearance del nodo Shape  ya que no es necesario, pues los puntos no van a tener la apariencia por defecto, sino la que se determina en el campo color.  

Ejemplo:

#VRML V2.0 utf8     #Ejemplo de un grupo de tres puntos con colores

   Shape {          geometry PointSet {             coord Coordinate {                 point [                      12.0 11.0 17.1,  #1º punto                     20.5 13.8 5.3,   #2º punto                     14.0 6.1 22.9    #3º punto                  ]              }              color Color {                  color [                      1.0 0.0 0.0, # 1º punto rojo                      0.0 1.0 1.0, # 2º punto verde                      1.0 1.0 0.0  # 3º punto amarillo                 ]              }          }     }

   

Nodo IndexedLineSet:

Page 36: Manual Vrml 2012

      Permite unir los diferentes puntos especificados en su campo coord mediante líneas poligonales. 

Sintaxis:

IndexedLineSet{       coord Coordinate {             point [ . . . ]       }      coordIndex  [...]       colorPerVertex     valor_lógico      color Color {             color [ . . . ]       }      colorIndex   [...]   }

"lineas.wlr"

     El campo coord  toma como valor un nodo de tipo Coordinate, el cual define los puntos que sirven como esqueleto de la figura. 

     El campo coordIndex se utiliza para especificar entre qué puntos se han de trazar las líneas. Una línea puede ser trazada utilizando más de dos puntos, de forma que se dibuja una línea entre el primer y el segundo punto, otra entre el segundo y el tercer punto, y así sucesivamente.Un índice con valor -1 indica que ha finalizado la línea actual y que comienza la siguiente.

     Para indicar el primer punto definido en el nodo Coordinate se

Page 37: Manual Vrml 2012

utiliza el 0, para el segundo el 1 y así sucesivamente. 

     El campo colorPerVertex indica como se han de aplicar los colores sobre las líneas:   

colorPerVertex

colorIndex Acción

FALSE  (Los colores  se aplican  sobre las  líneas)

VACIO

     Se aplican en orden los colores descritos en el nodo Color a cada una de las líneas descritas en coordIndex. Deben existir al menos tantos colores en el nodo Color como líneas haya en coorIndex. 

NO VACIO

     Este campo contiene una lista ordenada de números, los cuales representan a los colores definidos en el nodo Color. De esta forma, el 0 representará al primer color definido en el nodo Color, el 1 al segundo,etc.

     Se hace corresponder cada elemento de la lista con una de las líneas descritas en coordIndex.

     Si el mayor valor que admite el campo colorIndex es N, entonces deben existir en el nodo Color N+1 colores definidos. 

Ejemplo:

colorIndex[4,0,3,2]     De esta manera se asigna a la primera línea de coordIndex el tercer color del nodo Color, a la segunda línea el primer color,etc. 

TRUE  VACIO      Se utiliza el campo coordIndex para elegir los colores definidos en el nodo

Page 38: Manual Vrml 2012

(Los colores  se aplican  sobre los  vertices)

Color.  Si el mayor valor que admite el campo coordIndex es N, entonces deben existir en el nodo Color N+1 colores definidos. 

NO VACIO

     Se aplican los colores a cada vértice. Este campo va a tener ahora la misma estructura que el campo coordIndex, por lo que ha de contener al menos tantos índices como este último. También ha de poseer los indicadores de fin de línea (-1) en los mismos sitios que el campo coordIndex.

     Si el mayor valor que admite el campo colorIndex es N, entonces deben existir en el nodo Color N+1 colores definidos.

 

   

Nodo IndexedFaceSet: 

       Permite unir los diferentes puntos especificados en su campo coord mediante caras poligonales. 

Sintaxis:

IndexedFaceSet{       coord Coordinate {             point [ . . . ]       }      coordIndex  [...]       colorPerVertex     valor_lógico      color Color {             color [ . . . ]       }      colorIndex   [...]   }

 

Page 39: Manual Vrml 2012

"vasija.wrl"

     El campo coord  toma como valor un nodo de tipo Coordinate, el cual define los puntos que sirven como esqueleto de la figura.

     Utiliza los índices de su campo coorIndex para especificar las caras poligonales. Un índice con valor -1 indica que ha finalizado la cara actual y comienza la siguiente.

     El campo colorPerVertex indica como se han de aplicar los colores: 

colorPerVertex

colorIndex Acción

FALSE  (Los colores  se aplican  sobre las 

caras)

VACIO

     Los colores se aplican en el orden en el que se han definido dentro del nodo Color. Deben existir al menos tantos colores como caras. 

NO VACIO

     Los colores se aplican en el orden indicado por el campo colorIndex. Deben existir al menos tantos índices en este campo como caras se han definido.

     Si el mayor valor que admite el campo colorIndex es N, entonces deben existir en el nodo Color N+1 colores definidos. 

TRUE  VACIO      Se utiliza el campo coordIndex para elegir los colores definidos en el nodo

Page 40: Manual Vrml 2012

(Los colores  se aplican  sobre los  vertices)

Color.

     Si el mayor valor que admite el campo coordIndex es N, entonces deben existir en el nodo Color N+1 colores definidos. 

NO VACIO

     Se aplican los colores a cada vértice. Este campo va a tener ahora la misma estructura que el campo coordIndex, por lo que ha de contener al menos tantos índices como este último. También ha de poseer los indicadores de fin de línea (-1) en los mismos sitios que el campo coordIndex.

     Si el mayor valor que admite el campo colorIndex es N, entonces deben existir en el nodo Color N+1 colores definidos.

 

     A continuación se muestra un ejemplo de cómo se colorea una figura utilizando sus caras:

"tricaras.wrl"

     Ahora el ejemplo trata de cómo se colorea una figura utilizando sus vértices:

Page 41: Manual Vrml 2012

Tema 9 : Utilización de rejillas de elevación

   

Nodo ElevationGrid: 

      Este nodo crea una cuadrícula rectangular con alturas variables, lo que la hace especialmente útil para modelar el terreno y para la creación de otras superficies en el espacio. 

Sintaxis:

ElevationGrid{  xDimension     número_de_columnas(Eje_X)  xSpacing         valor_real  zDimension     número_de_filas(Eje_Z)  zSpacing         valor_real  height   [altura1, altura2,...,altura(numcolum x numfilas)]   color  Color[...]  colorPerVertext  }

     Los campos xDimension y zDimension especifican el número de puntos de la cuadrícula en las direcciones X y Z, definiendo una superficie que contiene un número de rectángulos igual a

Page 42: Manual Vrml 2012

(xDimension-1)*(zDimension-1). 

     Los campos xSpacing y zSpacing determinan la distancia entre los puntos de la cuadrícula en el eje X y en el eje Z respectivamente. 

     El campo height consiste en una ordenación de valores escalares que representan la altura de cada vértice sobre la cuadrícula. Los valores se almacenan de modo que la fila 0 es la primera, la fila 1 la segunda, etc. Dentro de cada fila, los valores de altura se almacenan de modo que la columna 0 es la primera, la 1 la segunda, etc. 

     El campo colorPerVertex indica como se han de aplicar los colores: 

colorPerVertex

Acción

FALSE     Los colores se aplican sobre las cuadrículas de la rejilla. Se han de definir en el nodo Colors al menos ((xDimension-1)*(zDimension-1)) colores.

TRUE     Los colores se aplican sobre los vértices  de la rejilla.Se han de definir en el nodo Colors al menos (xDimension*zDimension) colores.

Tema 10 : Utilización de texturas   

     La textura es la posibilidad que tenemos de envolver un objeto con una imágen determinada que se encuentra almacenada en un fichero, al cual accedemos mediante su URL. Los tipos de imagen que soporta VRML son:

JPEGGIFPNG

       Hasta ahora, para definir un objeto visible se ha utilizado el nodo Shape de la siguiente forma: 

Page 43: Manual Vrml 2012

Shape {        appearance Appearance {             material ...        }        geometry ...    }

en donde el nodo Appearance tiene un solo campo, material, con el que se definen el color y la transparencia, según se ha visto en temas anteriores. 

     Pero en realidad puede tener también otros dos campos: texture (cuyo valor suele ser un nodo de tipo ImageTexture o de tipo MovieTexture) y textureTransform, con los que se define la textura de los objetos:

 Shape {        appearance Appearance {             material ...             texture ImageTexture{...}             textureTransform {...}        }        geometry ...    }

   

   

Nodo ImageTexture: 

Sintaxis:

ImageTexture{       url            "direccion_URL"       repeatS     valor_lógico       repeatT    valor_lógico   }

     El campo url contiene la dirección URL del fichero gráfico que se va a usar como textura. Los formatos gráficos que admite VRML son jpeg,gig y png.  

Page 44: Manual Vrml 2012

     Las texturas  definen un conjunto de coordenadas 2D (Ejes S y T) que se emplean para trazar texturas sobre la superficie de los objetos. Las coordenadas de textura van de 0 a 1.  

     La coordenada horizontal se denominada S y la coordenada vertical T. El lado inferior de la imágen se corresponde con el eje S y el lado izquierdo con el eje T. La esquina inferior izquierda de la imagen, según este sistema de coordenadas, vendría dada por el punto (S=0,T=0) y la esquina superior derecha por (S=1,T=1). 

     Los campos repeatS y repeatT determinan como envuelve la textura en las direcciones S y T. Si repeatS es TRUE, la textura se repite (cada vez que S=1) en la dirección S hasta cubrir la superficie del objeto. Si repeatS es FALSE, la textura se adapta a toda la superficie del objeto a lo largo de la dirección S, sin tener en cuenta el valor de las coordenadas S y T. El campo repeatT haría lo mismo sobre el eje T. 

 

   

Nodo TextureTransform:

     Este nodo define una transformación 2D aplicada a las coordenadas de textura. Esto afecta a la forma en que se aplica la textura a las superficies de los objetos. La transformación consiste (por orden) en un ajuste de la escala no uniforme sobre un punto central arbitrario, una rotación sobre ese mismo punto y una translación. Esto permite al usuario modificar el tamaño, orientación y posición de las texturas de los objetos. 

Sintaxis:

TextureTransform{       center            Eje_S   Eje_T       rotation         ángulo      scale             Eje_S Eje_T  

Page 45: Manual Vrml 2012

    translation   Eje_S  Eje_T   }

       El campo center especifica un punto en el sistema de coordenadas de la textura (S,T) sobre el que los campos rotation y scale van a ser aplicados. 

     Supóngase que se comienza a trabajar a partir de la siguiente imagen:

 

     El campo scale contiene dos factores de escala, uno para el eje S y otro para el eje T de la textura. Puede tomar cualquier valor real en ambos ejes. 

Ejemplo gráfico: 

"headsca.wrl"

     El campo rotation determina la rotación en radianes de los ejes de coordenadas de la textura con respecto al punto marcado por el campo center, después de haber aplicado el campo scale. 

Page 46: Manual Vrml 2012

Ejemplo gráfico: 

"headrot.wrl"

     Por último, el campo translation provoca un desplazamiento del sistema de coordenadas de la textura.  

Ejemplo gráfico: 

"headtran.wrl"

     Es importante destacar que todas estas modificaciones aparecen invertidas cuando la textura se aplica sobre la superficie de un objeto. De esta forma si duplicásemos los ejes S y T de una textura (rotate 2 2) cuando se aplicase sobre un objeto se observaría que su tamaño se ha reducido a la mitad. De igual modo, si desplazasemos la textura 0.5 unidades con respecto al eje S (translation 0.5 0) cuando se aplicase sobre un objeto se podría apreciar que se ha desplazado -0.5 unidades con respecto a la superficie del objeto.  

Page 47: Manual Vrml 2012

 

Imágenes distintas en un mismo objeto:

     Puede interesar que un objeto tenga imágenes diferentes en alguna o algunas de sus caras,  para ello hemos de diseñar la figura de forma que cada una de sus caras sean objetos independientes. Supongamos que se desea poner una determinada textura sobre las bases de un cilindro y una textura diferente sobre la superficie lateral, los pasos a seguir serían los siguientes:   

Se define un cilindro con la textura de la base, anulando las superficies superior e inferior. 

Se define otro cilindro idéntico con otra textura,anulando la superficie lateral. 

Por medio del nodo Group  se agrupan ambos cilindros, con lo que el resultado es aparentemente un cilindro con imágenes distintas.

     En el fichero "lata.wrl" se encuentra definido un objeto creado mediante los pasos anteriormente mencionados.

MovieTexture:     En lugar de usar imágenes estáticas como textura de los objetos, se pueden utilizar videos (películas), en formato MPEG, haciendo uso del nodo MovieTexture, en vez de ImageTexture.

 

Sintaxis:MovieTexture {         url            "dirección_URL"         speed       valor_real    

Page 48: Manual Vrml 2012

    loop          valor_lógico        repeatS    valor_lógico        repeatT    valor_lógico    }

Ejemplo:Shape {         appearance Appearance {              texture MovieTexture {                  url "ejemplo.mpg"                  speed 1                  loop FALSE              }         }         geometry ...     }

     El campo url contiene la dirección URL del fichero que contiene el video. 

     El campo speed controla la velocidad (1, velocidad normal; 2 doble velocidad, etc.). Con valores negativos el video se ejecutaría hacia atrás. 

     El campo loop controla si el video funciona ininterrumpidamente (TRUE) o una sola vez (FALSE). 

     Los campos repeatS y repeatT ya se han descrito en el nodo TextureTransform.

Tema 11 : Iluminando el mundo virtual   

     La colocación de luces en un mundo virtual permite obtener un mayor grado de realismo, pudiendo convertir un misma escena virtual en un lugar cálido,en un lugar tenebroso y sombrío, etc. Además de la ambientación, también juega un importante papel a la hora de determinar que objetos visualizará el visitante con mayor claridad. Existen tres clases de fuentes de iluminacion, a cada una de las cuales se les asocia un nodo:    

Page 49: Manual Vrml 2012

Nodo PointLightNodo DirectionalLightNodo SpotLight

   

Nodo PointLight: 

       Define la posición de una luz que ilumina por igual en todas direcciones. 

Sintaxis:

PointLight{      color                        color_RGB      location                   Eje_X  Eje_Y  Eje_Z      radius                      valor_real      attenuation             coeficiente1  coeficiente2  coeficiente3      on                            valor_lógico      intensity                  valor_real      ambientIntensity    valor_real  }

Campo Accióncolor      Indica el color de luz. 

location      Determina la posición que va a ocupar el foco de luz dentro del escenario tridimensional. 

radius      Limita la zona (en metros) que va a ser iluminada. 

attenuation      Almacena tres valores que se utilizan para calcular la atenuación de la luz conforme nos alejamos del foco. El factor de atenuación viene dado por la siguiente ecuación:

1/(coef1+(coef2*radio)+ (coef3*radio*radio))

on      Indica si los campos intensity y

Page 50: Manual Vrml 2012

ambientIntensity están activos (TRUE) o no (FALSE). 

intensity      Establece la intensidad con la que la luz brilla, siendo el valor 1 la máxima intensidad y 0 la mínima. 

ambientIntensity

     Determina la luminosidad del entorno del foco.

 

   

Nodo DirectonialLight: 

       Define una fuente de luz orientable que ilumina con rayos paralelos a un determinado vector tridimensional. 

Sintaxis:

DirectionalLight{      color                        color_RGB      on                            valor_lógico      intensity                  valor_real      ambientIntensity    valor_real      direction                 Eje_X  Eje_Y  Eje_Z  }

     El campo direction contiene el vector que determina la orientación de la luz emitida dentro del espacio virtual. El resto de campos tienen la misma misión que en el nodo PointLight. 

   

Nodo SpotLight: 

       Define una fuente de luz de tipo foco, que se coloca en una

Page 51: Manual Vrml 2012

posición fija del espacio tridimensional e ilumina en forma de cono a lo largo de una dirección determinada. La intensidad de la iluminación desciende de forma exponencial según diverge el rayo de luz desde esa dirección hacia los bordes del cono.El régimen de descenso y el ángulo del cono se controlan mediante los campos beamWidth y cutOffAngle. 

Sintaxis: 

PointLight{      color                        color_RGB      location                   Eje_X  Eje_Y  Eje_Z      radius                       valor_real      attenuation             coeficiente1  coeficiente2  coeficiente3      on                            valor_lógico      intensity                  valor_real      ambientIntensity    valor_real      direction                 Eje_X  Eje_Y  Eje_Z      beamWidth             ángulo      cutOffAngle           ángulo  }

     El campo beamWidth almacena el radio (en radianes) de la base de un cono donde la luz emitida es uniforme y posee su máxima intensidad. Este cono tendría como base este campo, como altura el campo radius (orientado según el campo direction) y como vértice el punto indicado en el campo location. 

     El campo cutOffAngle almacena el radio (en radianes) de la base de un cono que contiene al cono mencionado arriba. Tiene las mismas características a excepción de su radio, el cual ha de ser mayor. Este radio determina el lugar donde la luminosidad es nula. Entre el radio almacenado en beamWidth y el almacenado en este campo, la intensidad de la luz va decreciendo conforme nos alejamos del primero de los conos.

Tema 12 : Utilización de fondos   

     La utilización de fondos en el mundo virtual, nos permite dotarlos de un cielo y de un suelo, añadiendo realismo de esta

Page 52: Manual Vrml 2012

forma a la escena que se pretende crear. Estos fondos se van a caracterizar porque siempre le van a dar al visitante la sensación de que se encuentran a una gran distancia.

     Por otra parte, su coste es menor que el uso de geometrías. Se distinguen dos tipos de fondos:

Backdrop

     Este tipo de fondo se caracteriza por definir un cielo y un suelo cuyos colores vienen dados mediante gradientes. Se realiza dentro de una esfera (Sphere).

Panorama

     Este tipo de fondo se caracteriza porque define una serie de imágenes que rodean la escena. Se realiza dentro de una caja (Box).

 

   

Nodo Background: 

       Incorpora un plano de suelo sombreado, texturas y cielo escénico. Sólo se emplea el primer nodo Background que se encuentre, debiéndose especificar en el archivo principal. 

Sintaxis:

Backgroud{      groundAngle     [ ]      groundColor     [ ]      skyAngle          [ ]      skyColor          [ ]      backUrl           "dirección_URL"      bottomURL     "dirección_URL"      frontUrl           "dirección_URL"      leftUrl              "dirección_URL"      rightUrl           "dirección_URL"      topUrl              "dirección_URL"  }

     Todos estos campos no se utilizan simultaneamente, sino que su uso dependerá del tipo de fondo que se desee crear. 

Page 53: Manual Vrml 2012

   

Backdrop 

Sintaxis:

Backgroud{      groundAngle     [ ]      groundColor     [ ]      skyAngle          [ ]      skyColor          [ ]  }

Ejemplo:

Backgroud{      groundAngle     [.785]      #                     color_RGB1,color_RGB2       groundColor     [ .14 .28 0,.09 .11 0 ]      skyAngle          [.785 ]      #                   color_RGB1,color_RGB2       skyColor          [.02 0 .26, .02 0 .65 ]  }   

     Gráficamente podríamos obtener lo siguiente: 

"backdrop.wrl"

Page 54: Manual Vrml 2012

     El fondo de tipo Backdrop se construye mediante una esfera incompleta (el suelo) inmersa dentro de otra esfera completa (el cielo), en donde el visitante se situa en el centro de ambas. Estas esferas tienen un radio infinito. 

     El campo skyColor determina el color del cielo en los distintos ángulos de la esfera que lo contiene.El primer valor de este campo determina el color del cielo en los 0.0 radianes de la esfera, es decir, el color que tiene el cielo en el lugar donde se une con el suelo. 

     El campo skyAngle es utilizado para indicar los ángulos (en radianes) en los que un nuevo color debe aparecer. El campo skyColor debe poseer N+1 colores si en skyAngle se han definido N ángulos, ya que el ángulo 0.0 (que es el que se corresponde con el cielo del horizonte) no se incluye en este último. 

     Los campos groundColor y groundAngle, son equivalentes a skyColor y skyAngle respectivamente, pero referidos a la esfera que representa el suelo. 

     Si se especifica más de un color, se interpolará el color del suelo entre los colores de 0 a 90 grados en el horizonte (plano X-Z). De forma similar se interpretan los colores del cielo, de 90 a 180 grados en la vertical (plano X-Y). 

   

Panorama 

Sintaxis:

Backgroud{      backUrl           "dirección_URL"      bottomURL     "dirección_URL"      frontUrl           "dirección_URL" 

Page 55: Manual Vrml 2012

    leftUrl              "dirección_URL"      rightUrl           "dirección_URL"      topUrl              "dirección_URL"  }

Ejemplo:

Backgroud{      backUrl           "ba_image.jpg"      bottomURL     "bo_image.jpg"      frontUrl           "f_image.jpg"      leftUrl              "l_image.jpg"      rightUrl           "r_image.jpg"      topUrl              "t_image.jpg"  }

        Gráficamente podríamos obtener lo siguiente: 

"panorama.wrl"

     El fondo de tipo Panorama consiste en seis imágenes, cada una de las cuales ocupa una de las caras de una inmensa caja centrada en el eje de coordenadas. Las imágenes que ocupan cada una de las caras vendrán determinadas por los valores de los campos backUrl, bottomUrl, frontUrl, leftUrl, rightUrl, topUrl. Todos estos campos toman como valor una dirección URL de un fichero que contiene una imágen en formato jpeg, gif o png.

Page 56: Manual Vrml 2012

Tema 13 : Utilización de niebla   

     Mediante la utilización de niebla es posible simular fenómenos atmosféricos, modificando a través de ella el aspecto de los objetos en función de la distancia a la que nos encontremos de estos.

 

Nodo Fog: 

       Este es el nodo que permite la simulación de fenómenos atmosféricos mezclando su color con el de los objetos a su alcance. 

Sintaxis:

Fog{      color                     color_RGB      fogtype                 "Tipo_niebla"      visibilityRange     valor_real  }

Ejemplo:

Fog{      color                     1  1  1      fogtype                 "LINEAR"      visibilityRange     1  }

     La niebla oscurece totalmente los objetos a través del color definido en su campo color.  

     El campo visibilityRange indica la distancia en metros a la cual los objetos no son visualizados por el visitante. La visibilidad va decreciendo desde el punto donde se encuentra el visitante hasta el límite indicado por este campo, donde la visibilidad es nula. Los objetos más cercanos se verán débilmente afectados por la niebla. 

     El campo fogType controla el grado con el que el color de la

Page 57: Manual Vrml 2012

niebla afecta al resto de los objetos. El tipo por defecto es LINEAR, lo cual indica que la función que se utiliza para ocultar los objetos es lineal. La otra opción es EXPONENTIAL, con la que se emplea una función exponencial, dando lugar a un efecto de niebla más realista.

     A continuación se muestran una serie de ejemplos para clarificar estos conceptos: 

     I) Escenario sin niebla:

"niebla0.wrl"

     II) Escenario con niebla (día):

Page 58: Manual Vrml 2012

"niebla1.wrl"

     III) Escenario con niebla (noche):

"niebla2.wrl"

Tema 14 : Niveles de detalle   

     Definir objetos con diferentes niveles de detalle va a permitir una mayor optimización del escenario virtual, ya que los objetos más lejanos al visitante se representan mediante formas más

Page 59: Manual Vrml 2012

simples de las que tendrían si se estuviese junto a ellos. Otra de sus ventajas es que se reduce el tiempo de carga del mundo VRML.     

Nodo LOD (Level Of Detail): 

       Este nodo se utiliza para permitir a los navegadores conmutar automáticamente entre varias presentaciones de objetos. Los hijos de este nodo representan generalmente el mismo objeto u objetos, a distintos niveles de detalle, que van variando desde el superior al inferior. 

Sintaxis:

LOD{  center     Eje_X  Eje_Y  Eje_Z  range      [valor1,valor2,...,valorN]  level        [Nodo1,Nodo2,...,NodoN,NodoN+1]  } 

     El campo center determina la posición que va a ocupar el objeto LOD dentro del sistema de coordenadas. 

     El campo level contiene una lista de nodos que representan a un mismo objeto con diferentes niveles de detalle, definiendose las representaciones de mayor nivel al principio de la lista y los de menor nivel de detalle al final. 

     El campo range contiene una lista de valores en orden creciente que indican a qué distancia se ha de conmutar entre una representación u otra. Para calcular esta conmutación se calcula la distancia que hay entre el visitante   y el punto central especificado del LOD; si es menor que el primer valor de la lista range entonces se dibuja el primer hijo de LOD indicado en la lista level; si está entre el primer y el segundo valor de la lista range, se dibuja el segundo hijo, y así sucesivamente. Si en la lista range figuran N valores, la lista level ha de tener N+1 hijos. 

     Cada valor del campo range debe ser menor que su predecesor, ya que de no ser así, los resultados serían indefinidos. 

Page 60: Manual Vrml 2012

     No se deben usar estos nodos para emular comportamientos, ya que los resultados pueden no coincidir con el efecto deseado. Por ejemplo, la utilización de un LOD para hacer que una puerta se abra cuando se aproxima un usuario es posible que no dé resultado en todos los navegadores.   

     Ejemplo LOD de un objeto mediante reducción del número de detalles: 

"lod1.wrl"  

     Ejemplo LOD de un objeto mediante simplificación de su geometría: 

Page 61: Manual Vrml 2012

"lod2.wrl"

Tema 15 : Control de colisiones   

Nodo Collision: 

       Indica al navegador que objetos de la escena no se van a poder atravesar. Esto permite evitar, por ejemplo, que los visitantes traspasen las paredes de un edificio. La respuesta a la colisión la define el navegador ( haciendo que se rebote en el objeto, deteniéndose simplemente, etc.). 

     Dado que es muy costoso el cálculo de una colisión  con una geometría compleja, para aumentar la eficacia se puede utilizar un método que consiste en definir una geometría alternativa que sirva como sustituto para colisiones. Esta geometría podría ser tan imperfecta como un simple cuadrado o una esfera. Este volumen alternativo se usa solamente para calcular la colisión con el visualizador. VRML ofrece volúmenes alternativos de colisión para objetos mediante el nodo  Collision. 

Sintaxis:

Collision{      collide           valor_lógico      proxy             nodo     children        [ ...] 

Page 62: Manual Vrml 2012

}         Si el valor del campo collide es FALSE entonces no se realiza colisión con la geometría afectada; si es TRUE el campo proxy define la geometría contra la que se hace la prueba de colisión.

     Si el valor de proxy no está definido o es NULL, se colisionará con la geometría real, y si no es NULL, contendrá la geometría que se emplea para calcular las colisiones.

    

Tema 16 : Utilización de sonidos   

     La adición de sonidos al escenario le añade mayor realismo. Las principales aplicaciones del sonido son: ruidos o músicas de fondo, sonidos localizados en un determinado punto del escenario (como por ejemplo el sonido de una catarata) o sonidos que se activan cuando se realiza una determinada acción (al pulsar un interruptor, saltar una pared,etc.).

     VRML utiliza dos nodos diferentes para controlar las fuentes de sonido:

Nodo AudioClipNodo Sound

Nodo AudioClip: 

       Es utilizado básicamente para cargar el fichero (en formato .wav o .mid) donde se encuentra almacenado el sonido. Se invoca el fichero a través de su dirección URL. 

Sintaxis:

AudioClip{        url                      "dirección_URL" 

Page 63: Manual Vrml 2012

    description         "descripción_del_sonido"       loop                    valor_lógico      pitch                   valor_real  }

    El campo url contiene la dirección URL del fichero que contiene el sonido, ya sea en formato .wav o .mid.  

     El campo description es una descripción textual del sonido.  

     El campo loop especifica si el sonido se ha de repetir constantemente. Por defecto, el sonido se reproduce una sola vez. Si el sonido no está en modo loop, el tiempo de reproducción viene dado por la duración del archivo.  

     El campo pitch controla el tono y la velocidad con la que se reproduce el sonido. Solo admite valores positivos. Si, por ejemplo, este campo tomase el valor 2.0, el sonido se emitiría con el doble de su velocidad normal y con un tono una octava superior al del sonido original.

 

   

Nodo Sound: 

       Define una fuente de sonido situado en un lugar especifico 3D. 

Sintaxis:

Sound{       source AudioClip{...}      intensity        valor_real      location        Eje_X  Eje_Y  Eje_Z      direction       Eje_X  Eje_Y  Eje_Z      minFront      valor_real      minBack       valor_real      maxFront     valor_real 

Page 64: Manual Vrml 2012

    maxBack      valor_real      spatialize      valor_real  }

     El campo source toma como valor un nodo de tipo AudioClip, en donde se define el fichero de sonido a reproducir. 

     El campo intensity ajusta el volumen de cada fuente de sonido.Admite únicamente valores entre 0 y 1. Una intensidad 0 es silencio y una intensidad 1, la correspondiente a la contenida en el fichero de sonido.   

     El campo location determina en el espacio tridimensional la posición del foco de sonido.  

     El campo direction especifica un vector tridimensional normal, en cuya dirección se emite el sonido. 

     Los campos minFront y  minBack determinan, junto con la dirección, la extensión de la región (hacia delante y hacia atrás respectivamente) donde la intensidad del sonido es máxima. 

     De forma similar, los campos maxFront y maxBack determinan los límites de la región a partir de la cual el sonido ya no será audible. 

     El campo spatialize determina la forma en la que se emite el sonido. Si su valor es TRUE, el sonido parecerá provenir de un único punto ("musica2.wrl"). Por el contrario, si su valor es FALSE, obtendremos un efecto envolvente, lo cual se utiliza para crear sonidos ambientales ("musica1.wrl").

Tema 17 : Descripción del mundo   

Nodo WorldInfo: 

       Contiene información sobre el mundo.  

Page 65: Manual Vrml 2012

Sintaxis:

WorldInfo{  info     [ "comentario1",                  "comentario2",                   ...                  "comentarioN"]

title    "nombre_del_mundo"  }

     El título se almacena en el campo title, permitiendo a los navegadores mostrarlo, por ejemplo, en el borde de su ventana.  

     Cualquier otra información sobre el mundo se puede almacenar en el campo info, como por ejemplo, el autor de la escena, información sobre los derechos de autor e información de dominio público.

Page 66: Manual Vrml 2012

Iluminación.

Tutorial de VRML97

Existen tres tipos de iluminación en VRML: luz direccional (node DirectionalLight), luz puntual (node PointLight) y espot de luz (node SpotLight). Cada uno de los tres tipos de luz corresponde a uno de los tres modelos clásicos de luz en gráficos per ordenador.

Iluminación Ambiente

El tratamiento de la luz ambiental es diferente en VRML respecto a otros sistemas gráficos. Es decir, tradicionalmente aquella parte de la luz que ilumina los objetos de forma indirecta, por rebotes de luz provinientes de las múltiples reflexiones y radiaciones sobre otros objetos adyacentes, es modelada mediante un único concepto llamado luz ambiental o luz ambiente. Esta luz ambiente se acostumbra a modelar mediante un valor único que representa un incremento de intensidad que se aplicará al color de los objetos, de forma uniforme. Esto es una simplificación de lo que, de otra forma, resultaría muy costoso en tiempo de cálculo.

En VRML no se dispone de un control único para simular la iluminación ambiente. En VRML disponemos de un control de emisión de luz ambiente por cada tipo de luz y un control de reflexión de luz ambiente por cada material. Es decir, que cada tipo de luz define su incremento de intensidad (que en caso de haber múltiples luces definidas, se van acumulando sus ilumiaciones ambiente sobre la intensidad de cada objeto), y por otra parte, cada material define en qué proporción se verá afectado por esa iluminación ambiente de cada luz.

En el node Material se encuentra el field ambientIntesity el cual determina en qué proporción el material refleja la intensidad ambiente de las luces definidas en el entorno. El valor de este field debe estar dentro del rango [0, 1] y su valor por defecto es 0'2.

node DirectionalLight

Con este tipo de luz podemos iluminar los objetos con rayos paralelos entre sí, como si fueran los rayos del sol al llegar a la tierra. En otras palabras, no tenemos un punto de luz

Page 67: Manual Vrml 2012

del que salen radialmente los rayos, sino que todos los rayos son paralelos entre sí y por tanto inciden con el mismo ángulo sobre una superfície. Veamos un ejuemplo:

 

Ejemplo1: Definición de una iluminación paralela que proviene de arriba a la derecha en dirección hacia abajo a la izquierda.

DirectionalLight {ambientIntensity 0.5color 1 1 1intensity 1direction -0.5 -0.5 0

}

Shape {appearance Appearance {

material Material {ambientIntensity 1diffuseColor 0 0 1

}}geometry Sphere { radius 2 }

}

Transform {translation 2 5 -5children [

Shape {appearance Appearance {

material Material {ambientIntensity 1diffuseColor 1 1 0

}}geometry Cone { bottomRadius 2 height 3 }

}]

}

En este entorno se ve claramente como la parte superior derecha de los objetos está muy iluminada por la luz direccional y en cambio la zona inferior izquierda está en sombra, solamente ligeramente iluminada por la intensidad ambiente. En este ejemplo hemos definido que la reflexión de la intensidad ambiente de los materiales sea el máximo para así poder apreciar bien la intensidad ambiente generada por la luz direccional.

Analizando el código del node DirectionalLight vemos el field ambientIntensity con un valor intermedio. Si ponemos un valor bajo, las sombras se intensifican resultando más duras o contrastadas. En cambio, si ponemos un valor elevado, las sombras quedan poco notorias y en consecuencia suaves.

Page 68: Manual Vrml 2012

El field siguiente es el field color donde definimos el color que tendrá la luz. Cabe resaltar que no es la intensidad, sino sólo el color. El color que hemos definido es totalmente blanco, como la luz del sol al mediodía. Si quisiéramos simular una puesta de sol, definiríamos una luz anaranjada (por ejemplo: RGB = [0.8 0.4 0]).

Después del color viene el field intensity donde se define la potencia con que la luz ilumina. Hemos definido el valor máximo para que se viera claramente la influencia de la luz sobre los objetos.

Finalmente, el field direction es el que determina la dirección de los rayos de luz. Lo que se debe definir es un vector director. En este caso hemos definido el [-0.5 -0.5 0] que significa que si partimos del origen de coordenadas, el rayo sale hacia abajo e izquierda con la misma proporción, pero no sale ni hacia delante ni atrás.

NOTA: Existe una luz que está encendida por defecto y que puede estorbar al hacer pruebas de iluminación. Es una luz asociada al punto de vista llamada "Headlight" y que viene a ser como una luz de casco de minero. Esta luz puede ser apagada desde el menú del browser (o en el CosmoPlayer con el asterisco "*"), pero también puede ser totalmente eliminada desde VRML con un comando especial. Nosotros hemos apagado esta luz mediante el comando en el código del ejemplo, aunque no lo hemos incluido arriba. Por lo tanto no veréis el efecto de esta luz. El comando para conseguir apagarla es: NavigationInfo { headlight FALSE }. Si quisierais saber como se vería el entorno con esta luz encendida, lo podéis hacer desde el menú del browser.

A continuación veremos un ejemplo jugando con los colores de luz.

Ejemplo2: Definición de tres luces direccionales con tres colores diferentes sobre una esfera blanca.

DirectionalLight { # Luz RojaambientIntensity 0.5color 1 0 0intensity 1direction 0.5 -0.5 -0.1

}

DirectionalLight { # Luz VerdeambientIntensity 0.5color 0 1 0intensity 1direction -0.5 -0.5 -0.1

}

DirectionalLight { # Luz AzulambientIntensity 0.5color 0 0 1intensity 1direction 0 0.5 -0.1

}

Page 69: Manual Vrml 2012

Shape {appearance Appearance {

material Material {ambientIntensity 1diffuseColor 1 1 1

}}geometry Sphere { radius 2 }

}

Con este ejemplo se puede ver la interacción entre luces distintas. Las tres luces que hemos definido son de tres colores básicos de la luz: Rojo arriba a kla izquierda, Verde arriba a la derecha y Azul abajo al centro. De este modo podemos ver la esfera iluminada uniformemente obteniendo zonas donde sólo incide una sola luz (y sólo se ve el color de esa luz), y otras zonas donde inciden más de una luz resultando el color de la mezcla de luces (por ejemplo rojo y verde forman amarillo).

node PointLight

las luces puntuales tienen la propiedad de irradiar rayos de luz en todas direcciones a partir de un punto dado en el espacio. Por esta razón no definen una dirección de iluminación. Lo que si definen es lo que se conoce como atenuación. Lo que significa es que la luz tiene una cierta fuerza que va menguando conforme nos alejamos de la fuente luminosa.

La atenuación es una propiedad física que se manifiesta debido a la pérdida de energía de los fotones al alejarse de la fuente de luz. Esta pérdida se puede modelar mediante una fórmula matemática que tiene en cuenta la distancia de la fuente de luz a un punto determinado, así como el cuadrado de esta distancia. Aquí no entraremos a ver el funcionamiento de la fórmula y solo diremos que en el node PointLight el field attenuation dispone de tres parámetros, los cuales se pueden variar para obtener diversos efectos de atenuación.

Otra propiedad de estas luces es el radio de acción. Se puede definir una distancia a partir de la cual, independientemente de la atenuación, la luz ya no actúa. Esto sirve para hacer más eficiente el render a tiempo real.

Acontinucaión damos dos pequeños ejemplos con dos tipos de atenuación distintos y un mismo radio de acción.

Ejemplo3: Definición de una luz puntual azul, sin atenuación sobre una superfície blanca.

PointLight { # Luz azul sin atenuaciónlocation 8 -3 -10

Page 70: Manual Vrml 2012

radius 15ambientIntensity 0.5color 0 0 1intensity 1attenuation 1 0 0 # Esta combinación no presenta atenuación

}

Transform {translation 0 -5 -10children Shape {

appearance Appearance {material Material {

ambientIntensity 1diffuseColor 1 1 1

}}geometry Box { size 20 1 10 }

}}

Ejemplo4: Definición de una luz puntual azul, con atenuación sobre una superfície blanca.

PointLight { # Luz azul con atenuaciónlocation 8 -3 -10radius 15ambientIntensity 0.5color 0 0 1intensity 1attenuation 1 0.5 0 # Presenta una cierta atenuación

}

Transform {translation 0 -5 -10children Shape {

appearance Appearance {material Material {

ambientIntensity 1diffuseColor 1 1 1

}}geometry Box { size 20 1 10 }

}}

Page 71: Manual Vrml 2012

node SpotLight

Este tipo de luz es el más complejo. La propiedad principal es el hecho que los rayos de luz salen de un punto determinado, en una dirección determinada. Es como una luz de teatro a la cual además de la dirección en que ilumina, también se define el ángulo de apertura del haz de luz. Veamos un ejemplo y estudiemos sus partes:

Ejemplo5: Definición de un espot de luz roja, sin atenuación sobre una superfície blanca.

SpotLight { # Spot rojolocation 0 0 -10radius 3ambientIntensity 0.5color 1 0 0intensity 1attenuation 1 0 0 # Esta combinación no presenta atenuacióndirection 0 -1 0 # apunta directamente hacia abajocutOffAngle 1.0472 # 60 grados en radianesbeamWidth 0.785398 # 45 grados en radianes

}

Transform {translation -10 -4 -15children Shape {

appearance Appearance {material Material {

ambientIntensity 1diffuseColor 1 1 1

}}geometry ElevationGrid {

colorPerVertex FALSExDimension 20zDimension 10xSpacing 1zSpacing 1height [

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

]}

}}

Page 72: Manual Vrml 2012

NOTA: En este ejemplo, en vez de un Box utilizamos una ElevationGrid como geometría para que sea más claro el efecto de punto de luz. Este nodo no lo hemos visto en el tutorial, pero no presenta ninguna complicación. Lo único que debe entenderse es que es una malla se 20x10 donde cada cuadrado de la malla tiene un teamaño de 1x1 unidades y que en realidad no son cuadrados, sino parejas de triángulos. Lo utilizamos para que el sombreado de los triángulos haga más visible la diferente intensidad que llega a cada uno de ellos.

En el ejemplo, todo es análogo al node PointLight hasta la atenuación. Lo que varía son los fields direction, cutOffAngle y beamWidth. El field direction permite dar el vector director dhaz de luz, es decir, la dirección en la que dirigimos la luz.

El field cutOffAngle nos determina el ángulo de apertura total del haz de luz (como siempre, definido en radianes). Se debe tener en cuenta que este ángulo hace referencia a la mitad de la apertura y que por lo tanto si queremos una apertura total de 60 grados, debemos especificar un field cutOffAngle de 30 grados.

El field beamWidth define un ángulo interno al field cutOffAngle donde la intensidad del haz de luz es máxima y uniforme. Entre el ángulo especificado por field beamWidth y el especificado por field cutOffAngle la intensidad del haz de luz va menguando de dentro a fuera creando una zona difuminada.

Ejercicios propuestos:Diversas luces

Definir diversos tipos de lucess iluminando objetos blancos como práctica y experimentación

Punts de Vista.

Tutorial de VRML97

En VRML97 existe la posibilidad de definir puntos de vista diversos de forma que podemos mostrar al usuario aquellas partes que nos parecen importantes del mundo que hemos definido. El usuario podrá continuar navegando con total libertad, poro si definimos una série de puntos de interes, él podrá ir diréctamente a estos sin porderse ni dudar.

node Viewpoint

La forma de definir estos puntos de vista o puntos de interes, es mediante el node Viewpoint.

Page 73: Manual Vrml 2012

Posición y OrientaciónComo siempre, veremos un ejemplo y después lo estudiaremos:

Ejemplo1: Definición de dos puntos de vista de un mundo sencillo.

Viewpoint {position 0 0 10orientation 0 0 1 0description "PVpor_Defecto"

}

Viewpoint {position 10 0 10orientation 0 1 0 0.7854 # 45 grados en radianesdescription "PV_tres_cuartos"

}

Shape {appearance Appearance { material Material { diffuseColor 1 0.6 0 }

}geometry Sphere { radius 2 }

}

Transform {translation 0 0 -8children

Shape {appearance Appearance { material Material

{ diffuseColor 0.4 0 1 } }geometry Sphere { radius 2 }

}}

Para escoger otro punto de vista, se utiliza le utilidad que el browser normalmente tiene disponible. El primer punto de vista que se define en el código, pasa a ser el punto de vista de arranque del mundo cuando se abre en un browser. (También es usual poder pasar de un punto de vista a otro con las teclas de avanzar y retroceder página del teclado).

Ahora si, examinemos las partes. El primer node Viewpoint define un punto de vista idéntico al que ya se establece por defecto al entrar al browser. Esto nos sirve para poder volver a la posición inicial sin tener que volver a cargar el entorno. Los valores por defecto son pués, situar el observador sobre el eje Z positivo a 10 unidades del origen y mirando en dirección del eje Z negativo.

La forma en que funciona el field orientation es bastante incómoda ya que no utiliza el modelo conocido como "look at" ("mira a..") sino que utiliza un vector como eje de rotación y un ángulo de rotación para desviar el vector director por defecto de la cámara: el [0 0 -1]. En el caso del punto de vista por defecto, el eje de rotación definido (los tres primeros valores del field orientation), es el eje Z. pero esto en realidad es indiferente ya

Page 74: Manual Vrml 2012

que el àngulo de rotación (el último valor del field orientation) es, de hecho, cero grados. Por lo tanto no hay desviación.

En el segundo punto de vista se entenderán mejor los conceptos. Aquí definimos la posición del observador a 10 unidades positivas en el eje X y 10 unidades positivas en el eje Z. Lo que queremos conseguir es una vista tres cuartos de escena y por lo tanto queremos mirar en dirección al origen de coordenadas. Para hacer esto, debemos desviar el vector director por defecto de la cámara, que es el [0 0 -1], es decir, el que mira en la dirección del eje Z negativo. Para desviarlo hacia el origen debemos rotar 45 grados respecto al eje Y (local del punto de vista), tal y com muestra la figura:

Angulo de Visión

Así como en una cámara se puede cambiar la lente para tener un ángulo de visión más o menos amplio, el modelo de punto de vista de VRML97 permite variar este ángulo de visión. El ángulo que se varía es el horitzontal y el vertical se adapta automáticamente según las proporciones de la ventana del browser. Veamos un ejemplo con tres puntos de vista simulando tres tipos de lentes:

Ejemplo2: Definición de tres puntos de vista de un mundo sencillo.

Viewpoint {fieldOfView 2.618description "Gran_Angular"

}

Viewpoint {fieldOfView 1.3962667description "80mm"

Page 75: Manual Vrml 2012

}

Viewpoint {fieldOfView 0.31416description "Telefoto"

}

Shape {appearance Appearance { material Material { diffuseColor 1 0.6 0 }

}geometry Box { size 30 10 2 }

}

Shape {appearance Appearance { material Material { diffuseColor 0.3 0 1 }

}geometry Box { size 8 5 5 }

}

Shape {appearance Appearance { material Material { diffuseColor 0 1 0.5 }

}geometry Box { size 1 1 8 }

}

Hace falta tener claro que al cambiar de punto de vista, la posición del observador no se modifica, es decir, el observador no se mueve ni hacia delante ni atrás, sio que es como si tuviese un zoom el cual utiliza para ampliar o reducir lo que cae en su rango de visión.

Paso de un punto de vista a otro

Otra propiedad de los puntos de vista es la de pasar de uno a otro de forma suave o saltando directamente . Trabajando con el Cosmo Player (y en general con todos los browsers) el paso de uno a otro de manera suave es la forma por defecto. Si se desea saltar de golpe, debemos modificar el field jump y ponerlo a TRUE. Si de manera explícita se quiere saltar de manera suave, debemos modificar el field jump y ponerlo a FALSE.

Prototipos, DEF y USE.

Tutorial de VRML97

PROTO

Cuando se modelan objetos para un entorno, nos podemos encontrar que necesitemos definir un tipo de objeto que será utilizado de formas diferentes en diferentes sitios del

Page 76: Manual Vrml 2012

entorno. Para poder definir un objeto genérico y poder utilizarlo con parámetros diferentes en diferentes lugares, VRML97 dispone de los prototipos.

Debe quedar claro que PROTO no es un node de VRML97, sino un mecanismo para definir nuevos nodes. Lo que se hace al definir un prototipo, es definir un tipo de objeto nuevo para poderlo utilizar de la misma forma en que utilizamos los node Box, node Sphere, node Material, node Appearance, etc. Veamos un ejemplo para entender las diferentes partes.

Ejemplo1: Definición de un prototipo de Paraguas. Se define el nuevo tipo de node Paraguas.

PROTO Paraguas [field SFColor colorBaston 0.1 0.1 0field SFColor colorTela 0 0.2 1

]{

Group {children [

Shape {geometry Cylinder { height 3 radius 0.1 }appearance Appearance { material Material {

diffuseColor IS colorBaston } }}Transform {

translation 0 1.75 0children Shape {

geometry Cone { height 0.5 bottomRadius 3 }

appearance Appearance { material Material { diffuseColor IS colorTela } }

}}

]}

}

Paraguas { } #Creamos un objeto Paraguas con los valores por defecto

Transform {translation 8 0 0children Paraguas { colorBaston 0.2 0 0 colorTela 0 0.2 0.1 }

}

Transform {translation -8 0 0children Paraguas { colorBaston 0 0 0.3 colorTela 0.4 0 0.1 }

}

Analicemos el ejemplo. Comenzamos definiendo el prototipo con la palabra clave PROTO. A continuación damos el nombre que deseamos que tenga el nuevo tipo de node que

Page 77: Manual Vrml 2012

definimos, en este caso Paraguas. Entonces debemos definir los parámetros que podremos variar de nuestro prototipo cada vez que necesitemos uno. Nosotros hemos decidido que para el paraguas podremos variar el color de sus piezas pero no podremos variar sus medidas. Para esto definimos dos fields, uno para el color del bastón field SFColor colorBaston y otro para el color de la tela que sirve de tela field SFColor colorTela. Como ambos son colores, los hemos definido de tipo SFColor (single-valued field color, campo de color univaluado). A cada uno le damos el color por defecto porque si alguien define un objeto de tipo Paraguas y no le da valores a los parámetros, el VRML97 tinga unos colores para utilizar. Ahora ya podemos definir como serán las características generales de nuestro nuevo node Paraguas.

Para empezar, utilizamos un nuevo node que es el node Group. Este node sirve para agrupar en un solo objeto, varios subobjetos. Este node nos agrupará el objeto bastón y el objeto tela de nuestro paraguas. Si no los agrupásemos y definiésemos el objeto bastón y a continuación el objeto tela, el prototipo estaría formado por un bastón visible y una tela invisible. En la definición de un prototipo se pueden poner tantos objetos com se quiera, pero siempre se tomará el primero para determinar el tipo de node que se está definiendo y para visualizarlo. El resto de objetos pueden servir para muchas cosas, pero no serán visualizados.

Así pués, definimos un cilindro que nos hará de bastón. Como se puede observar, la geometría del cilindro está fijada. En cambio, la apariencia es lo que deseamos poder variar. Por lo tanto, definimos una apariencia con un material y con un color. La forma de conseguir que el color sea el que nosotros deseamos al definir un paraguas concreto, es utilizando la palabra clave IS. Esta palabra hace que podamos definir que el field diffuseColor de nuestro objeto sea en realidad (IS) el field colorBaston que hemos definido en los parámetros. De forma análoga se define la parte de la tela que definimos mediante un cono trasladado hacia arriba para que encaje bien con el bastón.

Hasta aquí hemos definido el prototipo y como tal, no es un objeto que exista. Si no pusiéramos nada más en el archivo de VRML97, y lo cargásemos en un browser, obtendríamos una escena vacía. Esto es por qué un PROTO es tan solo un molde del cual queremos sacar objetos concretos. Para esto lo que hacemos a continuación es lo que se llama instanciar un objeto a partir del prototipo. Por el solo hecho de poner el nombre del nuevo node Paraguas, ya estamos creando una instancia del prototipo. Como en este primer caso tan solo ponemos unas llaves vacías ({}), no estamos definiendo parámetros para este objeto en concreto. En este caso se utilizan los parámetros por defecto que havíamos establecido dentro del prototipo.

Las otras dos instanciaciones, se hacen trasladando el paraguas a un lado y otro del primero, y dando colores diferentes de los colores por defecto. Debe quedar claro que al instanciar los tres paraguas obtenemos tres objetos diferenciados y que si modificamos uno los otros no se verán alterados.

A continuación mostramos un ejemplo más complejo:

Page 78: Manual Vrml 2012

Ejemplo2: Definición de un prototipo de banquillo. Se define el nuevo tipo de node Banquillo.

PROTO Banquillo [field SFColor colorPatas 1 1 0field SFColor colorAsiento 0 0 1field SFVec3f proporciones 1 1 1field SFVec3f posicion 0 0 0

]{

PROTO Pata [field SFColor colorPata 1 1 0field SFVec3f posicion 0 0 0

]{

Transform {translation IS posicionchildren Shape {

geometry Cylinder { radius 0.1 height 1 }appearance Appearance { material Material {

diffuseColor IS colorPata } }}

}}

Transform {translation IS posicionscale IS proporcioneschildren [

Shape { # Asientogeometry Box { size 1 0.2 1 }appearance Appearance { material Material {

diffuseColor IS colorAsiento } }}Pata { posicion 0.4 -0.6 0.4 colorPata IS

colorPatas }Pata { posicion -0.4 -0.6 0.4 colorPata IS

colorPatas }Pata { posicion -0.4 -0.6 -0.4 colorPata IS

colorPatas }Pata { posicion 0.4 -0.6 -0.4 colorPata IS

colorPatas }]

}

}

Banquillo { } #Creamos un objeto Banquillo con los valores por defectoBanquillo { colorPatas 1 0.5 0 colorAsiento 0.5 0 1 posicion -2 0 0 }Banquillo { colorPatas 0.5 1 0 colorAsiento 1 0.5 0 posicion 2 0 0 }Banquillo { colorPatas 1 0 0.8 colorAsiento 1 0.5 0 posicion 0 2 0 proporciones 3 1 1 }

Page 79: Manual Vrml 2012

En este ejemplo vemos un prototipo de banquillo que se ayuda de otro prototipo de pata para definir sus cuatro patas. Recordad que PROTO no es un node y por lo tanto, aunque sea lo primero que se define dentro del PROTO Banquillo, no se toma en cuenta y lo que define al prototipo externo es el node Transform que engloba las piezas del banquillo.

Cabe resaltar como los nombres de los fields no se solapan entre el PROTO padre y el hijo. Es decir, que por ejemplo, podemos tener como field el nombre posicion tanto en uno com en el otro, y se sabe perfectamente a quien se está haciendo referencia en cada momento debido al ámbito donde se encuentra.

DEF y USE

Cuando queremos definir un objeto que se utiliza en muchos sitios y nos satura el código por el hecho de repetir y repetir un mismo bloque de código, entonces podemos utilizar DEF y USE. No debemos confundir estos dos comandos con PROTO. DEF y USE no definen un objeto genérico que se instancía como objeto particular al llamarlo con unos ciertos parámetros. Lo que estos dos nuevos comandos permiten es dar nombre a un cierto nodo que posteriormente utilizaremos con la misma estructura y definición en diversos sitios. Veamos un ejemplo:

Ejemplo3: Utilización de DEF y USE.

DEF MiRojo Appearance {material Material {

diffuseColor 0.8 0.2 0.4}

}

Transform {translation -2 0 0children Shape {

geometry Box { size 3 3 3 }appearance USE MiRojo

}}Transform {

translation 2 0 0children Shape {

geometry Sphere { radius 2 }appearance USE MiRojo

}}

Aquí vemos como hemos DEFinido una apariencia que después USEmos en dos objetos diferentes. Lo que hemos hecho en realidad es sencillamente darle el nombre MiRojo a un trozo de código para después ahorrarnos el escribirlo muchas veces. Y quizás aún más importante que el ahorro en escritura, es la gran ayuda que supone cuando decidimos variar la definición de color de MiRojo, ya que si tenemos la difinición de color repetida en

Page 80: Manual Vrml 2012

distintos lugares, es necesario encontrar todas las repeticiones y modificar cada una de ellas, en cambio si está DEFinido tan solo lo tenemos que variar en este sitio y automáticamente se nos modifica en todos los lugares donde lo USEamos.

Por ejemplo, si queremos que nuestro color MiRojo en relidad sea más rojo solo tenemos que variar su DEFinición:

Ejemplo4: Modificamos ejemplo anterior.

DEF MiRojo Appearance {material Material {

diffuseColor 1 0.2 0}

}

Transform {translation -2 0 0children Shape {

geometry Box { size 3 3 3 }appearance USE MiRojo

}}Transform {

translation 2 0 0children Shape {

geometry Sphere { radius 2 }appearance USE MiRojo

}}

Page 81: Manual Vrml 2012

Ejercicios propuestos:Rueda de Coche

Definid un prototipo de rueda de coche que pueda ser situada donde se quiera en el espacio 3D, que se pueda orientar y que pueda girar sobre su eje como si rodase en el suelo. Una vez definido, construir un "coche" con las cuatro ruedas, donde las dos delanteras estén orientadas como si el coche girase a la izquierda.

Comentarios

Utilizar tan solo primitivas para modelar los objetos. Utilizar transformaciones individuales para cada característica.

Solución propuesta: roda.wrl.

Materiales II.

Tutorial de VRML97

Ya hemos visto una introducción a los materiales en el módulo Primitivas y Materiales I. Allí hemos visto como tratar con el color básico de los objetos, es decir el color difuso. Ahora veremos otras propiedades de color y de textura que se pueden definir en los objetos en VRML.

Materiales Brillantes

El node Material tiene dos fields para poder controlar las características de brillantez de un material. Estos fields son field specularColor y field shininess. El primero define el color que presenta un objeto al reflejar especularmente la luz. El segundo determina que tan definido o borroso es el reflejo especular.

Veamos un ejemplo donde aparecen cuatro esferas cada una con unos parámetros diferentes:

Ejemplo1: Definición de cuatro materiales especulares.

Shape { # Objeto de referencía con material mate.geometry Sphere { radius 1.5 }appearance Appearance {

material Material {

Page 82: Manual Vrml 2012

diffuseColor 0.5 0.5 0.5}

}}Transform {

translation -2 2 0children Shape {

geometry Sphere { radius 1.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5specularColor 1 0 0shininess 0

}}

}}Transform {

translation 2 2 0children Shape {

geometry Sphere { radius 1.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5specularColor 1 0 0shininess 0.05

}}

}}Transform {

translation -2 -2 0children Shape {

geometry Sphere { radius 1.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5specularColor 1 0 0shininess 0.3

}}

}}Transform {

translation 2 -2 0children Shape {

geometry Sphere { radius 1.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5specularColor 1 0 0shininess 1

}}

}}

Page 83: Manual Vrml 2012

La primera esfera (la que queda al centro del conjunto), no tiene definido un material especular para tener una referencia respecto a los otros.

Materiales Autoiluminados

Cuando se desea definir un material para emular que emite luz, como por ejemplo un fluorescente, se puede utilizar el field emissiveColor. Con este field se puede definir el color que emite el material sin necesidad de que haya una fuente de luz que ilumine.

Ejemplo2: Definición de materiales autoiluminados.

Transform {translation -1.5 0 0children Shape {

geometry Cylinder { radius 0.2 height 8 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5

}}

}}Transform {

translation -0.5 0 0children Shape {

geometry Cylinder { radius 0.2 height 8 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5emissiveColor 1 1 1

}}

}}Transform {

translation 0.5 0 0children Shape {

geometry Cylinder { radius 0.2 height 8 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5emissiveColor 1 1 0

}}

}}Transform {

translation 1.5 0 0children Shape {

geometry Cylinder { radius 0.2 height 8 }

Page 84: Manual Vrml 2012

appearance Appearance {material Material {

diffuseColor 0.5 0.5 0.5emissiveColor 0.6 1 1

}}

}}

Materiales Transparentes

La transparencia es otra propiedad a poder modificar mediante un field de material. El field transparency nos permite dar el grado de transparencia del material en el rango [0 1].

Ejemplo3: Definición de materiales transparentes.

Transform { # Objeto de fondo para referencia translation 0 0 -2

children Shape {geometry Box { size 10 10 0.5 }appearance Appearance {

material Material {diffuseColor 0 0 1

}}

}}Transform {

translation -3.75 0 0children Shape {

geometry Box { size 2 4 0.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5transparency 0

}}

}}Transform {

translation -1.25 0 0children Shape {

geometry Box { size 2 4 0.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5transparency 0.33

}}

}

Page 85: Manual Vrml 2012

}Transform {

translation 1.25 0 0children Shape {

geometry Box { size 2 4 0.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5transparency 0.66

}}

}}Transform {

translation 3.75 0 0children Shape {

geometry Box { size 2 4 0.5 }appearance Appearance {

material Material {diffuseColor 0.5 0.5 0.5transparency 0.9

}}

}}

Texturas

El texturado de objetos no se hace mediante el node Material dentro de la apariencia, sino que se utiliza otro field del node Appearance: el field texture. En este field se pueden insertar tres nodes posibles: node ImageTexture, node MovieTexture o node PixelTexture. Aquí tan solo veremos el primero.

node ImageTexture

En este node se define el URL (es decir, la dirección) de la imagen que ha de servir como textura. La especificación del VRML97 dice que los formatos estándares son el JPEG y el PNG, pero recomienda que también se acepte el GIF incluyendo transparencia . Veamos un ejemplo:

Ejemplo4: Aplicación de una textura a un cubo.

Transform {translation -2 0 0children Shape {

geometry Box { size 3 3 3 }appearance Appearance {

Page 86: Manual Vrml 2012

texture ImageTexture {url "teapot.gif"

}}

}}

Transform {translation 2 0 0children Shape {

geometry Box { size 3 3 3 }appearance Appearance {

material Material {diffuseColor 1 1 1

}texture ImageTexture {

url "teapot.gif"}

}}

}

El cubo de la izquierda (el primero que definimos), tan solo tiene el field texture definido. Esto causa que el cubo no sea iluminado por ninguna de las fuentes de luz del entorno y resta con los colores originales de la textura. En cambio, el de la derecha, también tiene definido el field appearance con un color difuso. Esto provoca que si sea iluminado por las fuentes de luz del entorno. Probad de apagar el headlight desde el menú de opciones y mirad la diferencia entre uno y otro.

El siguiente ejemplo muestra como queda aplicada la textura sobre cada una de las primitivas:

Ejemplo5: Aplicación de una textura a las primitivas.

DEF Textura Appearance {material Material {

diffuseColor 1 1 1}texture ImageTexture {

url "teapot.gif"}

}

Transform {translation -2 2 0children Shape {

geometry Box { size 3 3 3 }appearance USE Textura

}}

Page 87: Manual Vrml 2012

Transform {translation 2 2 0children Shape {

geometry Sphere { radius 1.5 }appearance USE Textura

}}Transform {

translation -2 -2 0children Shape {

geometry Cone { height 3 bottomRadius 1.5 }appearance USE Textura

}}

Transform {translation 2 -2 0children Shape {

geometry Cylinder { height 3 radius 1.5 }appearance USE Textura

}}

Para poder variar el tamaño y colocación de la textura sobre el objeto, se puede usar el field textureTransform de aparencia. En este field, se debe utilizar el node TextureTransform que permite escalar, rotar y trasladar la textura.

Ejemplo6: Modificación de una textura en un cubo.

Shape {geometry Box { size 3 3 3 }appearance Appearance {

material Material {diffuseColor 1 1 1

}texture ImageTexture {

url "teapot.gif"}textureTransform TextureTransform {

scale 2 2rotation 1.5708 # PI/2

}}

}

Debemos tener en cuenta que lo que estamos haciendo es escalando, rotando y trasladando las coordenadas de textura y no la textura en si misma, por lo tanto un escalado de [2 2] no la amplía al doble, sino que la reduce a la mitad (y por eso se repite), y una rotación de PI/2 no rota la textura PI/2, sino -PI/2, etc.

Page 88: Manual Vrml 2012

A continuación podeis ver un ejemplo con una textura GIF con transparencia . Esto es útil para texturar polígonos con imágenes de objetos los cuales serían complejos de modelar con geometría , como por ejemplo árboles (lo veremos más adelanteen el módulo Billboarding).

Ejemplo7: Cubo con textura GIF con transparencia .

Transform { # Fondo de referencia translation 0 0 -5

children Shape {geometry Box { size 10 10 0.2 }appearance Appearance {

material Material {diffuseColor 0.2 0.8 0.4

}}

}}Shape {

geometry Box { size 4 2 4 }appearance Appearance {

material Material {diffuseColor 1 1 1

}texture ImageTexture {

url "teapot2.gif"}

}}

Ejercicios propuestos:Diversas Transformaciones de Textura

Hacer pruebas con diversos tipos de transformaciones sobre las coordenadas de textura como práctica y experimentación.

"Billboarding" y Colisiones.

Tutorial de VRML97

Page 89: Manual Vrml 2012

"Billboarding"

Esta técnica se utiliza mucho en gráficos 3D a tiempo real para representar objetos que tendrían una geometria muy compleja si fueran modelados en polígonos. Lo que se hace es texturar un solo polígono con la textura del objeto en cuestión y se le da la propiedad de "billboard" o "valla publicitaria", con la cual se consigue que el polígono siempre esté encarado hacia el observador. Con esto se consigue que nunca se descubra el "truco" porque el usuario nunca verá el polígono de perfil. En VRML97 esto se consigue mediante el node Billboard. Veamos un ejemplo:

Ejemplo1: Definición de un arbol mediante un billboard.

Billboard {axisOfRotation 0 1 0children Shape {

geometry IndexedFaceSet {coord Coordinate {

point [ 2 3 0, -2 3 0, -2 -3 0, 2 -3 0 ]}coordIndex [ 0 1 2 3 ]solid FALSEtexCoord TextureCoordinate {

point [ 1 1, 0 1, 0 0, 1 0 ]}

}appearance Appearance {

texture ImageTexture {url "redwood.gif"

}}

}}

Lo que definimos es un polígono con las proporciones de nuestra textura de arbol (para que no se deforme), le aplicamos la textura del arbol con transparencia en las zonas que no son arbol, y lo definimos como hijo del node Billboard. El otro dato que debemos definir es el eje de rotación respecto al cual ha de pivotar nuestro polígono.

Como el eje que hemos definido es el Y, entonces sólo nos seguirá si nos movemos en un plano perpedicular a este eje. Si nos movemos hacia arriba o abajo, podemos perder el efecto deseado.

Colisiones

La deteccióa de colisiones puede ser muy importante en algunos casos y el VRML97 permite una detección parcial. Parcial en el sentido que tan solo da mecanismos para detectar colisiones entre el observador (punto de vista virtual) y los objetos, pero no entre objetos.

Page 90: Manual Vrml 2012

El mecanismo para activar y desactivar la detección de colisiones funciona a partir de un nodo de agrupación: el node Collision. Este se utiliza de manera que agrupa una lista de objetos los cuales no se desea que el observador pueda atravesar. Veamos un ejemplo:

Ejemplo2: Definición de un grupo de colisión.

Collision {collide FALSEchildren [

Transform {translation -3 0 0children Shape {

geometry Box { size 2 2 2 }appearance Appearance { material Material {

diffuseColor 1 0 0 } }}

}]

}

Collision {collide TRUEchildren [

Shape {geometry Sphere { radius 1 }appearance Appearance { material Material

{ diffuseColor 0 1 0 } }}Transform {

translation 3 0 0children Shape {

geometry Cone { height 1 bottomRadius 1 }appearance Appearance { material Material {

diffuseColor 0 0.5 1 } }}

}]

}

En este ejemplo, el observador puede atravesar el cubo pero en cambio no puede atravesar ni la esfera ni el cono. Como se puede apreciar, ponemos el cubo dentro del grupo de colisión con la propiedad de colisión FALSE. Esto lo hacemos porqué la especificación del VRML97 dice que los browsers, por defecto, habrán de detectar colisiones con todos aquellos objetos en que no se haya definido el comportamiento explícitamente.

Page 91: Manual Vrml 2012

Ejercicios propuestos:Bosque

Diseñar un Bosque con arboles hechos de billboard.

Comentarios

Utilizar el prototipage de objetos.

Solución propuesta: bosc.wrl.

Eventos II y las Rutas.

Tutorial de VRML97

Aunque ya se ha visto una introducción a los eventos en el módulo Nodos, Campos y Eventos, en este módulo aclararemos los conceptos que hay detrás.

Eventos (Events)

Un evento es como un mensage que puedeser enviado por un objeto y capturado por otro. Pueden haber eventos indicando que un nodo ha cambiado de posición, o que ha pasado de un estado inactivo a uno activo, o que ha pasado un fracción de tiempo, etc.

En teoría, los browsers tienen un reloj interno que va marcando en tiempo real el paso del tiempo. Los eventos se van produciendo y recibiendo a cada intervalo de tiempo del reloj (en teoría de forma contínua), pero en la práctica, normalmente podemos asumir que los browsers marcan el paso del tiempo a cada frame (cuadro o imagen) generado gráficamente. Así pues, cada evento tiene una especie de sello de tiempo, del instante en que se ha generado (emitido, enviado).

Evidentemente, un evento es emitido por un eventOut y debe ser recibido por un eventIn. Pero también puede ocurrir que un evento sea emitido o recibido por un exposedField que como recordareis són fields de entrada y salida.

Como es de suponer, tanto el evento que envía como el que recibe, han de ser del mismo tipo. por lo tanto, un evento enviado por un eventOut de tipo SFInt32 (entero 32 bits univaluado) sólo puede ser recibido por un eventIn (o exposedField) de tipo SFInt32.

La figura siguiente muestra el diagrama de flujo del sistema que hemos descrito.

Page 92: Manual Vrml 2012

Puede ocurrir que un objeto (nodo) reciba un evento el cual le fuerce a enviar uno él mismo. En este caso, se genera lo que se conoce por cascada de eventos. En una cascada de eventos, todos los eventos implicados tienen el mismo sello de tiempo.

¿Pero que pasa si se genera un "loop" (lazo o bucle)? Podria pasar que nunca se acabase de enviar eventos y en consecuencia no avanzase el tiempo. Este problema no puede ocurrir en VRML97 ya que no se permite que un nodo reciba en un eventIn un evento proviniente de un mismo sitio con el mismo sello temporal. Si se detecta un loop, entonces el VRML97 se encarga de convertir el sello temporal del instante ti al ti+1 y retardar su emisión.

Se permite que un eventOut pueda ser encaminado hacia múltiples eventIns, y esto se conoce como Fan Out ("abanico de apertura"). En cambio no es legal encaminar múltiples eventOuts a un solo eventIn, donde esto es conocido como Fan In ("abanico de entrada"). Si se produce un Fan In, se pueden obtener resultados no esperados e indefinidos.

Routing de valores (comando ROUTE)

¿Pero como podemos decir que un cierto eventOut debe estar enlazado a un cierto eventIn? Para esto, el VRML97 provée un mecanismo llamado rutas, el cual se consigue a través del

Page 93: Manual Vrml 2012

comando ROUTE. (Debe resaltarse que no es un nodo, si no tan solo un comando que aporta un mecanismo).

Por ejemplo supongamos que, de alguna forma, el color de un material cambia y queremos que el evento (que es de tipo SFColor) lo reciba una luz direccional, modificando así el color de la luz. Entonces los nodos y la ruta en cuestión serían:

Ejemplo1: ROUTE para modificar el color de una luz direccional en función del cambio del color de un material.

Shape {geometry Sphere { radius 2 }appearance Appearance {

material DEF MaterialEsfera Material { diffuseColor 1 0 0 }

}}

DEF Luz DirectionalLight {color 1 1 1direction 0.5 0.5 0intensity 1

}

ROUTE MaterialEsfera.diffuseColor TO Luz.color

Como vemos, hemos de asignar un nombre a los nodos que queremos enlazar para poderlos referenciar. Una vez DEFinidos los nombres, podemos establecer el enlace con el ROUTE.

El ROUTE nos dice que los eventos emitidos por el exposedField diffuseColor del Material MaterialEsfera han de ser encaminados a (TO) el exposedField color del DirectionalLight Luz.

Como se puede observar, la forma de decir que eventIn, eventOut o exposedField es el que nos interesa tratar de un cierto nodo, es mediante un punto (.) que une el nombre del nodo al del campo (field)seleccionado.

NOTA: Este ejemplo, tal y como está, no tendría ningún efecto, ya que no hay nada que pueda hacer que el material envíe un evento a la luz. En el siguiente módulo veremos ejemplos plenamente funcionales.

Interpoladores y el Sensor de Tiempo

Tutorial de VRML97

Page 94: Manual Vrml 2012

Sensor de Tiempo

En VRML97 disponemos de una herramienta muy potente, el Sensor de Tiempo ( TimeSensor). Este es un reloj que podemos utilizar a nuestro antojo para poder aprovechar el paso del tiempo como motor para mover objetos, cambiar color de objetos, variar orientaciones, etc.

Imaginemos que queremos que un objeto gire alrededor de uno de sus ejes conforme va pasando el tiempo. Tenemos un reloj que a cada "tic-tac" podemos definir que nos ayude a variar alguna cosa de nuestro entorno con una cierta frecuencia. Si de algún modo pudiéramos redirigir el paso del tiempo, que ha ocurrido en el reloj, para poder variar la rotación de un objeto, ya lo tendríamos solucionado.

Un TimeSensor se basa en el reloj real de sistema, midiendo el tiempo actual en segundos transcurridos a partir de las 00:00 horas del 1º de Enero del 1970.

Veamis algunos ejemplos de TimeSensor con efectos distintos:

Ejemplo1: Se inicia y realiza un ciclo de 5 segundos.

DEF Infinit TimeSensor{startTime 0cycleInterval 5

}

Este TimeSensor se inicia al cargarse el entorno en el visualizador y se para al cabo de 5 segundos. Un TimeSensor da constantemente, como evento de salida (eventOut), la fracción de ciclo que ha transcurrido. Esto lo hace mediante el eventOut SFFloat fraction_changed que es un valor entre 0.0 y 1.0. La duración del ciclo se define en segundos en el exposedField SFTime cycleInterval que en este caso hemos definido a 5 segundos. Es decir, el TimeSensor tardará 5 segundos en pasar el valor de fraction_changed de 0.0 a 1.0. Al haber transcurrido los 5 segundos, y por lo tanto haber llegado a 1.0 el valor de fraction_changed, el TimeSensor dejará de modificar el fraction_changed y se parará.

Ejemplo2: Se inicia y va realizando ciclos de 5 segundos sin pararse.

DEF Infinit TimeSensor{startTime 0cycleInterval 5loop TRUE

}

Ahora, al haber transcurrido los primeros 5 segundos y haber llegado a 1.0 el valor de fraction_changed, como hemos definido que realice bucles con el loop TRUE, el sensor volverá a empezar un nuevo ciclo. Esto lo irá realizando sin pararse hasta que carguemos un entorno nuevo en el visualizador o bien apaguemos el visualizador.

Page 95: Manual Vrml 2012

Para poder aprovechar el paso del tiempo que nos va dando el TimeSensor, debemos utilizar los interpoladores que pasamos a ver a continuación.

Interpoladors

La interpolación lineal (que es la que utiliza VRML97) és un concepto matemático que permite definir dos puntos (en cualquier dimensión) y calcular un punto intermedio sobre la recta que los une a partir de especificar el tanto porciento del recorrido entre los dos puntos.

Para saber que es un interpolador...

En VRML97 hay seis tipos de interpoladores:

ColorInterpolator : Interpola colores. CoordinateInterpolator : Interpola coordenadas de vértices. NormalInterpolator : Interpola normales a superfícies. OrientationInterpolator : Interpola ángulos de rotación. PositionInterpolator : Interpola posiciones de objetos. ScalarInterpolator : Interpola valores cualesquiera (escalares, es decir, univaluados).

Para ver como funcionan empezaremos por el interpolador de colores. Lo que vamos a hacer es que un objeto vaya cambiando de color de forma gradual, empezando por el rojo y terminando en el verde. Tengamos en cuenta que segun la forma de definir colores RGB (valores entre 0 y 1) el rojo es el (1 0 0) y el verde es el (0 1 0).

Así pues, definimos nuestro interpolador de colores como:

DEF Rojo_a_Verde ColorInterpolator {key [ 0, 1 ]keyValue [ 1 0 0, 0 1 0 ]

}

Con esta definición, estamos diciendo que queremos que cunado el interpolador empiece (0% del trayecto, key=0) nos dé el color rojo, keyValue=(1 0 0), y cuando termine (100% del trayecto, key=1) nos dé el color verde, keyValue=(0 1 0).

El interpolador deberá ir cambiando el valor de key gradualmente y en función de este valor, ir calculando el valor del color de keyValue. Por ejemplo, cuando sea key=0.5, obtendrá el valor de keyValue=(0.5 0.5 0) que es un tono amarillo medio.

Pero no sólo se puede dar un tramo de interpolación. Podríamos decir que empiece en rojo, a continuación pase por verde, después llegue a azul y finalmente vuelva a rojo.

Ahora tenemos tres tramos de cambio de color y por lo tanto definimos nuestro interpolador de colores de la siguiente forma:

Page 96: Manual Vrml 2012

DEF Arcoiris ColorInterpolator {key [ 0, 0.3, 0.6, 1]keyValue [ 1 0 0, 0 1 0, 0 0 1, 1 0 0]

}

Con esta definición estamos determinando que cuando el interpolador empiece (0% del trayecto, key=0) nos dé el color rojo, keyValue=(1 0 0). Cuando llegue a key=0.3 (aproximadamente un tercio del trayecto) nos dé color verde, keyValue=(0 1 0). Al llegar a key=0.6 (aprox. dos tercios) nos de color azul, keyValue=(0 0 1) y, finalmente, cuando termine (100% del trayecto, key=1) nos dé color rojo de nuevo, keyValue=(1 0 0).

Así, si tenemos definido un material que aplicamos a un objeto, podemos hacer que el interpolador vaya modificando el valor del field de este material (ver Materiales) y por lo tanto nos vaya cambiando el color del objeto al que lo aplicamos. Así pues, haremos un ROUTE desde un evento de salida del interpolador al evento de entrada diffuseColor del material.

Pero qué es lo que hace que el interpolador vaya pasando del valor inicial al final de forma gradual? Pues el paso del tiempo de un TimeSensor como los que hemos introducido arriba. Aquí también tendremos que hacer un ROUTE entre el tiempo del TimeSensor y el cambio de tanto por ciento del interpolador (es decir, el key).

Las "rutas" que hemos visto en el módulo anterior nos enlazan los valores que irán modificando nuestro entorno con los sensores de tiempo y los interpoladores. Veamos como funcionaría nuestro ejemplo completo de un objeto que va cambiando de color:

Exemple3: Cub cambiando de color.

DEF motorColor TimeSensor{loop TRUEcycleInterval 5

}

DEF Arcoiris ColorInterpolator {key [ 0, 0.3, 0.6, 1]keyValue [ 1 0 0, 0 1 0, 0 0 1, 1 0 0]

}

DEF CuboColorCambiante Shape {geometry Box { size 2 2 2 }appearance Appearance { material DEF materialColorCambiante

Material {} }}

ROUTE motorColor.fraction_changed TO Arcoiris.set_fractionROUTE Arcoiris.value_changed TO materialColorCambiante.diffuseColor

Analicemos que hace este código:

Page 97: Manual Vrml 2012

En primer lugar estamos definiendo un TimeSensor al que llamamos motorColor. Este TimeSensor se pondrá en marcha al cargar el entorno e irá actuando en ciclos de 5 segundos sin pararse nunca.

A continuación definimos un ColorInterpolator de tres tramos (rojo-verde, verde-azul, azul-rojo) de la misma longitud, aproximadamente un tercio cada uno.

En tercer lugar definimos nuestro objeto, el CuboColorCambiante, que como su nombre indica, es un cub que va cambiando de color. Este objeto se define como una geometría que es una caja (Box) que forma un cubo, y por una apariencia con un material. Al material se le ha asignado el nombre materialColorCambiante pero no tiene ningún parámetro definido: Material { }. Esto se debe a que el campo diffuseColor será tratado como evento de entrada (eventIn).

Finalmente, encontramos las rutas: o La primera define que el paso del tiempo del TimeSensor vaya haciendo avanzar el

trayecto recorrido por el interpolador de color. Esto se consigue enlazando el evento de salida fraction_changed del TimeSensor motorColor con el evento de entrada set_fraction del ColorInterpolator Arcoiris. Con este enlace, cada "tic-tac" del TimeSensor hace incrementar en una pequeña porción el avance del ColorInterpolator.

o La segunda enlaza el nuevo color generado por el ColorInterpolator después de haber avanzado (debido a la acción del TimeSensor) con el color del objeto. Esto se consigue enlazando el evento de salida, eventOut value_changed, del ColorInterpolator con el evento de entrada, eventIn diffuseColor, del material materialColorCambiante del cubo que hemos definido.

Del mismo modo en que hemos enlazado un TimeSensor a un ColorInterpolator, lo podemos hacer para cualquier otro interpolador.

Page 98: Manual Vrml 2012

Ejercicios propuestos:NORIA

Diseñar una noria de parque de atracciones con cuatro cestas.

Comentarios

Utilizar tan solo primitivas para modelar las partes. Utilizar el OrientationInterpolator. Aprovechar el prototipage de objetos.

Solución propuesta: sinia.wrl.Pasos seguidos en la construcción de este entorno: sinia_e.htm

CARRUCEL

Diseñar uns carrucel de parque de atracciones con seis cavallitos.

Comentarios

Utilizar tan solo primitivas para modelar las partes. Utilizar el OrientationInterpolator y el PositionInterpolator Aprovechar el prototipage de objetos.

Solución propuesta: cavallts.wrl.

Para acabar mirad estas dos propuestas, una es la unión de la noria y el carrucel, el otro es una versión sofisticada de la noria, la geometria de la cual se ha modelado en 3D Max: park.wrl y siniasof.wrl.

Sensores de Visibilidad y Movimiento

Tutorial de VRML97

Sensor de Visibilidad

Este sensor, en principio, solo sirve para cuestiones de optimización. Por ejemplo, si tenemos muchos elementos en movimiento en nuestro entorno, el rendimiento de navegación puede ser bastante bajo. Pero si hacemos que los objetos solo se muevan cuando entren en nuestro campo de visión, mejoraremos el rendimiento por que solo se moverá aquello que realmente es necesario.

Page 99: Manual Vrml 2012

Esto se puede hacer, definiendo una zona en forma de caja alrededor de los objetos. El sensor de visibilidad node VisibilitySensor nos permite definir esta caja invisible, centrada en un cierto punto. Cuando esta caja entra en nuestro rango de visión , entonces el sensor de visibilidad se activa y emite un evento.

Ejemplo1: Sensor de visibilidad.

Transform {translation -5 8 3children Shape {

geometry Sphere { radius 2 }appearance Appearance { ... }

}}

VisibilitySensor {center -5 8 3size 4 4 4

}

Aunque este ejemplo no es funcional, nos muestra como definir la caja de visibilidad alrededor de un objeto. Como la esfera está centrada en el punto (-5 8 3) y tiene un radio de 2 unidades, entonces hemos de centrar la caja de visibilidad en el mismo punto y dar-le unas medidas de 4x4x4 parr que englobe toda la esfera.

Sensores de Movimiento

Estos sensores permiten incidir sobre las traslaciones y rotaciones de objetos directamente e individualmente, sin tener que modificar toda la escena con las interficies del browser.

Hay tres tipos de sensores de movimiento (o "drag sensors " en Inglés):

node PlaneSensor : Permite modificar la posición del objeto, como si se moviese en un plano.

node CylinderSensor : Permite modificar la orientación del objeto, como si rotase alrededor de un eje.

node SphereSensor : Permite modificar la orientación del objeto, como si rotase respecto a su centro.

node PlaneSensor

Este sensor permite mapear los movimientos 2D del cursor de pantalla, en movimientos 2D sobre el plano XY del sistema de coordenadas del sensor. El sensor se activa cuando se oprime sobre el objeto activo y, sin soltar el botón del ratón, se mueve el cursor. Entonces, los movimientos del cursor se pueden aplicar sobre el objeto mediante un ROUTE. Veamos un ejemplo donde un cubo verde es el objeto activo y tenemos un cubo naranja de referencia, inactivo.

Page 100: Manual Vrml 2012

Ejemplo1: Sensor de Movimiento en un Plano.

Transform { # Cubo de referenciatranslation -3 0 0children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0.7 0.3 0 }}

}}

Group {children [

DEF Cubo Transform {children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0 0.7 0.3 }

}}

}DEF PS PlaneSensor { }

]}

ROUTE PS.translation_changed TO Cubo.translation

Observad como este sensor se define de forma parecida al sensor de tacto visto en el módulo anterior, es decir, debe definirse como "hermano" de los objetos que han de ser activos.

A continuación veremos un ejemplo donde el cubo naranja es el activo, pero el que se mueve es el verde.

Ejemplo2: Sensor de Movimiento en un Plano, donde el objeto activo es diferente al que se mueve.

Group {children [

Transform { # Cubo activotranslation -3 0 0children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0.7 0.3 0 }

}}

}DEF PS PlaneSensor { }

Page 101: Manual Vrml 2012

]}

DEF Cubo Transform { # Cubo que se muevechildren Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0 0.7 0.3 }}

}}

ROUTE PS.translation_changed TO Cubo.translation

Como se puede observar, el mapeo hecho con el ROUTE no ha variado, pero hemos puesto el sensor de movimiento en el plano, agrupado con el otro cubo (el naranja).

node CylinderSensor

Este sensor permite mapear los movimientos 2D del cursor de pantalla, en rotaciones alrededor del eje Y del sistema de coordenadas del sensor. El sensor se activa cuando se oprime sobre el objeto activo y sin soltar el botón del ratón, se mueve el cursor. Entonces, los movimientos del cursor se pueden reflejar sobre el objeto mediante un ROUTE. Veamos el ejemplo del cubo verde modificado.

Ejemplo3: Sensor de Movimiento Cilíndrico.

Transform { # Cubo de referenciatranslation -3 0 0children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0.7 0.3 0 }}

}}

Group {children [

DEF Cubo Transform {children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0 0.7 0.3 }

}}

}DEF CS CylinderSensor { }

]}

Page 102: Manual Vrml 2012

ROUTE CS.rotation_changed TO Cubo.rotation

Observad como este sensor se define de forma parecida al sensor de tacto visto en el módulo anterior, es decir, debemos definirlo como "hermano" de los objetos que han de ser activos.

node SphereSensor

Este sensor permite mapear los movimientos 2D del cursor de pantalla, en rotaciones alrededor del origen de coordenadas. El sensor se activa cuando se oprime sobre el objeto activo y sin soltar el botón del ratón, se mueve el cursor. Entonces, los movimientos del cursor se pueden reflejar sobre el objeto mediante un ROUTE. Veam el ejemplo del cubo verde modificado.

Ejemplo4: Sensor de Movimiento Esférico.

Transform { # Cubo de referenciatranslation -3 0 0children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0.7 0.3 0 }}

}}

Group {children [

DEF Cubo Transform {children Shape {

geometry Box { size 2 2 2 }appearance Appearance {

material Material { diffuseColor 0 0.7 0.3 }

}}

}DEF SS SphereSensor { }

]}

ROUTE SS.rotation_changed TO Cubo.rotation

Observad como este sensor se define de forma parecida al sensor de tacto visto en el módulo anterior, es decir, debemos definirlo como "hermano" de los objetos que han de ser activos.

Page 103: Manual Vrml 2012

Ejercicios propuestos:Control de un Objeto

Definir tres objetos que sirvan de íconos y de sensores de movimiento en el plano, rotación cilíndrica y rotación esférica para muver otro objeto que escojais.

Comentarios

Utilizad solo primitivas para modelar los objetos.

Solución propuesta : sensores .wrl.

Nivel de Detalle (LOD)

Tutorial de VRML97

El nivel de detalle (o LOD: Level Of Detail) es una técnica imprescindible en gráficos 3D generados en tiempo real, para poder mantener la velocidad de refresco de pantalla sin gastar tiempo inútilmente. De lo que se trata es de tener modelos simplificados (en diferentes grados) de un mismo objeto. Entonces se escoge cual de los modelos se muestra en cada momento según la distáncia a la que está del observador. Esto se hace por que no tiene sentido dibujar un objeto muy complejo con centenares de polígonos si este objeto ocupa 3x3 pixels en pantalla. Si no tuviéramos modelos simplificados estaríamos malgastando tiempo en dibujar a pleno detalle una cosa que finalmente no se apreciaría.

La manera en que se trabaja al aplicar el LOD, es a base de definir espacios o rangos delante del observador y asignar uno de los modelos del nivel de detalle adecuado para ser visto en aquella distáncia. El node que el VRML implementa para conseguir este efecto es precisamente el node LOD.

El siguiente ejemplo nos muestra el efecto de irnos acercando a una silla. Conforme nos vamos acercando el modelo va ganando en definición.

Ejemplo1: Definición de una silla en niveles de detalle.

LOD {range [ 10 15 20 ]level [

Group { # Niell 1 (máximo nivel): dos cajas y cuatro cilindros

children [Transform { # Respaldo

Page 104: Manual Vrml 2012

translation 0 3.5 -1.75children Shape {

geometry Box { size 3.5 3 0.5 }

appearance Appearance { material Material { diffuseColor 0.8 0.6 0 } }

}}Shape { # Asiento

geometry Box { size 3.5 0.5 3.5 }appearance Appearance { material

Material { diffuseColor 0.8 0.6 0 } }}Transform { # Pata posterior izquierda

translation -1.75 0 -1.75children Shape {

geometry Cylinder { radius 0.25 height 10 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}Transform { # Pata posterior derecha

translation 1.75 0 -1.75children Shape {

geometry Cylinder { radius 0.25 height 10 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}Transform { # Pata frontal izquierda

translation -1.75 -2.5 1.75children Shape {

geometry Cylinder { radius 0.25 height 5 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}Transform { # Pata frontal derecha

translation 1.75 -2.5 1.75children Shape {

geometry Cylinder { radius 0.25 height 5 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}

]}Group { # Nivel 2: seis cajas

children [Transform { # Respaldo

translation 0 3.5 -1.75children Shape {

Page 105: Manual Vrml 2012

geometry Box { size 3.5 3 0.5 }

appearance Appearance { material Material { diffuseColor 0.8 0.6 0 } }

}}Shape { # Asiento

geometry Box { size 3.5 0.5 3.5 }appearance Appearance { material

Material { diffuseColor 0.8 0.6 0 } }}Transform { # Pata posterior izquierda

translation -1.75 0 -1.75children Shape {

geometry Box { size 0.5 10 0.5 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}Transform { # Pata posterior derecha

translation 1.75 0 -1.75children Shape {

geometry Box { size 0.5 10 0.5 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}Transform { # Pata frontal izquierda

translation -1.75 -2.5 1.75children Shape {

geometry Box { size 0.5 5 0.5 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}Transform { # Pata frontal derecha

translation 1.75 -2.5 1.75children Shape {

geometry Box { size 0.5 5 0.5 }

appearance Appearance { material Material { diffuseColor 0.8 0 0.2 } }

}}

]}Group { # Nivel 3: dos cajas

children [Transform { # Respaldo

translation 0 2.5 -1.75children Shape {

geometry Box { size 4 5 0.5 }

Page 106: Manual Vrml 2012

appearance Appearance { material Material { diffuseColor 0.8 0.6 0 } }

}}Transform { # Asiento

translation 0 -2.5 0children Shape {

geometry Box { size 4 5 4 }appearance Appearance

{ material Material { diffuseColor 0.8 0.6 0 } }}

}]

}Shape { # Nivel 4 (más bajo): una caja

geometry Box { size 4 10 4 }appearance Appearance { material Material

{ diffuseColor 0.8 0.6 0 } }}

]}

Las partes del node LOD son las siguientes. En primer lugar encontramos el field range donde definimos las particiones de distancia donde se verá cada nivel de modelo. Querremos definir cuatro (4) modelos diferentes y para esto definimos tres (3) valores. El primer valor nos indica que se ha de ver el modelo más detallado si el observador está a menos de 10 unidades del objeto. El segundo valor nos indica que se ha de ver el segundo nivel de detalle si el observador está a menos de 15 unidades ( y a más de 10 unidades) del objeto. El tercer valor nos indica que se ha de ver el tercer nivel de detalle si el observador está a menos de 20 unidades ( y a más de 15 unidades) del objeto. Finalmente, no es necesario poner un cuarto valor por que ya se deduce que se ha de ver el cuarto nivel de detalle si el observador está a más de 20 unidades del objeto.

El segundo elemento que encontramos es el field level que es donde indicamos las diferentes versiones del objeto en orden de mayor a menor detalle.

Evidentemente, los rangos que hemos tomado en este ejemplo no producen un efecto suave de cambio, y son solamente como ejemplo didáctico. Para que os hagais una idea de como son los cuatro elementos, aquí los podréis ver todos uno al lado del otro: 4nivels.wrl.

Page 107: Manual Vrml 2012

Ejercicios propuestos:Casa

Diseñar una casa en 5 niveles de detalle y definir el comportamiento con el node LOD.

Comentarios

Utilizar tan solo primitivas para modelar las partes.

Mundo MisteriosoDiseñar un objeto que tenga un cierto comportamiento como por ejemplo que crezca o se reduzca o rote, y haced que el cambio de comportamiento se active en función de la distancia del observador al objeto. Será como si el objeto reflejase la inmovilidad o movilidad del observador.

Comentarios

Utilizar tan solo primitivas para modelar las partes. No utilizar Interpoladores ni Sensores de Tiempo. Aprovechar el prototipage de objetos.

Solución propuesta: misteri.wrl.

Sonido

Tutorial de VRML97

El sonido en VRML puede ser de dos tipos: espacializado o no espacializado. Por espacializado se entiende que se modela una fuente emisora de sonido y que el observador percibe la posición de esta fuente en función de las posiciones relativas entre ambos Por no espacializado se entiende que la percepción del sonido por parte del usuario es independiante de cualquier parámetro de posición u orientación..

Sonido No Espacializado o Sonido Ambiente

El sonido que no tiene la cualidad de espacializado, es un sonido que se escucha siempre igual, se esté en la posición que sea dentro del entorno. Se le llama también sonido ambiente por hacer referencia al hecho que siempre está presente y crea una especie de ambientación global.

Page 108: Manual Vrml 2012

Para definir un sonido en VRML, se utiliza el node Sound. Para que sea un sonido ambiente, debemos definirle un rango de actuación muy grande (tan grande como sea nuestro entorno). Veamos (o escuchemos) un ejemplo:

Ejemplo1: Definición de un sonido ambiente.

Shape {geometry Sphere { radius 2 }appearance Appearance { material Material { diffuseColor 1 1 0 } }

}

Sound {minFront 200minBrack 200maxFront 200maxBack 200spatialize FALSEsource AudioClip {

url "forest.wav"startTime 1loop TRUE

}}

Aquí aparecen diversos conceptos. En primer lugar, el hecho que el sonido esté formado por una fuente (field source). Para poder especificar qué sonido queremos generar, debemos definir un node AudioClip como fuente sonora (también se puede definir mediante un node MovieTexture pero no lo veremos aquí). En este node AudioClip definimos el archivo de sonido que deseamos integrar a nuestro entorno (field url) y en este caso definimos que se vaya repitiendo indefinidamente (field loop).

Una vez definido el archivo de sonido, debemos establecer las características de este sonido. Hemos dicho que el sonido ambiente no es espacializado y por esta razón definimos como FALSE esta propiedad (field spatialize). Los otros cuatro fields describen el rango de acción del sonido y, por ahora, diremos que definen una esfera de sonido dentro de la cual se oirá el sonido y fuera de ella no. Esta esfera la hemos definido de radio 200 unidades.

Sonido Espacializado

La espacialización del sonido se basa en el hecho de que los seres humanos tenemos dos orejas (y dos oidos), y por esta razón se manifiesta un decalage en tiempo (y en fase) entre el sonido que llega a cada una desde la fuente sonora. De esta forma, podemos detectar de dónde proviene un sonido. Este es el efecto percibido pero, ¿cómo se definen estos sonidos espacializados en VRML?

Para empezar, una fuente sonora tiene una posición en el espacio desde la cual salen las ondas sonoras y se transmiten por vibración de las partículas en el aire. Un sonido usualmente no se emite en todas direcciones por igual, y por esta razón presenta una dirección privilegiada. Este "centro" y esta dirección, generan unos volúmenes en el

Page 109: Manual Vrml 2012

espacio, en que el sonido se percibe de forma distinta según la posición del oyente. Estos volúmenes no son esféricos por efecto de la dirección privilegiada. Son un tipo de volúmenes llamados elipsoides ("esferas alargadas"). Finalmente un sonido pierde intensidad conforme se aleja de la fuente: es el fenómeno conocido como atenuación. POr esta razón, el oyente nota como va bajando el volúmen (la intensidad) del sonido conforme se aleja de del sitio donde se ha producido (la fuente sonora). Pero como hay una dirección privilegiada de emisión, la atenuación es más lenta en la dirección principal y más rápida en la dirección opuesta.

La siguiente ilustración muestra una vista lateral de una persona gritando. El elipse muestra un corte lateral del elipsoide de sonido generado por la fuente sonora (la boca de la persona). La flecha muestra la dirección principal o privilegiada de emisión (la dirección en que la persona está mirando). El tono de gris muestra cómo se atenúa el sonido (negro = intensidad máxima; blanco = intensidad mínima).

Los valores maxBack y maxFront son las distancias máxima hacia atrás y hacia delante (respectivamente) a las que se llega a oir el sonido. Más allá de estas distancias ya no se oye nada.

El modelo del VRML se basa absolutamente en estos principios. El siguiente ejemplo muestra, en 3D, los volúmenes generados y las componentes del node Sound que listamos. Este excelente ejxemplo ha sido diseñado por la empresa dFORM dentro de su tutorial específico de Àudio en VRML.

NOTA: Se debe tener un poco de paciencia para bajar todo el ejemplo completo. Una vez esté totalmente cargado os podéis mover libremente o (de forma recomendada) podéis utilizar los puntos de vista predefinidos.

NOTA2: Puede ocurrir que aparezca un error avisando que no se reconoce el tipo de compresión de sonido. Ignoradlo y pulsar OK.

Sound volumes: Definición del node Sound con valores por defecto. En el ejemplo, podéis ver y escuchar los distintos conceptos al iros moviendo por los puntos de vista predefinidos.

Page 110: Manual Vrml 2012

Sound {location 0 0 0 # Posición por defecto de la fuente sonora:

el origendirection 0 0 1 # Dirección por defecto: eje Zintensity 1 # Intensidad máxima por defecto: 1 (el

máximo)minFront 1 # Máxima distancia hacia delante en que hay

sonido regular (o ambiente)minBack 1 # Máxima distancia hacia atrás en que hay

sonido regular (o ambiente)maxFront 10 # Máxima distancia hacia delante en que se

oye el sonidomaxBack 10 # Máxima distancia hacia atrásen que se oye

el sonidospatialize TRUE # Por defecto espacializar el sonidosource AudioClip {

...

...

...}

}

Como podéis observar, existen dos pares de límites sonoros. Estos dos límites forman dos elipsoides concéntricos. El menor (el interior), definido por field minFront y field minBack, determina la zona en la que el sonido es totalmente envolvente y presente (por lo tanto, como si fuera sonido ambiente). El mayor (el exterior), definido por field maxFront yi field maxBack, determina la frontera a partir de la cual ya no se oye el sonido porque se supone que se está demasiado lejos de la fuente sonora. El espacio entre los dos elipsoides es la zona en la que se puede apreciar la atenuación. Tanto más cercano esté el oyente del elipsoide menor, más fuerte se oirá el sonido. Tanto más lo esté al elipsoide exterior, más bajo se oirá el sonido, hasta que en el límite se deja de oir.

Page 111: Manual Vrml 2012

Ejercicios propuestos:El Mosquito

Diseñar un entorno en el que haya un objeto (el mosquito) que vaya girando alrededor de un objeto central (la cabeza de la víctima) y hacer que el mosquito vaya zumbando en su vuelo.

Comentarios

Utilizad tan solo primitivas para modelar los objetos. Utilizad el sonido que os damos en la dirección:

http://www.iua.upf.es/~npares/docencia/vrml/so/exemples/mosquit.wav Utilizad un interpolador de orientación. Haced el tamaño del elipsoide interno del tamaño del mosquito. Haced el tamaño del elipsoide externo lo suficientemente grande como para que se

oiga desde la "cabeza". Notad que un mosquito es una de las pocas fuentes sonoras que si emiten de forma

(bastante) regular en todas direcciones por igual.

Solución propuesta: mosquit.wrl.

Scripting

Tutorial de VRML97

Aunque el VRML da muchos mecanismos para definir interacción y comportamientos, hay cosas que no se pueden hacer diréctamente y entonces se debe utilizar la poténcia de un lenguaje de programación externo. Esto se consigue a través del node Script y los lenguajes que se pueden utilizar son el Java y el JavaScript (o compatible JavaScript).

En este tutorial, tan solo entraremos a ver la utilización del JavaScript dentro del node Script debido a que es mucho más sencillo, directo y común de utilizar.

Nota: Partiremos del supósito que el lector ya cuenta con un conocimiento previo del JavaScript como lenguaje y que lo sabe utilizar a nivel básico para realizar pequeñas utilidades en pantallas de HTML.

El node Script

El concepto básico detrás del node Script es que es un node que permite los siguientes pasos:

Page 112: Manual Vrml 2012

captar los eventos que necesitemos conseguir los valores que forman los eventos y procesarlos enviar los resultados de este proceso como eventos de salida (para ser encaminados,

mediante ROUTEs, hacia otros nodes)

Un node Script está formado por dos partes principales: las definiciones de campos y eventos, y el código en el lenguaje que hemos escogido.

Es importante el hecho que en este node podemos definir campos y eventos según nuestras necesidades, en contraste con los otros nodes de VRML que ya tienen predefinidos todos sus componentes.

El sitio donde se pone el código del lenguaje es en el field url. Este field permite escribir todo el código entre comillas dobles (") o bién referenciar un archivo externo donde figure todo el código.

A continuación vemos un esquema de la estructura del node:

Esquema: Estructura del node Script.

Script {field .... . .. . .field ...eventIn .... . .. . .eventIn ...eventOut .... . .. . .eventOut ...

url "javascript:function X (v,t){

. . .

. . .}. . .. . .function Z (v,t){

. . .

. . .}

"}

Aquí se pueden observar las dos partes que definíamos arriba. Primero se encuentran las definiciones de campos y eventos. Estos no requieren estar ordenados de ningúna forma concreta. En segundo lugar, encontramos el field url donde, entre comillas, se define el tipo

Page 113: Manual Vrml 2012

de código que se utiliza (en nuestro caso javascript:) y a continuación todas las funciones que configuran nuestros procesos.

Los eventIns y las functions de JavaScript

Existe una relación directa entre los nombres de los eventIn y los nombres de las funciones del código. Esta relación se establece para que cuando llegue un evento de entrada al node Script en custión, él llame a la función que tiene el mismo nombre que el eventIn referenciadi y así se pueda capturar el valor que se ha recibido y se pueda procesar.

El mecanismo implementado por el node Script hace que toda función de JavaScript asociada a un eventIn tenga dos parámetros por defecto: el valor recibido por el eventIn y el instante de tiempo en que se ha generado aquel evento. De esta forma, la función puede utilizar el valor del evento que ha recibido e incluso discernirlo de otros eventos gracias al hecho de que también se dispone de su sello de tiempo.

A continuación damos un ejemplo donde un ProximitySensor envía un evento de cambio de posición del punto de vista a un Script que mira si la coordenada X de este punto de vista es mayor que 5 (y no hace nada más de momento).

Ejemplo1: Definimos un ProximitySensor llamado SensorPuntoVista que va detectando el movimiento del punto de vista del usuario por dentro suyo. Este ProximitySensor va generando eventOuts de nombre position_changed, los cuales son encaminados mediante un ROUTE al eventIn de nombre nuevaPosicion del Script llamado SiguePuntoVista.

DEF SensorPuntoVista ProximitySensor {size 100 100 100

}

DEF SiguePuntoVista Script {eventIn SFVec3f nuevaPosicion

url "javascript:function nuevaPosicion (v,t) {

if (v[0] > 5);}

"}

ROUTE SensorPuntoVista.position_changed TO SiguePuntoVista.nuevaPosicion

Analicemos este código parte por parte:

En primer lugar, tenemos la definición del ProximitySensor al cual le damos un nombre para referenciarlo en el ROUTE.

Después encontramos el Script al cual también damos un nombre. Este node, no tiene ningún campo o evento definido a priori a parte del campo url (después veremos que si hay 2 pero de momento quedémonos con esta idea). Por lo tanto, es necesario que

Page 114: Manual Vrml 2012

nosotros definamos los campos y eventos que nos convienen. De momento, como la única cosa que queremos hacer es captar el evento de cambio de posición del punto de vista dentro del ProximitySensor, definimos un eventIn del tipo vector 3D univaluado en coma flotante (SFVec3f, Single-valued Field of Vector 3 components in floating point). A este evento de entrada le asignamos el nombre nuevaPosicion, lo cual implica que tendremos que definir una función de JavaScript con el mismo nombre para así poder captar el valor que entre por este evento.

En el campo url encontramos el código JavaScript. De momento sólo nos hace falta definir una sola función, la que debe estar asociada al evento de entrada. Así pués, definimos una función con nombre nuevaPosicion y a la que por defecto el VRML le define dos parámetros: v que es el valor que llega al eventIn y t que es el instante de tiempo en el que se ha generado el evento. De esta forma, desde dentro de la función podemos acceder al valor del evento de entrada y lo podremos comparar en su coordenada X(1) con nuestro límite de 5 unidades.

Finalmente encontramos el ROUTE con el cual enlazamos el eventOut position_changed que tiene predefinido el ProximitySensor con el eventIn nuevaPosicion que hemos definido en nuestro node Script.

(1) Al contrario de en VRML donde no se accede nunca a las componentes de los datos que pertenecen a tipos no escalares como SFVec3f, SFRotation, SFColor, SFVec2f y todos los MFs, cuando hemos de programar puede interesarnos acceder a estas componentes. En un caso como este, un valor de estos tipos se comporta como si fuera un array de JavaScript y por lo tanto se accede a las componentes indexando desde 0 (cero) hasta el número de componentes menos uno. Por ejemplo: a un field SFColor con nombre miColor, se le podrían asignar los valores RGB (1, 0.5, 0.3) desde un Script indexando de la siguiente forma: miColor[0]=1; miColor[1]=0.5; miColor[2]=0.3;

Los eventOut

Los eventOut se definen en la primera parte del node Script de forma similar a los eventIn. Para poder generar el evento de salida a través del eventOut que hemos definido, tan solo tenemos que asignarle un valor desde dentro de la función que ha de generar el evento.

Ampliemos nuestro ejemplo anterior. Ahora queremos que suene una alarma cuando detectemos que el punto de vista ha sobrepasado el límite de 5 unidades en el eje X. Los elementos necesarios son los siguientes:

Ejemplo2: Definición de unos eventos de salida para activar un sonido de alarma (añadimos al ejemplo anterior).

DEF SensorPuntoVista ProximitySensor {size 100 100 100

}

DEF SiguePuntoVista Script {eventIn SFVec3f nuevaPosicioneventOut SFTime activaAlarma

Page 115: Manual Vrml 2012

eventOut SFTime apagaAlarma

url "javascript:function nuevaPosicion (v,t) {

if (v[0] > 5) activaAlarma = t;else apagaAlarma = t;

}"

}

DEF ClipAlarma AudioClip {url "alarma.wav"startTime -1loop TRUE

}

Sound {source USE ClipAlarmamaxFront 200maxBack 200

}

ROUTE SensorPuntoVista.position_changed TO SiguePuntoVista.nuevaPosicionROUTE SiguePuntoVista.activaAlarma TO ClipAlarma.startTimeROUTE SiguePuntoVista.apagaAlarma TO ClipAlarma.stopTime

Los elementos nuevos son los siguientes:

Hemos añadido dos eventOuts a nuestro Script: activaAlarma y apagaAlarma, de esta forma podremos activar y apagar el sonido de alarma según la posición del usuario. Estos eventos de salida son del tipo SFTime porque lo que deseamos es dar un tiempo de inicio y un tiempo de finalización del sonido.

En el código de JavaScript, hemos añadido una acción a realizar en el if y hemos añadido una opción else. Lo que hacemos es aprovechar el hecho de que toda la función asociada a un eventIn tiene los dos parámetros por defecto: el valor del evento y el tiempo en que se ha generado. Así pués, en t tenemos el instante de tiempo en que se ha generado el cambio de posición del usuario y por lo tanto es el instante indicado para activar o apagar el sonido. Una vez el if ha discernido si el usuario ha traspasado el límite, asignamos el tiempo al evento de salida correspondiente. Nota: Es importante entender que el evento de salida se genera por el solo hecho de asignar un valor al eventOut. El momento en el que se envían estos eventos de salida es cuando el VRML ha terminado de ejecutar todo el Script.

A continuación hemos añadido dos nodes para definir el sonido. No entraremos a explicarlo ya que se explican en el módulo de sonido de este tutorial.

Finalmente hemos añadido dos ROUTEs para encaminar los eventos de salida de nuestro Script hacia los eventos de entrada correspondientes de nuestro AudioClip.

Page 116: Manual Vrml 2012

Los fields

Los field también se definen en la primera parte del node Script de forma similar a los eventIn y a los eventOut. Los field sirven como variables globales para el Script y para guardar valores a lo largo de toda la ejecución del entorno. Con esto podemos comparar valores de eventos nuevos con valores antiguos que hayamos guardado previamente en fields.

De nuevo ampliemos nuestro ejemplo. Lo que haremos ahora es que suene la alarma solo la primer vez que el usuario pase el límite. Si el usuario vuelve atrás y después de nuevo sobrepasa el límite, la alarma ya no deberá sonar. Los elementos necesarios son los siguientes:

Ejemplo3: Definición de un field booleano para saber si el usuario ya había traspasado el límite préviamente.

DEF SensorPuntoVista ProximitySensor {size 100 100 100

}

DEF SiguePuntoVista Script {eventIn SFVec3f nuevaPosicionfield SFBool haEntrado FALSEeventOut SFTime activaAlarmaeventOut SFTime apagaAlarma

url "javascript:function nuevaPosicion (v,t) {

if (v[0] > 5)if(!haEntrado){

activaAlarma = t;haEntrado = TRUE;

}else apagaAlarma = t;

}"

}

DEF ClipAlarma AudioClip {url "alarma.wav"startTime -1loop TRUE

}

Sound {source USE ClipAlarmamaxFront 200maxBack 200

}

ROUTE SensorPuntoVista.position_changed TO SiguePuntoVista.nuevaPosicionROUTE SiguePuntoVista.activaAlarma TO ClipAlarma.startTime

Page 117: Manual Vrml 2012

ROUTE SiguePuntoVista.apagaAlarma TO ClipAlarma.stopTime

Solo hemos añadido los elementos siguientes:

Primero, hemos añadido un field de tipo SFBool con el nombre haEntrado. A este field le hemos dado un valor inicial de FALSE porque al inicio, el usuario aún no ha sobrepasado la zona prohibida. Nota: todo field ha de tener un valor inicial independientemente de la utilización que se haga.

En segundo lugar, hemos añadido un if dentro de la rama cierta del primero, poniendo la condición de que per activar la alarma se debe cumplir que el usuario aún nunca haya passado el límite. Esto se consigue mirando si nuestro field haEntrado es falso o cierto.

Finalmente, hemos añadido a la rama cierta del if, la acción de asignar el valor TRUE al field haEntrado para tener conocimiento de que el usuario ya ha traspasado una vez el límite.

No es necesario añadir nada más porque cada vez que se llame el Script el field que hemos definido tendrá el último valor que le hayamos asignado.

El field mustEvaluate

Inicialmente hemos dicho que, excepto por el field url, el node Script no tenía ningún otro campo predefinido. Esto lo hemos dicho para simplificar las explicaciones anteriores, pero no es exáctamente cierto. De hecho el node Script dispone de dos campos predefinidos: mustEvaluate y directOutput.

Durante la ejecución de un entorno de VRML, el browser tiene la autorización (por especificación) de gestionar los eventos en el momento que le sea más idóneo. Esto puede provocar que se acumulen una série de eventos durante un lapso de tiempo, para después ser evaluados todos de golpe (evidentemente en el orden en que se han generado).

Esto significa que cuando programemos un Script para gestionar unos eventos, podría pasar que no se nos evalúe el Script cada vez que se genera el evento de entrada que necesitamos. En este caso pasaría que al cabo de un rato se evaluaría nuestro Script tantas veces como eventos de entrada se hayan acumulado.

Para poder evitar o controlar esto, el node Script dispone del campo prodefinido field SFBool mustEvaluate. Por defecto, este campo tiene valor FALSE, cosa que significa que la evaluación del Script puede ser postpuesta. Si queremos que nuestro Script se evalúe cada vez que se reciba un evento de entrada de los que gestionamos, entonces debemos poner el campo mustEvaluate TRUE.

Nota: Es necesario tener en cuenta que poner mustEvaluate TRUE implica imponer un control más exhaustivo al browser y por lo tanto se pierde eficiencia. Sólo debe hacerse cuando sea estríctamente necesario.

Page 118: Manual Vrml 2012

El Mecanismo de Acceso a otros Nodes y el field directOutput

A veces es práctico poder acceder diréctamente a los exposedFields, eventOuts y eventIns de nodes externos al Script, sin tener que definir todo un conjunto de ROUTEs. Esto da más control sobre el entorno ya que no se depende de la gestión de eventos que hace el browser. Así pués, podríamos tener definido un node de transformación con un cubo como geometría, del cual queremos saber el valor del campo de traslación desde dentro del Script sin necesidad de que se genere un evento. Entonces lo que haríamos sería:

Ejemplo4: Definimos un acceso directo a un node externo a un Script.

DEF TransfCubo Transform {translation 0 0 0children [

Shape {geometry Box { size 1 1 1 }

}DEF TS TouchSensor {}

]}

DEF MiScript Script {eventIn SFTime clickfield SFNode TCubo USE TransfCubo

url "javascript:function click(v,t) {

if(TCubo.translation[0] > 5) ...}

"}

ROUTE TS.touchTime TO MiScript.click

Miremos paso a paso lo que se ha hecho en este ejemplo:

Definimos un node de trasformación al cual ponemos un nombre TransfCubo para poder accederlo. Este node contiene un cubo como geometría, y un TouchSensor para que el cubo sea "clicable".

A continuación definimos un Script con los siguientes elementos: o Un eventIn SFTime click que nos captura los eventos de activación del

TouchSensor. o Definimos después un field de tipo node (SFNode) para poder referenciar

diréctamente el node de trasformación externo. A este field le llamamos TCubo y para dejar claro que no es un node nuevo sino que en realidad estamos haciendo referencia al de la trasformación, añadimos USE TransfCubo. Esto significa que está utilizando el node TransfCubo externo.

o Entonces definimos la función asociada al eventIn click. En esta función empezamos mirando el valor de la componente X del campo de traslación del

Page 119: Manual Vrml 2012

node de transformación TransfCubo. Esto lo conseguimos a través de la referencia que hemos definido en la primera parte del Script, es decir, a través de TCubo.

Con este ejemplo vemos que podemos acceder a información de nodes externos sin tener que establecer ROUTEs que nos encaminen eventos. Pero tal y como está definido, sólo podemos acceder a los exposedFields o a los eventOuts para leer su valor.

Si quisiéramos acceder a los exposedFields o a los eventIns para modificarlos, no podríamos a menos que utilizáramos el campo que subministra el VRML en los Scripts, que es el field SFBool directOutput. Este campo, por defecto tiene el valor FALSE. Así, para poder tener acceso a los campos de nodes externos y poderlos modificar, debemos cambiarlo a TRUE.

Veamoslo en el siguiente ejemplo:

Ejemplo5: Definimos un acceso directo a un node externo a un Script con posibilidad de modificación.

DEF TransfCubo Transform {translation 0 0 0children [

Shape {geometry Box { size 1 1 1 }

}DEF TS TouchSensor {}

]}

DEF MiScript Script {directOutput TRUEeventIn SFTime clickfield SFNode TCubo USE TransfCubo

url "javascript:function click(v,t) {

if(TCubo.translation[0] > 5) TCubo.translation[0] = 0;

else TCubo.translation[0] = TCubo.translation[0] + 1;

}"

}

ROUTE TS.touchTime TO MiScript.click

Lo que hace el ejemplo es que cada vez que se entra al Script, se mueve el cubo una posición en el eje de las X hasta llegar a 5, momento en el que se devuelve el cubo al origen.

Page 120: Manual Vrml 2012

Ejercicos propuestos:Diseñar un puente levadizo que suba y baje al apretar un botón que se encuentre en un panel. El puente debe realizar todo el recorrido de subida y de bajada sin que se pueda interrumpir a medio camino y sin que se le pueda pedir subir ciando ya esté arriba ni bajar cuando esté abajo.

Comentarios

Utilizar tan solo primitivas para modelar los objetos. Utilitzar campos de Script de tipo SFBool (booleanos o lógicos) para saber el estado

del puente en cada momento. Utilitzar OrientationInterpolators para animar el puente.

Solución propuesta: pont.wrl.

Información de Navegación y Fondos

Tutorial de VRML97

Este módulo resulta un poco un cajón de sastre para terminar de ver las herramientas más útiles del VRML97.

Información de Navegación

La información de navegación son aquellas características del browser que se pueden modificar desde el VRML97. por ejemplo, qué tipo de interfaz de navegación se desea, si se quiere activar la luz de usuario (headlight), la velocidad de desplazamiento del punto de vista, etc. Esta herramienta es muy útil para poder establecer ciertos parámetros del browser sin que lo tenga que hacer el usuario a través del menú. De esta forma podemos personalizar el entorno a nuestra aplicación.

La forma de definir estos parámetros, es mediante el node NavigationInfo. De todas formas, no todas las opciones de los menús del browser están accessibles desde este nodo. Veamos las más importantes:

La luz de usuario o headlight

Esta luz ya la hemos descrito en el módulo sobre Iluminación y vimos que es como si fuera una luz de casco de minero. Esta luz puede interferir en la iluminación que deseamos dar a nuestro entorno y por eso es importante poder-lo apagar ya de entrada. La forma de hacerlo es:

Page 121: Manual Vrml 2012

Ejemplo1: Apagar luz de usuario o headlight.

NavigationInfo { headlight FALSE }

Añadiendo esta línea a un entorno, nos aseguramos que controlamos la iluminación.

Interfaz de Navegación

Cuando se navega con un browser de VRML, se puede escoger entre tres modos que listamos a continuación:

Modo examinar objetos o EXAMINE:

con el cual, el efecto es como si el punto de vista se mantiene fijo y son los objetos los que se mueven respecto al punto de vista. Este modo es muy útil, jústamente, para examinar objetos por todos sus costados.

Modo de caminar o WALK:

con el cual, es cláramente el punto de vista el que se mueve, pero limita el movimiento de forma que se mantiene en un plano o bien siguiendo un "terreno". Este modo es útil para emular el movimiento humano o de un vehículo terrestre.

Modo de vuelo o FLY:

con el cual el punto de vista se mueve en todas direcciones sin ninguna restricción.

Modo ningún interfaz o NONE:

con el cual no aparece ningún tablero de controles de navegación. Esto puede ser muy útil si queremos nosotros proveer las herramientas de navegación al usuario.

Todo lo que hay que hacer es escoger la palabra del navegador que queremos utilizar y escribir el siguiente comando:

Ejemplo2: Escoger el tipo de interfície de navegación.

NavigationInfo { type "WALK" }

Velocidad de movimiento dentro del entorno

También puede ser interesante controlar la velocidad con que se desplaza el punto de vista por el espacio en el entorno que hemos diseñado. La velocidad por defecto es 1 y se puede controlar a través de:

Page 122: Manual Vrml 2012

Ejemplo3: Establecer la velocidad de movimiento del punto de vista.

NavigationInfo { speed 1.0 }

Donde la cantidad especificada significa metros por segundo (recordad que las unidades en VRML son entendidas como metros).

Fondos

El control de un color de fondo puede ser muy útil en el diseño de un entorno. En VRML97, no solo podemos controlar el color, sino que además podemos definir degradados de "cielo", de "tierra", o bien poner imágenes como si fueran escenografías.

La Esfera del Cielo y la Tierra

Para definir un color sólido o un degradado de fondo, VRML97 define el concepto de esfera (o semiesfera) de cielo (y tierra). El cielo es como si hubiera una esfera de radio infinito que engloba todo el mundo. La tierra es una semiesfera de radio infinito situada boca arriba, que engloba toda la mitad inferior del mundo. Todo esto se define a través del node Background.

En estas esfera y semiesfera, podemos definir un único color, o bien podemos definir que un cierto color corresponde a un cierto ángulo de elevación. Curiosamente, en la esfera del cielo, el ángulo se calcula a partir del punto superior (el "polonorte") que corresponde al ángulo 0º (cero grados) y se va incrementando hasta el punto inferior ("polo sur") al que corresponde el ángulo 180º. En cambio, la semiesfera de la tierra funcieno al revés. La siguiente figura mustra una sección vertical de la esfera del cielo (la externa) y la semiesfera de la tierra (interna).

Page 123: Manual Vrml 2012

No es obligatorio definir los dos fondos, la esfera del cielo y la semiesfera de la tierra, sino que se puede escoger definir una u otra, o las dos o ninguna. A continuación veremos un ejemplo en que definimos un solo color de cielo.

Ejemplo4: Definimos un fondo azul uniforme.

Background {skyColor [ 0.8 0.8 1 ]

}

Shape { # Objeto de referenciageometry Sphere { radius 2 }appearance Appearance { material Material { diffuseColor 1 0.8 0 }

}}

En este caso estamos definiendo un solo color de cielo, que aunque no se especifica se asigna al ángulo 0º (cero grados) y el cual el VRML se encarga de distribuir a todo el fondo. El siguiente ejemplo define un degradado de azul obscuro a naranja como si fuese una puesta de sol.

Ejemplo5: Definimos una "puesta de sol".

Background {# 0º 22º 45º 60º 75º 85º

90ºskyAngle [ 0.384, 0.785, 1.047, 1.309, 1.484,

1.5708 ]skyColor [ 0 0 0.2, 0 0 1, 0 1 1, 0.75 0.75 1, 0.8 0.8 0, 0.8 0.6

0, 1 0.4 0 ]# azulobscuro azul cian azulclaro amarillo

anaranjado rojizo}

Shape { # Objeto de referenciageometry Sphere { radius 2 }appearance Appearance { material Material { diffuseColor 1 0.8 0 }

}}

Cabe observar que el primer ángulo, el cero (0º), no se incluye en la lista de ángulos. Ya se da por entendido que el primer valor de color corresponde al "polo norte" o ángulo cero.

Como se puede observar, el último color definido (el rojizo), se extiende hasta el polo sur. Esto es debido a que el VRML llena toda la esfera de color y por lo tanto deduce que queremos llenar la parte de la esfera que queda indefinida con el último valor dado.

Debido a estas dos razones, el primer ejemplo de color de fondo uniforme, tan solo define un solo color y ningún ángulo.

Page 124: Manual Vrml 2012

Par definir una tierra, se procede de forma análoga, pero en este caso, se empieza por el "polo sur" (que representa cero grados, 0º). Añadamos pues un color de tierra verdoso uniforme a nuestro ejemplo de la puesta de sol:

Ejemplo6: Definimos una "puesta de sol" con tierra verde.

Background {# 0º 22º 45º 60º 75º 85º

90ºskyAngle [ 0.384, 0.785, 1.047, 1.309, 1.484,

1.5708 ]skyColor [ 0 0 0.2, 0 0 1, 0 1 1, 0.75 0.75 1, 0.8 0.8 0, 0.8 0.6

0, 1 0.4 0 ]# azulobscuro azul cian azulclaro amarillo

anaranjado rojizo

# 0º 90ºgroundAngle [ 1.5708 ]groundColor [ 0.2 1 0.4, 0.2 1 0.4 ]

}

Shape { # Objeto de referenciageometry Sphere { radius 2 }appearance Appearance { material Material { diffuseColor 1 0.8 0 }

}}

Observad que para la tierra, el funcionamiento es diferente que para el cielo. En este caso, el VRML97 deduce que debe poner el "color transparente" entre el último ángulo definido y el "polo norte". por lo tanto, si solo definimos un color y ningún ángulo, no nos muestra nada, por qué entre el último ángulo que hemos definido (el cero) y el "polo norte" él no pone nada. Por esta razón tenemos que repetir el color verde de la tierra, para la posición cero y para la posición 90º.

Imágenes de Escenografía

Para definir un fondo, el VRML97 también permite definir unas imágenes que se mapean sobre las paredes internas de un cubo de tamaño teóricamente infinito que rodean todo el entorno: Así pues, hemos de definir 6 imágenes para cubrir las paredes: frontal, posterior, derecha, izquierda, superior e inferior del cubo. A continuación podemos ver un ejemplo donde las imágenes no forman un fondo uniforme, pero que permiten distinguir bien las seis superficies.

Ejemplo7: Definimos un fondo con seis imágenes.

Background {frontUrl "fons1.gif"backUrl "fons2.gif"topUrl "fons3.gif"

Page 125: Manual Vrml 2012

bottomUrl "fons4.gif"rightUrl "fons5.gif"leftUrl "fons6.gif"

}

Shape { # Objeto de referenciageometry Sphere { radius 2 }appearance Appearance { material Material { diffuseColor 1 0.8 0 }

}}

Page 126: Manual Vrml 2012

http://wwwdi.ujaen.es/~rse gura/igai/web3d/web3d/docs/cap16.html

16. Textura

Hasta ahora, para definir un objeto visible se ha utilizado el nodo Shape de la siguiente forma:

Shape { appearance Appearance { material ... } geometry ... }

en donde el nodo Appearance tiene un solo campo, material, con el que se definen el color y la transparencia, según se ha visto en el capítulo anterior.

Pero en realidad puede tener también otros dos campos: texture y textureTransform, con los que se define la textura de los objetos:

Shape { appearance Appearance { material ... texture ... textureTransform ... } geometry ... }

Vamos a centrarnos en el segundo campo exclusivamente (texture):

Shape { appearance Appearance { texture ... } geometry ... }

¿Qué es la textura?

La textura es la posibilidad que tenemos de envolver un objeto con:

una imagen existente, usando el campo ImageTexture una película, usando el campo MovieTexture una imagen creada por nosotros pixel a pixel, usando el campo PixelTexture

Page 127: Manual Vrml 2012

Se van a ver los dos primeros (ImageTexture y MovieTexture) en este capítulo, y el tercero (PixelTexture) en el capítulo siguiente.

Textura con ImageTexture

Tomemos como ejemplo la imagen de la derecha: monalisa.jpg

Vamos a envolver con ella los objetos primitivos (caja, cono, cilindro y esfera).

Para ello, se hace uso del nodo ImageTexture, como valor del campo texture, de la siguiente manera:

Shape { appearance Appearance { texture ImageTexture { url ["monalisa.jpg"] } } geometry ... }

Como se puede ver, el nodo ImageTexture tiene el valor url ["monalisa.jpg"] (se supone que la imagen está en el mismo directorio que el documento VRML. Si no fuera así, se pondría entre comillas la ruta del fichero de imagen)

Aplicando esto a una caja de dimensiones 1.5x2.2x0.5:

#VRML V2.0 utf8 # Ejemplo de caja con textura de una imagen

Shape { appearance Appearance { texture ImageTexture { url ["monalisa.jpg"] } } geometry Box { size 1.5 2.2 0.5 } }

Page 128: Manual Vrml 2012

A la derecha se puede ver el resultado (pulsar para cargar el escenario). Como se puede observar, la imagen se ha reproducido en todas las caras.

De manera similar, he aquí los resultados de aplicar esta imagen como textura de un cono, un cilindro y una esfera.

Imágenes distintas en un mismo objeto

Puede interesar que un objeto tenga imágenes diferentes en alguna o algunas de sus caras, como en el caso de la imagen de la derecha (pulsarla para cargar el escenario).

Como se puede ver, este objeto, que representa una lata de bebida (que en realidad es un cilindro), tiene una imagen para su superficie lateral, y otra distinta para los fondos superior e inferior.

Si nos limitamos a ponerlo de esta manera:

Shape { appearance Appearance { texture ImageTexture { url ["etiqueta.jpg"] } } geometry ... }

se reproduciría la imagen de la etiqueta también en los fondos superior e inferior (como se ha podido comprobar en el caso del cilindro con la imagen monalisa.jpg)

Nos interesa que en los fondos superior e inferior tenga la imagen de la derecha (fondo.jpg)

Page 129: Manual Vrml 2012

La operación se hace de la siguiente manera:

Se define el cilindro con la imagen etiqueta.jpg, pero se anulan las superficies superior e inferior:

Shape { appearance Appearance { texture ImageTexture { url ["etiqueta.jpg"] } } geometry Cylinder { height 2 radius 0.6 top FALSE bottom FALSE } }

Lo que anula las superficies superior e inferior son los comandos top FALSE y bottom FALSE respectivamente.

Se define otro cilindro idéntico con la imagen fondo.jpg, pero se anula la superficie lateral.

Shape { appearance Appearance { texture ImageTexture { url ["fondo.jpg"] } } geometry Cylinder { height 2 radius 0.6 side FALSE } }

En este caso, lo que anula la superficie lateral es el comando side FALSE

Por medio del nodo Group (ver cap. 7) se agrupan ambos cilindros, con lo que el resultado es aparentemente un cilindro con imágenes distintas. Pulsando aquí se puede ver el texto final del documento VRML.

Formatos de las imágenes

Los formatos de imagen soportados para ser utilizados como texturas son:

JPG (ó JPEG) GIF PNG

Page 130: Manual Vrml 2012

Textura con MovieTexture

En lugar de usar imágenes estáticas como textura de los objetos, se pueden utilizar videos (películas), en formato MPEG, haciendo uso del nodo MovieTexture, en vez de ImageTexture, de la siguiente manera:

Shape { appearance Appearance { texture MovieTexture { url "mivideo.mpg" speed 1 loop FALSE } } geometry ... }

Con el comando speed se controla la velocidad (1, velocidad normal, 2 doble velocidad, etc.). Con valores negativos el video se ejecutaría hacia atrás.

Con el comando loop se controla si el video funciona ininterrumpidamente (TRUE) o una sola vez (FALSE).

Ejercicio práctico

Se propone como ejercicio práctico de este capítulo poner textura a algunos de los objetos del ejercicio del capítulo anterior (planetas13.wrl), de la siguiente manera:

Planeta WebMaestro: Adjudicar a este objeto como textura la imagen de la derecha (wmtextura.gif). Para ello, es necesario capturar la imagen (pulsando con el botón derecho del ratón, y guardándola con su nombre junto con los demás ficheros de los ejemplos)

Planeta Web3D: Adjudicar a este objeto como textura la imagen de la derecha (web3dtextura.gif). También será necesario capturar esta imagen y guardarla con su nombre junto con los demás ficheros de los ejemplos.

Para ello, tal como se ha visto anteriormente, basta con sustituir, en el nodo Shape de ambos objetos el campo material:

Page 131: Manual Vrml 2012

material Material {}

por el campo texture, de la siguiente manera:

texture ImageTexture { url "imagen.gif" }

Una vez de hechos los cambios indicados, guardar el fichero como planetas16.wrl

A la derecha puede verse el resultado (pulsar la imagen para cargar el escenario).

Como todavía no se ha definido el punto de vista inicial más conveniente, puede ser que el visor se sitúe inicialmente dentro de la esfera mayor, y no se vea nada. En este caso, es necesario retroceder lo que sea preciso.

Pulsando aquí se puede ver el texto del ejercicio práctico planetas16.wrl

#VRML V2.0 utf8#Ejercio práctico planetas16.wrl

#Planeta WebMaestroShape {

appearance Appearance {texture ImageTexture {

url ["wmtextura.gif"]}

}geometry Sphere {

radius 10}

}

#Planeta WebStoreTransform {

translation 10 6 10children [

Shape {appearance Appearance {

material Material {diffuseColor 1 0.5 1transparency 0.5

}}geometry Sphere {

radius 1

Page 132: Manual Vrml 2012

}}

]}

#Planeta Chat de WMaestroTransform {

translation 25 1 -7children [

Shape {appearance Appearance {

material Material {diffuseColor 1 0.3 0.3transparency 0.6

}}geometry Sphere {

radius 1}

}]

}

#Planeta Web3DTransform {

translation -8 8 27children [

Shape {appearance Appearance {

texture ImageTexture {url ["web3dtextura.gif"]

}}geometry Box {

size 1 1 1}

}]

}

#Letrero de bienvenidaTransform {

translation -7 9 25children [

Shape {appearance Appearance {

material Material {diffuseColor 1 1 0

}}geometry Text {

string [" Bienvenido",

" a WMaestro!", "Aterriza en tu planeta preferido"

]}

Page 133: Manual Vrml 2012

}]

}

13. Formas complejas. Elevaciones

En el capítulo anterior se ha visto cómo crear un suelo plano para nuestro mundo, haciendo uso del nodo IndexedFaceSet.

En este capítulo se va a ver cómo crear suelos accidentados, con distintas elevaciones, muy apto para crear cordilleras, fondos marinos, superficies de planetas, etc.

Nodo ElevationGrid para crear suelos accidentados

El nodo ElevationGrid (en inglés: rejilla de elevaciones) determina una rejlla de puntos, es decir, una cuadrícula de puntos de separación uniforme en el plano horizontal XZ, a los que se atribuyen distintas cotas de altura. Se genererá una superficie irregular uniendo dichas cotas.

Veamos su estructura general con un ejemplo:

ElevationGrid { xDimension 6 xSpacing 4 zDimension 3 zSpacing 8 height [ 0.25, 4, 7, 3, 1.5, 0.25, 1.5, 2.5, 1.5, 2.1, 1, 0, 0.3, 0.3, 0, -2.7, -1.5, -3.7 ] }

Observamos los siguientes campos (puede tener otros más, como veremos):

xDimension es el número de puntos de la rejilla, en la dirección del eje X (en este caso, 6 puntos)

xSpacing es la separación de los puntos de la rejilla, en la dirección del eje X (en este caso, 4)

zDimension es el número de puntos de la rejilla, en la dirección del eje Z (en este caso, 3 puntos)

zSpacing es la separación de los puntos de la rejilla, en la dirección del eje Z (en este caso, 8)

height es la altura de cada uno de los puntos de la rejilla. En este caso, la rejilla tiene 6x3=18 puntos, por lo tanto, hay que poner las 18 cotas de altura que correspondan a cada punto.

Page 134: Manual Vrml 2012

A continuación, una representación de la rejilla (en rojo), con sus 18 puntos (en azul) y las cotas de altura atribuidas a cada punto:

La rejilla debe comenzar siempre en el origen de coordenadas y crecer en el sentido positivo de los ejes X y Z.

En el ejemplo se puede observar que habrá un pico máximo de valor 7 en el centro de la hilera trasera, y una depresión máxima de -3.7 a la derecha de la hilera delantera.

Inclusión del nodo ElevationGrid en el nodo Shape

Como se ha dicho repetida veces, para que un nodo que define una forma (como es el caso del nodo ElevationGrid) sea visible, debe incluirse dentro del nodo Shape (ver cap. 5).

La estructura general del nodo Shape es:

Shape { appearance ... geometry ... }

El nodo ElevationGrid será el valor del campo geometry, quedando por tanto así (de manera resumida):

Shape { appearance ... geometry ElevationGrid { ... } }

Page 135: Manual Vrml 2012

Y desarrollando totalmente el ejemplo:

#VRML V2.0 utf8 #Ejemplo del nodo ElevationGrid, #con la apariencia por defecto

Shape { appearance Appearance { material Material { } } geometry ElevationGrid { xDimension 6 xSpacing 4 zDimension 3 zSpacing 8 height [ 0.25, 4, 7, 3, 1.5, 0.25, 1.5, 2.5, 1.5, 2.1, 1, 0, 0.3, 0.3, 0, -2.7, -1.5, -3.7 ] } }

Este es el resultado.

Como el punto inicial (el origen de coordenadas) no es demasiado conveniente para visualizar la superficie generada, a la derecha se puede ver una imagen de este ejemplo en donde se ha modificado el punto de vista inicial a uno más conveniente. También se han añadido unos ejes coordenados. (Pulsar la imagen para cargar el escenario)

Obsérvese que la superficie generada es sólida y existe gravedad, por lo que si se camina por la supeficie se "escalará" por las elevaciones.

Si se gira completamente el escenario, se puede comprobar también que la superficie sólo es visible por su parte delantera.

Determinando una cara visible

Por defecto, la cara visible es la perpendicular a la parte positiva de los ejes coordenados. En el ejemplo anterior, la cara es perpendicular a la parte positiva del eje Z.

Pero puede haber ocasiones que nos interese que sea visible la otra cara. Para determinar una cosa o la otra, el nodo ElevationGrid puede tener el campo ccw (abreviatura de counterclockwise: contrario a la agujas del reloj). Hay dos posibilidades:

ccw TRUE Es la opción por defecto, por tanto no es obligatoria ponerlo. La cara visible es la perpendicular a la parte positiva de los ejes coordenados.

Page 136: Manual Vrml 2012

ccw FALSE En este caso, la cara visible es la opuesta a la parte positiva de los ejes coordenados

Si en el ejemplo anterior se añade el campo ccw FALSE, se puede ver aquí el resultado. Para poder ver la superficie hay que girar 180º el escenario.

Determinando ambas caras visibles

Se puede hacer que ambas caras sean visibles simultáneamente. Para ello el nodo ElevationGrid puede tener el campo solid, que tiene dos posibilidades:

solid TRUE Es la opción por defecto: sólo una cara es visible (la determinada por el campo ccw), y por tanto no es obligatorio ponerlo.

solid FALSE En este caso, ambas caras son visibles simultáneamente.

Si al ejemplo anterior de la cara verde, se le añade el campo solid FALSE, se puede ver aquí el resultado. Girando el escenario, se verá que ambas caras son visibles.

Poniendo color a la superficie generada

En el ejemplo visto anteriormente se ha utilizado la apariencia por defecto, sin un color definido. Más adelante (en el capítulo 13), se verá cómo se define el color para toda una superficie, mediante la inclusión de determinados campos dentro del nodo Material. Esto es general para toda clase de objetos visibles.

Pero en este caso concreto, hay una manera de determinar el color de partes determinadas de la superficie, como vamos a ver a continuación.

Para comprender este método conviene observar de nuevo la representación de la rejilla vista anteriormente. En este caso, la rejilla está formada por dos hileras de 5 cuadrículas, es decir, en total 10 cuadrículas. Se puede determinar el color de la superficie generada sobre cada cuadrícula.

A continuación está la representación de la rejilla vista desde arriba. Además, se ha escrito en cada cuadrícula el color que se desea para la parte de la superficie que le corresponda y un número (del 1 al 10), para señalar el orden de atribución de colores.

Se ha escogido el color blanco para las zonas más altas, el rojo para las intermedias, el verde para las bajas y el azul para las más bajas.

Page 137: Manual Vrml 2012

Hay que añadir dos campos al nodo ElevationGrid:

color que contiene el nodo Color, que a su vez contiene el campo color, en donde se especifican los 10 colores atribuidos a cada cuadrícula.

colorPerVertex que puede ser TRUE, para colores en gradiente (no se estudiará este caso). O puede ser FALSE, en cuyo caso los colores son continuos. Se aplicará esta posibilidad.

El ejemplo anterior quedará de esta manera:

#VRML V2.0 utf8 #Ejemplo del nodo ElevationGrid, #con colores en las caras

Shape { appearance Appearance { material Material { } } geometry ElevationGrid { xDimension 6 xSpacing 4 zDimension 3 zSpacing 8 height [ 0.25, 4, 7, 3, 1.5, 0.25, 1.5, 2.5, 1.5, 2.1, 1, 0, 0.3, 0.3, 0, -2.7, -1.5, -3.7 ] color Color { color [ 1 0 0 #rojo para la cuadr. 1 1 1 1 #blanco para la cuadr. 2

Page 138: Manual Vrml 2012

1 1 1 #blanco para la cuadr. 3 1 0 0 #rojo para la cuadr. 4 0 1 0 #verde para la cuadr. 5 0 1 0 #verde para la cuadr. 6 0 1 0 #verde para la cuadr. 7 0 1 0 #verde para la cuadr. 8 0 1 0 #verde para la cuadr. 9 0 0 1 #azul para la cuadr. 10 ] } colorPerVertex FALSE #colores continuos (no degradados) solid FALSE #ambas caras visibles } }

A la derecha puede verse el resultado. Se han añadido unos ejes coordenados y modificado el punto de vista inicial. (Pulsar la imagen para cargar el escenario).

Ejercicio práctico

Como ejercicio práctico de este capítulo se propone crear la superficie inversa a la del ejemplo práctico visto a lo largo del capítulo, es decir, mantener la misma rejilla y la misma distribución de colores, pero con las 18 cotas cambiadas de signo, que serían por lo tanto, las siguientes:

-0.25, -4, -7, -3, -1.5, -0.25, -1.5, -2.5, -1.5, -2.1, -1, 0, -0.3, -0.3, 0, 2.7, 1.5, 3.7

Guardar el fichero resultante con el nombre de superficie13.wrl

Este es el resultado y este es el texto del fichero.

#VRML V2.0 utf8#Ejemplo práctico del capítulo 13#Superficie con colores en las caras

Shape { appearance Appearance {

Page 139: Manual Vrml 2012

material Material { } } geometry ElevationGrid { xDimension 6 xSpacing 4 zDimension 3 zSpacing 8 height [

-0.25, -4, -7, -3, -1.5, -0.25, -1.5, -2.5, -1.5, -2.1, -1, 0, -0.3, -0.3, 0, 2.7, 1.5, 3.7

] color Color { color [ 1 0 0 #rojo para la cuadr. 1 1 1 1 #blanco para la cuadr. 2 1 1 1 #blanco para la cuadr. 3 1 0 0 #rojo para la cuadr. 4 0 1 0 #verde para la cuadr. 5 0 1 0 #verde para la cuadr. 6 0 1 0 #verde para la cuadr. 7 0 1 0 #verde para la cuadr. 8 0 1 0 #verde para la cuadr. 9 0 0 1 #azul para la cuadr. 10 ] } colorPerVertex FALSE #colores continuos (no degradados) solid FALSE #ambas caras visibles } }

12. Formas complejas. CarasNodo IndexedFaceSet para obtener caras

En los dos capítulos últimos se ha visto cómo obtener puntos aislados, o líneas uniendo una serie de puntos. En éste se verá cómo obtener caras (superficies planas) definidas por varios puntos.

La idea es unir una serie de puntos para que formen una polilínea cerrada, que es la que definirá la cara.

Su estructra resumida es:

IndexedFaceSet { coord Coordinate { point [ . . . ] } coordIndex [ . . . ]

Observamos dos campos (puede tener más, como se verá):

Page 140: Manual Vrml 2012

coord, cuyo valor es el nodo Coordinate, y que sirve para determinar las coordenadas de los puntos aislados que se van a unir entre sí para formar las caras. Se definió en el capítulo 10.

coordIndex, con este campo se define el orden con el que se unen los puntos entre sí para formar las distintas caras, como vamos a ver a continuación.

Veamos primero un ejemplo sencillo: tres puntos que se unen ordenadamente entre sí para formar una cara:

IndexedFaceSet { coord Coordinate { point [ 5 5 0, # este es el punto 0 15 9 0, # este es el punto 1 20 18 0 # este es el punto 2 ] } coordIndex [ 0, 1, 2, -1 ] }

En el campo coord se establecen las coordenadas de los tres puntos. A cada coordenada se ha añadido una línea de comentario para indicar cuál es la numeración que le corresponde al punto. Obsérvese que se comienza por 0 (y no por 1).

En el campo coordIndex se establece el orden en el que se unen los tres puntos que van a formar la polilínea cerrada que va a formar la cara. Con el valor -1 se indica que ahí acaba la cara.

Inclusión del nodo IndexedFaceSet en el nodo Shape

Como se vió en el cap. 10, para que un nodo pueda verse, debe estar incrustado en el nodo Shape. Por tanto, de manera resumida, la inclusión del nodo IndexedFaceSet en el nodo Shape se hará de esta manera:

Shape {geometry IndexedFaceSet { ... }

}

No se ha especificado ningún campo para su apariencia ni color, lo que se verá más adelante.

Desarrollando el ejemplo, quedará de esta manera:

#VRML V2.0 utf8 #Ejemplo de cara uniendo tres puntos, sin definicion del color

Shape { geometry IndexedFaceSet { coord Coordinate { point [ 5 5 0, #este es el punto 0

Page 141: Manual Vrml 2012

15 9 0, #este es el punto 1 20 18 0 #este es el punto 2 ] } coordIndex [ 0, 1, 2, -1 ] } }

A la derecha puede verse el resultado (pulsarla para cargar el escenario). Se han añadido unos ejes coordenados y modificado el punto de vista inicial.

Se puede observar que se ha creado una cara triangular, sin color ni apariencia definida. Si se manipula el escenario, se puede comprobar que la cara sólo es visible por un lado.

Se pueden definir más de una cara simultáneamente, como veremos más adelante.

El color en las caras

Para determinar el color de la cara hay que hacer uso de tres campos más:

color colorIndex colorPerVertex

Con el campo color se especifican cuántos y qué colores se van a usar (en el caso de que haya más de una cara). Este campo se vió en el cap. 10.

Con el campo colorIndex se atribuye a cada una de las caras existentes alguno de los colores expresados en el campo anterior.

Con el campo colorPerVertex se especifica si los colores serán colores continuos, o un gradiente entre dos colores.

Veamos una aplicación en el ejemplo anterior: vamos a hacer que la cara tenga un color verde.

#VRML V2.0 utf8 #Ejemplo de cara, uniendo tres puntos, de color verde Shape { geometry IndexedFaceSet { coord Coordinate { point [

Page 142: Manual Vrml 2012

5 5 0, #este es el punto 0 15 9 0, #este es el punto 1 20 18 0 #este es el punto 2 ] } coordIndex [ 0, 1, 2, -1 ] color Color { color [ 0 1 0 #este es el color 0 (verde), ] #el unico posible pues solo hay una cara } colorIndex [ 0 #a la unica cara se le atribuye el unico color 0 ] colorPerVertex FALSE } }

En el campo color se especifica el color (o los colores, si hay más de una cara)

En el campo colorIndex se atribuye el color a la la cara (o caras, si hay más de una).

En este ejemplo sólo hay una cara con un único color. En el ejercicio práctico se va ver un caso de tres caras de distinto color.

Nota: Se omite la explicación del caso colorPerVertex TRUE (para conseguir caras con colores en gradiente), por su complicación y escasa utilidad, pero sobre todo porque provoca inestabilidad en los visores de VRML (por lo menos en el mío :-)

A la derecha puede verse el resultado (pulsar para cargar el escenario). Se han añadido unos ejes coordenados y modificado el punto de vista inicial.

Si se manipula el escenario, se puede observar que la cara verde es visible sólo por un lado, el que está de frente.

Determinando una cara visible

Por defecto, la cara visible es la perpendicular a la parte positiva de los ejes coordenados. En el ejemplo anterior, la cara es perpendicular a la parte positiva del eje Z.

Page 143: Manual Vrml 2012

Pero puede haber ocasiones que nos interese que sea visible la otra cara. Para determinar una cosa o la otra, el nodo IndexedFaceSet puede tener el campo ccw (abreviatura de counterclockwise: contrario a la agujas del reloj). Hay dos posibilidades:

ccw TRUE Es la opción por defecto, por tanto no es obligatoria ponerlo. La cara visible es la perpendicular a la parte positiva de los ejes coordenados.

ccw FALSE En este caso, la cara visible es la opuesta a la parte positiva de los ejes coordenados

Si en el ejemplo anterior se añade el campo ccw FALSE, se puede ver aquí el resultado. Para poder ver la cara verde hay que girar 180º el escenario.

Determinando ambas caras visibles

Se puede hacer que ambas caras sean visibles simultáneamente. Para ello el nodo IndexedFaceSet puede tener el campo solid, que tiene dos posibilidades:

solid TRUE Es la opción por defecto: sólo una cara es visible (la determinada por el campo ccw), y por tanto no es obligatorio ponerlo.

solid FALSE En este caso, ambas caras son visibles simultáneamente.

Si al ejemplo anterior de la cara verde, se le añade el campo solid FALSE, se puede ver aquí el resultado. Girando el escenario, se verá que ambas caras son visibles.

Utilización de este nodo para crear un suelo

Un uso muy útil del nodo IndexedFaceSet es el de crear un suelo para un escenario de realidad virtual.

Supongamos que queremos crear un suelo de color azul para nuestro mundo, de dimensiones 100x100. Entonces, las coordenadas de las cuatro esquinas serán:

50,0,50-50,0,50-50,0,-50 50,0,-50

Vamos a añadir el campo solid FALSE, visto en el apartado anterior. Este es el resultado. Pero si se carga el escenario, en principio no se verá nada. Esto es debido a que el punto de vista por defecto está precisamente a nivel cero, es decir, en el mismo suelo. Sólo se verá el suelo si se hace girar todo el escenario.

Determinando un punto de vista inicial elevado sobre el suelo (se verá más adelante cómo conseguirlo), y superponiendo unos ejes coordenados, obtenemos el resultado que se puede ver en la imagen de la derecha (pulsarla para cargar el escenario).

Obsérvese que al cargar el escenario, se "aterriza" sobre el suelo, y que se puede desplazar por él, pero no se pueden efectuar movimientos de elevación. Esto es debido, a que automáticamente se determina que

Page 144: Manual Vrml 2012

existe gravedad en el mundo. Para poder flotar, hay que pulsar el mando "Float", que inhabilita la gravedad.

Con este método obtenemos un suelo del color que queramos, pero se pueden obtener suelos que tengan una textura determinada (hierba, piedra, etc.), lo que se verá más adelante.

Con el nodo IndexedFaceSet se crean suelos planos. En el siguiente capítulo se verá cómo crear suelos accidentados (terrenos con ditintas elevaciones, colinas, etc.).

Ejercicio práctico

Partiendo de estos cuatro puntos, de coordenadas:

5 5 0, # punto 0 15 9 0 # punto 1 20 18 0 # punto 2 20 0 15 # punto 3

Se propone crear tres caras contiguas, visibles por ambos lados y de distinto color, de la siguiente manera:

Una cara verde, con los puntos 0-1-2 Una cara amarilla, con los puntos 1-2-3 Una cara azul, con los puntos 0-1-3

En el campo point se pondrán las coordenadas de los 4 puntos, que tienen una numeración del 0 al 3.

En el campo coordIndex se expresará que existen tres caras formadas por sus respectivos puntos. Por tanto quedará así:

coordIndex [ 0, 1, 2, -1, # primera cara 1, 2, 3, -1, # segunda cara 0, 1, 3, -1 #tercera cara ]

Como hay tres colores, el campo color deberá ser:

color [ 0 1 0, # color 0 (verde) 1 1 0, # color 1 (amarillo) 0 0 1 # color 2 (azul) ]

Page 145: Manual Vrml 2012

En el campo colorIndex se expresará que el orden de los colores atribuidos es el 0 (verde) para la primera cara, el 1 (amarillo), para la segunda y 2 (azul), para la tercera

colorIndex [ 0, 1, 2 ]

Además, se añadirán los campos colorPerVertex FALSE y solid FALSE (para que sean visibles por ambos lados).

Guardar el fichero con el nombre de caras12.wrl. Este es el resultado y este es el texto.

A la derecha puede verse este ejercicio práctico al que se ha modificado el punto de vista inicial y añadido unos ejes coordenados (pulsar la imagen para cargar el escenario).

#VRML V2.0 utf8 #Ejercico practico del capitulo 12: Tres caras de distinto color, visibles por ambos lados Shape {

geometry IndexedFaceSet { coord Coordinate {

point [5 5 0, #este es el punto 0

15 9 0, #este es el punto 1 20 18 0, #este es el punto 2

25 0 15 #este es el punto 3 ]

} coordIndex [

0, 1, 2, -1, #primera cara1, 2, 3, -1, # segunda cara0, 1, 3, -1 #tercera cara

]color Color {

color [ 0 1 0, #color 0 verde

1 1 0, # color 1 (amarillo)0 0 1 # color 2 (azul)

] }

Page 146: Manual Vrml 2012

colorIndex [ 0, 1, 2 #orden de atribucion de los colores

]colorPerVertex FALSEsolid FALSE

} }

11. Formas complejas. LíneasNodo IndexedLineSet, para crear líneas

Con este nodo se crean líneas, uniendo una serie de puntos determinados. Su estructura resumida es la siguiente:

IndexedLineSet { coord Coordinate { point [ . . . ] } coordIndex [ . . . ] }

Como se puede ver, tiene dos campos:

coord, cuyo valor es el nodo Coordinate, y que sirve para determinar las coordenadas de los puntos aislados que se van a unir entre sí para formar las líneas. Se definió en el capítulo anterior.

coordIndex, con este campo se define el orden con el que se unen los puntos entre sí, dónde empieza y acaba una línea, etc., como vamos a ver a continuación.

Veamos primero un ejemplo sencillo: tres puntos que se unen ordenadamente entre sí, para formar una línea:

IndexedLineSet { coord Coordinate { point [ 5 5 0, # este es el punto 0 15 9 0, # este es el punto 1 20 18 0 # este es el punto 2 ] } coordIndex [ 0, 1, 2, -1 ] }

En el campo coord se establecen las coordenadas de los tres puntos (tal como se vió en el capítulo anterior.) A cada coordenada se ha añadido una línea de comentario para indicar cuál es la numeración que le corresponde al punto. Obsérvese que se comienza por 0 (y no por 1).

Page 147: Manual Vrml 2012

En el campo coordIndex se establece el orden en el que se unen los tres puntos. En este caso la línea empieza en el primero (el 0), sigue con el segundo (el 1) y acaba en el tercero (el 2). Con el valor -1 se indica que ahí acaba la línea.

Inclusión del nodo IndexedLineSet en el nodo Shape

Como se vió en el cap. anterior, para que un nodo pueda verse, debe estar incrustado en el nodo Shape. Por tanto, de manera resumida, la inclusión del nodo IndexedLineSet en el nodo Shape se hará de esta manera:

Shape {geometry IndexedLineSet { ... }

}

No se ha especificado ningún campo para su apariencia ni color, lo que se verá más adelante.

Desarrollando el ejemplo, quedará de esta manera:

#VRML V2.0 utf8 #Ejemplo de linea uniendo tres puntos, sin definicion del color

Shape { geometry IndexedLineSet { coord Coordinate { point [ 5 5 0, #este es el punto 0 15 9 0, #este es el punto 1 20 18 0 #este es el punto 2 ] } coordIndex [ 0, 1, 2, -1 ] } }

Es te es el resultado (se han superpuesto unos ejes coordenados y modificado el punto de vista inicial).

En el ejemplo, se han unido los puntos según el orden en el que están especificados en el campo point (0,1,2), pero se pueden unir en el orden que se desee, como por ejemplo (0,2,1), con lo que resultará una línea distinta. Habría que modificar el campo coordIndex, que quedaría de esta manera:

coordIndex [ 0, 2, 1, -1 ]

Este es el resultado.

Page 148: Manual Vrml 2012

Se pueden crear simultáneamente diversas líneas. Supongamos que en el campo point se han especificado las coordenadas de 12 puntos (por tanto, del 0 al 11), y queremos crear dos líneas, la primera con los 6 primeros puntos y la segunda con los 6 últimos. El campo coordIndex quedaría de esta manera:

coordIndex [ 0, 1, 2, 3, 4, 5, -1, #esta es una línea 6, 7, 8, 9, 10, 11, -1 #esta es otra línea ]

El color en las líneas

Para determinar el color de cada uno de los segmentos que compone la línea, hay que hacer uso de tres campos más:

color colorIndex colorPerVertex

Con el campo color se especifican cuántos y qué colores se van a usar (en el caso de que haya más de una línea). Este campo se vió en el cap. anterior.

Con el campo colorIndex se atribuye a cada una de las líneas existentes alguno de los colores expresados en el campo anterior.

Con el campo colorPerVertex se especifica si los colores serán colores continuos, o un gradiente entre dos colores.

Veamos una aplicación en el ejemplo anterior: una única línea quebrada que une tres puntos, se va a hacer que sea toda ella de color verde.

#VRML V2.0 utf8 #Ejemplo de linea de color verde, uniendo tres puntos

Shape { geometry IndexedLineSet { coord Coordinate { point [ 5 5 0, #este es el punto 0 15 9 0, #este es el punto 1 20 18 0 #este es el punto 2 ] } coordIndex [ 0, 1, 2, -1 ] color Color { color [ 0 1 0 #este es el color 0 (verde), ] #el unico posible pues solo hay una linea } colorIndex [

Page 149: Manual Vrml 2012

0 #a la unica linea se le atribuye el unico color 0 ] colorPerVertex FALSE } }

En el campo color se especifica el color (o los colores, si hay más de una línea)

En el campo colorIndex se atribuye el color a la la línea (o líneas, si hay más de una). Este campo hace una función análoga con los colores y las líneas a la del campo coordIndex con los puntos y las líneas.

En este ejemplo sólo hay una línea con un único color. En el ejercicio práctico se va ver un caso de dos líneas con dos colores.

Este es el resultado del ejemplo (se han añadido unos ejes coordenados, y se ha modificado el punto de vista inicial).

Nota: Se omite la explicación del caso colorPerVertex TRUE (para conseguir líneas con colores en gradiente), por su complicación y escasa utilidad, pero sobre todo porque provoca inestabilidad en los visores de VRML (por lo menos en el mío :-)

Ejercicio práctico

En el ejercicio práctico del capítulo anterior se creó un grupo de 10 puntos verdes y otro de 10 puntos amarillos.

Ahora se propone crear una línea verde que una los diez primeros puntos, y otra línea amarilla que una los 10 últimos.

En el campo point se pondrán las coordenadas de los 20 puntos, que tienen una numeración del 0 al 19.

En el campo coordIndex se expresa que existen dos líneas: la primera uniendo ordenadamente los puntos 0 al 9, y la segunda del 10 al 19. Por tanto quedará así:

coordIndex [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, # primera linea 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -1 #segunda linea ]

Como hay dos colores, el campo color deberá ser:

color [ 0 1 0 # color 0 (verde) 1 1 0 # color 1 (amarillo) ]

Page 150: Manual Vrml 2012

En el campo colorIndex se expresará que el orden de los colores atribuidos es el 0 (verde) para la primera línea y el 1 (amarillo), para la segunda:

colorIndex [ 0, 1 ]

Guardar el fichero con el nombre de lineas11.wrl Este es el escenario y éste es el texto de este fichero

#VRML V2.0 utf8#Ejercicio practico del capitulo 11#Dos lineas de color, verde y amarilla, uniendo dos conjuntos de 10 puntos

Shape {geometry IndexedLineSet {

coord Coordinate {point [

# Coord. del primer grupo de 10 puntos1 1 0, 2 4 0, 3 5 0, 4 4 0, 5 6 0, 6 7 0, 7 5 0, 8 6 0, 9 4 0, 10 3 0,# Coord. del segundo grupo de 10 puntos1 3 0, 2 2 0, 3 2 0, 4 1 0, 5 2 0, 6 4 0, 7 3 0, 8 5 0, 9 5 0, 10 6 0

]}coordIndex [

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, # primera linea

10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -1 #segunda linea ]

]color Color {

color [0 1 0 # color 0 (verde)1 1 0 # color 1 (amarillo)

]}

Page 151: Manual Vrml 2012

colorIndex [0, 1

]colorPerVertex FALSE

}}

10. Formas complejas. PuntosFormas complejas

Hasta ahora, para crear los distintos objetos que forman un escenario de realidad virtual, se han utilizado exclusivamente las formas primitivas (caja, cono, cilindro y esfera), que se definieron en el capítulo 4 (Nodos primitivos).

Tal como se ha visto en los capítulos anteriores, agrupando y modificando estas formas primitivas se pueden conseguir otras formas más complejas.

Pero esta técnica tiene un límite. Supongamos que se quiere representar un automóvil, por ejemplo. Con la sola utilización de las formas primitivas sería demasiado complicado de crear, y se generarían ficheros VRML demasiado voluminosos.

Hay un método más eficaz para construir las formas complejas, que consiste en definir una serie de puntos en el espacio y luego unirlos entre sí para crear líneas o superficies.

Nodo Coordinate

Este nodo sirve simplemente para definir una serie de puntos en el espacio tridimensional. En sí mismo no sirve para representarlos, sino que se utilizará dentro de otros nodos, como se va a ver a continuación.

La estructura de este nodo es la siguiente:

Coordinate { point [ 12 11 17.1, 20.5 13.8 5.3, 14 6.1 22.9 ] }

Como se puede ver, tiene un campo point, cuyo valor son grupos de tres cifras, separadas por comas, englobadas entre corchetes [ y ].

Cada grupo de tres cifras representa un punto en el sistema de coordenas (según se vió en el capítulo 8). En el ejemplo están definidos tres puntos, pero se pueden poner tantos como se quiera.

Page 152: Manual Vrml 2012

Este nodo se utiliza dentro de otros nodos, para conseguir cosas distintas:

PointSet - para crear puntos aislados IndexedLineSet - para crear líneas IndexedFaceSet - para crear caras (superficies)

Nodo PointSet, para crear puntos aislados

Su estructura es:

PointSet { coord Coordinate { point [ . . . ] } }

Como se puede ver, tiene un campo coord cuyo valor es el nodo Coordinate visto anteriormente.

Aplicando al ejemplo del nodo Coordinate, quedaría de esta manera:

PointSet { coord Coordinate { point [ 12 11 17.1, 20.5 13.8 5.3, 14 6.1 22.9 ] } }

Si incluyéramos este código, tal como está, en un documento VRML, no podríamos ver ninguno de los puntos todavía. La razón es que, como se vió en el capítulo 5, para crear un objeto visible se debe utilizar el nodo Shape.

Inclusión del nodo PointSet en el nodo Shape

Como se vió en el capítulo 5, la estructura general del nodo Shape es:

Shape {appearance ...geometry ...

}

Con el campo appearance se define la apariencia del objeto (color, textura, etc.) y con el campo geometry su forma.

Por tanto, es evidente que la inclusión del nodo PointSet deberá hacerse en este último campo, ya que la geometría de este objeto es la de un grupo de puntos. De manera resumida, quedará de esta manera:

Page 153: Manual Vrml 2012

Shape {appearance ...geometry PointSet { ... }

}

Desarrollando totalmente el ejemplo:

#VRML V2.0 utf8 #Ejemplo de un grupo de tres puntos Shape { appearance Appearance { material Material { } } geometry PointSet { coord Coordinate { point [ 12 11 17.1, 20.5 13.8 5.3, 14 6.1 22.9 ] } } }

Pulsando aquí se carga el escenario con los tres puntos, al que se le han añadido unos ejes coordenados. Se podrá observar que se ven los puntos con la apariencia por defecto (es decir, sin color ni textura). Pero los puntos pueden tener color si se desea.

Color en los puntos

Hasta ahora hemos considerado que el nodo PointSet tenía un solo campo (coord), que sirve para definir la posición de los puntos. Pero puede tener también otro campo (color), que sirve para definir el color de cada uno de los puntos.

Es decir, el nodo PointSet puede tener esta estructura (resumida):

PointSet { coord Coordinate { point [ . . . ] } color Color { color [ . . . ] } }

Como se puede observar, el campo color tiene como valor el nodo Color, que a su vez tiene como valor el campo color de nuevo.

Desarrollando totalmente el ejemplo:

Page 154: Manual Vrml 2012

#VRML V2.0 utf8 #Ejemplo de un grupo de tres puntos con colores

Shape { geometry PointSet { coord Coordinate { point [ 12 11 17.1, #1º punto 20.5 13.8 5.3, #2º punto 14 6.1 22.9 #3º punto ] } color Color { color [ 1 0 0, # 1º punto rojo 0 1 1, # 2º punto verde 1 1 0 # 3º punto amarillo ] } } }

Obsérvese que se ha prescindido del campo appearance del nodo Shape, que había en el ejemplo anterior, ya que no es necesario, pues los puntos no van a tener la apariencia por defecto, sino la que se determina en el campo color.

En el campo color se puede observar que hay (entre corchetes) tres grupos de números, separados por comas. Cada grupo de tres cifras representa un color, para cada punto expresado en el campo point, y correspondiéndose en el mismo orden. (Ver en el capítulo 13 el código de colores)

Pulsando aquí se carga el escenario con los tres puntos con sus correspondientes colores. Se han añadido unos ejes coordenados, y se ha forzado el punto de vista inicial para poder obsevarlos mejor.

Ejercicio práctico

Como ejercicio práctico de este capítulo se propone definir dos grupos de 10 puntos, el primero de ellos de color verde y el segundo de color amarillo.

Las coordenadas de los 10 puntos verdes son las siguientes:

1 1 0 2 4 0 3 5 0 4 4 0 5 6 0 6 7 0 7 5 0 8 6 0

Page 155: Manual Vrml 2012

9 4 0 10 3 0

y las coordenadas de los 10 puntos amarillos son las siguientes:

1 3 0 2 2 0 3 2 0 4 1 0 5 2 0 6 4 0 7 3 0 8 5 0 9 5 0 10 6 0

Guardar el fichero del ejercicio con el nombre de puntos10.wrl Este es el escenario, y éste es el texto del ejercicio.

En el ejercicio práctico del capítulo siguiente, se van a unir entre sí los puntos del primer grupo para formar una línea verde, y los del segundo para formar otra línea amarilla.

#VRML V2.0 utf8#Web3D. Manual de VRML - http://www.wmaestro.com/web3d#Ejercio práctico del capítulo 10: 10 puntos verdes y 10 puntos amarillos

Shape {geometry PointSet {

coord Coordinate {point [

# Coord. del primer grupo de 10 puntos1 1 0, 2 4 0, 3 5 0, 4 4 0, 5 6 0, 6 7 0, 7 5 0, 8 6 0, 9 4 0, 10 3 0,# Coord. del segundo grupo de 10 puntos1 3 0, 2 2 0, 3 2 0, 4 1 0, 5 2 0, 6 4 0, 7 3 0, 8 5 0, 9 5 0, 10 6 0

]}color Color {

Page 156: Manual Vrml 2012

color [# Definicion del color verde para los

primeros 10 puntos:0 1 1, 0 1 1, 0 1 1, 0 1 1, 0 1 1, 0 1 1, 0 1 1, 0 1 1, 0 1 1, 0 1 1, # Definicion del color amarillo para los 10

ultimos puntos:1 1 0,1 1 0,1 1 0,1 1 0,1 1 0,1 1 0,1 1 0,1 1 0,1 1 0,1 1 0

]}

}

}

9. Nodos Switch y Billboard

En este capítulo se van a estudiar dos nodos que también sirven para agrupar otros nodos: el nodo Switch y el nodo Billboard.

Nodo Switch

Este nodo Switch (en inglés, bascular o conmutar) sirve para agrupar otros nodos, pero con una diferencia: sólo será utilizado uno de los hijos agrupados.

Su estructura es la siguiente:

Switch { whichChoice 0 choice [...] choice [...] choice [...] }

Como se puede ver, este nodo tiene un campo whichChoice (en inglés, cuál elección) cuyo valor es un número que indica cúal hijo choice es el elegido (0, 1, 2, etc.). Si este valor es -1, entonces se indica que no está elegido ninguno.

Page 157: Manual Vrml 2012

¿Qué utilidad tiene este nodo? Un posible uso de este nodo es el de tener preparadas diferentes versiones del nodo Shape (ver cap. 5), es decir, diferentes formas de un objeto. Bastará con variar el valor de whichCoice para pasar rápidamente de una forma a otra.

Esta variación se hará utilizando los eventos, que es algo que se verá más adelante.

Nodo Billboard

Este nodo Billboard (en inglés, cartel) sirve para agrupar otros nodos hijos. Todos los nodos agrupados serán visibles (al contrario del anterior, en el que sólo es visible uno de ellos).

La particularidad de este nodo es que crea un sistema de coordenadas para los nodos agrupados que está siempre de cara al espectador.

Su estructura es la siguiente:

Billboard { axisOfRotation 0 1 0 children [ . . . ] }

Tiene un campo, axisOfRotation (eje de rotación), cuyo valor es un grupo de tres cifras que indican cuál es eje alrededor del cual se efectúa automáticamente el giro para permanecer siempre de cara. La convención que se utiliza es la misma que la vista en el capítulo anterior para la rotación, excepto que en este caso no hace falta poner un cuarto valor para expresar el ángulo:

Rotación alrededor del eje X: 1 0 0 Rotación alrededor del eje Y: 0 1 0 Rotación alrededor del eje Z: 0 0 1

A la derecha se puede ver un ejemplo de utilización de este nodo (pulsar la imagen para cargar el escenario), creado por David R. Nadeau para el manual Introduction To VRML 2.0

En el centro hay una figura agrupada con el nodo Billboard, que está siempre de cara al usuario, girando alrededor de su eje vertical. A su alrededor hay cinco fichas de color azul que han sido creadas usando el nodo Transform, y que por tanto no tienen este comportamiento.

8. Nodo Transform

Como se ha mencionado en el capítulo anterior, por defecto, todos los objetos son creados en el centro del escenario de realidad virtual.

Page 158: Manual Vrml 2012

Ahora vamos a ver cómo posicionarlos en otros puntos. Pero para ello, es necesario antes comprender la noción de los sistemas de coordenadas.

Un punto en el espacio está definido por su posición con respecto al centro de coordenadas.En el lenguaje VRML se adopta la convención de que sea X la distancia que ese punto esté desplazado a la derecha o a la izquierda del centro, Y la distancia por encima o por debajo, y Z la distancia hacia delante o hacia atrás.

Se puede ver en la imagen de la derecha una representación tridimensional de los ejes de coordenadas. Pulsándola se carga el escenario. (Se ha confeccionado utilizando cilindros muy finos, convenientemente girados para representar los ejes)

Un mundo virtual tiene su sistema de coordenadas situado en el centro. Con el nodo Group, visto en el capítulo anterior, se consigue agrupar un conjunto de objetos, que son creados haciendo coincidir su centro con el centro del sistema de coordenadas, como se puede apreciar en la figura de la derecha. (Se ha superpuesto el conjunto de objetos a los ejes coordenados)

Con el nodo Transform, que vamos a ver a continuación, se determina un nuevo

sistema de coordenadas para un grupo de objetos.

Este nuevo sistema de coordenadas sufre unas transformaciones: puede ser trasladado a un punto determinado, puede ser girado un determinado ángulo, y puede tener una escala (tamaño relativo) distinta a la original.

El grupo de objetos especificados en el nodo sufrirán las mismas transformaciones, es decir, serán trasladados, girados y variados de escala.

Estructura del nodo Transform

Su estructura general es la siguiente:

Transform { translation . . . rotation . . . scale . . . children [ . . . ] }

Como se puede ver, tiene tres campos con los que se determina su posible traslado, rotación o nueva escala, y un cuarto campo children, en donde se especifican cuáles son los objetos agrupados que sufrirán esas transformaciones.

Page 159: Manual Vrml 2012

No tienen por qué estar los tres campos a la vez. Por tanto, para simplificar, vamos a ver cada uno de ellos por separado.

Traslación

Poniendo sólo el campo translation, queda el nodo Transform de esta manera:

Transform { translation 20 0 0 children [ . . . ] }

Se ha puesto un valor al campo translation. El orden para el traslado de las coordenadas es X, Y, Z. Por tanto, en este caso, hay una traslación de 20 unidades hacia la derecha (si hubiera sido hacia la izquierda se habría puesto -20.0)

Por supuesto que se podrían haber variado las tres coordenadas, no sólo la X como en este caso.

Con respecto al campo children, se aplica lo dicho en el capítulo anterior, para el nodo Group.

Aplicando lo visto al ejemplo práctico del capítulo anterior, en el que se utilizaba el nodo Group para un conjunto de seis objetos (este era su código), éste sería el nuevo código.

RotaciónPoniendo ahora sólo el campo rotation, queda el nodo Transform de esta manera:

Transform { rotation 1 0 0 1.57 children [ ... ] }

Tal como se ha puesto el valor del campo rotation quiere decir lo siguiente: rotación de 90 º alrededor del eje X.

Explicación: Las tres primeras cifras sólo pueden tener el valor 0 ó 1, y representan la rotación alrededor de cada eje, en este orden: X, Y, Z.

Es decir:

Rotación alrededor del eje X: 1 0 0 Rotación alrededor del eje Y: 0 1 0 Rotación alrededor del eje Z: 0 0 1

Page 160: Manual Vrml 2012

La cuarta cifra representa el ángulo girado, expresado en radianes.

Para calcular la correspondencia entre grados y radianes, hay que tener en cuenta que 180º equivalen al número pi en radianes, es decir a 3.14 radianes. Por tanto, 90º sería la mitad de 3.14, es decir 1.57 radianes.

El sentido del giro es el de un sacacorchos avanzando en la dirección positiva de los ejes.

En la figura de la derecha se puede ver al grupo de objetos, trasladados 20 unidades hacia la derecha y girados 90º alrededor del eje X (pulsar la imagen para cargar el escenario), cuyo código es:

Transform { translation 20 0 0 rotation 1 0 0 1.57 children [ ... ] }

Variación de la escala

Poniendo ahora en el nodo Transform sólo el campo scale, para variar la escala de los objetos, queda de la siguiente forma:

Transform { scale 0.5 2 0.5 children [ ... ] }

Los valores del campo scale representan las variaciones de las dimensiones con respecto a los ejes X, Y , Z.

Por tanto, en el ejemplo que se ha puesto, se reducen las dimensiones en la dirección de las X a la mitad (0.5), se duplican en la dirección del eje Y (2), y se reducen a la mitad en la dirección del eje Z (0.5).

Si se hubiera variado la misma cantidad en los tres valores (por ejemplo, 0.5) se habría mantenido las proporciones de la pieza.

En la figura de la derecha se puede ver al grupo de objetos, trasladados 20 unidades hacia la derecha y variada su escala (pulsarla para cargar el escenario),

Page 161: Manual Vrml 2012

de acuerdo con el siguiente código:

Transform { translation 20 0 0 scale 0.5 2 0.5 children [ ... ] }

Combinando los tres campos simultáneamente (traslación, giro y cambio de escala), su código sería:

Transform { translation 20 0 0 rotation 1 0 0 1.57 scale 0.5 2 0.5 children [ ... ] }

Se puede ver en la figura de la derecha la pieza después de sufrir los tres cambios (pulsarla para cargar el escenario).

En todos los ejemplos de este capítulo se ha utilizado el mismo grupo de seis objetos definidos en el campo children. Pero dentro del campo children puede haber un único objeto, no tienen por qué ser siempre varios objetos.

Ejercicio práctico

Ahora que sabemos cómo colocar los objetos en distintas posiciones, vamos a desarrollar el escenario de los planetas, que se comenzó como ejercicio práctico del capítulo 5.

Partiendo del documento VRML planetas05.wrl, en el que se creó una esfera de radio 10, se va a crear un nuevo documento con el nombre de planetas08.wrl, en el que se van a crear los siguientes objetos:

El planeta WebMaestro, que es la esfera de 10 de diámetro, situada en el centro, que ya estaba creada en el ejercicio planetas05.wrl

El planeta WebStore, que es una esfera de radio 1, trasladada a las coordenadas 10.0 6.0 10.0

Page 162: Manual Vrml 2012

El planeta Chat de WMaestro, que es una esfera de radio 1, trasladada a las coordenadas 25.0 1.0 -7.0

El planeta Web3D que es un cubo de lado 1, que se creó en el ejercicio del capítulo 5, cuborot05.wrl y que debe ser trasladado a las coordenadas -8.0 8.0 27.0

El letrero de bienvenida, que se creó en el ejercicio del capítulo 6 con el nombre de texto06.wrl, y que debe ser trasladado a las coordenadas -7.0 9.0 25.0

Este es el texto del documento planetas08.wrl

La imagen de la derecha es el escenario de planetas08.wrl (pulsar para cargarlo).

Los cuerpos todavía no tienen ninguna textura o color, y faltan las animaciones del cubo giratorio y de la luna alrededor del planeta WebMaestro.

Además el punto de vista inicial es el que hay por defecto. Por tanto, puede ocurrir que el visor se sitúe inicialmente en un sitio inapropiado (como es el caso del Cosmo Player 2.0, que se sitúa dentro de la esfera mayor). En este caso, será necesario alejarse, utilizando el mando Zoom. Más adelante se verá cómo forzar para que sea el que nos interese.

En la imagen de la derecha (pulsar para cargar el escenario), se puede ver el escenario del ejercicio práctico al que se le han superpuesto los ejes coordenados, para que se puedan apreciar mejor las posiciones relativas entre los distintos cuerpos. Además, se ha forzado el punto de vista inicial, para que sea uno conveniente.

#VRML V2.0 utf8#Ejercio práctico planetas08.wrl

#Planeta WebMaestroShape {

appearance Appearance {material Material {}

}geometry Sphere {

radius 10}

}

#Planeta WebStoreTransform {

Page 163: Manual Vrml 2012

translation 10 6 10children [

Shape {appearance Appearance {

material Material {}}geometry Sphere {

radius 1}

}]

}

#Planeta Chat de WMaestroTransform {

translation 25 1 -7children [

Shape {appearance Appearance {

material Material {}}geometry Sphere {

radius 1}

}]

}

#Planeta Web3DTransform {

translation -8 8 27children [

Shape {appearance Appearance {

material Material {}}geometry Box {

size 1 1 1}

}]

}

#Letrero de bienvenidaTransform {

translation -7 9 25children [

Shape {appearance Appearance {

material Material {}}geometry Text {

string [" Bienvenido",

" a WMaestro!", "Aterriza en tu planeta preferido"

]

Page 164: Manual Vrml 2012

}}

]}

7. Agrupación de nodos. Nodo GroupAgrupación de nodos

Hasta ahora hemos visto los objetos aisladamente. Veamos ahora cómo podemos agrupar un conjunto de ellos para conseguir formas más complejas. En los próximos tres capítulos se van a ver diferentes nodos que sirven para agrupar otros nodos:

Nodo Group (cap. 7) Nodo Transform (cap. 8) Nodo Switch (cap. 8a) Nodo Billboard (cap. 8a)

Nodo Group

Existe el nodo Group que permite tratar a un conjunto de nodos como una entidad única, pero sin efectuar ninguna transformación en ellos.

Su estructura general es la siguiente:

Group {children [ ... ]

}

Tiene un campo llamado children (en inglés, niños o hijos), cuyo valor (los puntos suspensivos) va entre corchetes [ y ], y que como veremos a continuación, es la lista de los objetos que se quieren agrupar, representados por sus nodos Shape respectivos:

Group {children [

Shape { ... },Shape { ... },...

] }

Veamos un ejemplo: Vamos a agrupar los ejemplos de una caja y de un cono vistos en el capítulo 5:

#VRML V2.0 utf8#Ejemplo de agrupación de una caja y un cono

Page 165: Manual Vrml 2012

Group { children [ #Aquí empieza la caja: Shape { appearance Appearance { material Material { } } geometry Box { size 2 0.5 3 } }, #Aquí empieza el cono: Shape { appearance Appearance { material Material { } } geometry Cone { height 3 bottomRadius 0.75 } } ]}

Véase el resultado en la imagen de la derecha (pulsándola se carga el escenario). Se puede observar que la caja y el cono están superpuestos. Esto es debido a que los objetos son creados todos en el mismo punto: en el centro del escenario de realidad virtual.

Para colocar un objeto, o grupo de objetos, en otros puntos que no sean el centro, se deberá utilizar otro tipo de nodo, como se verá más adelante.

Consejos prácticos para escribir el código

A lo largo de los capítulos hemos ido viendo la sintaxis de cada nodo y la manera de cómo se incrustan unos nodos dentro de otros, etc., para poder confeccionar los correspondientes documentos VRML.

Si observamos el último ejemplo, parece como si el código se complicara más y más (a pesar de tratarse de un ejemplo relativamente sencillo).

No hay tal complicación, pero sí es muy importante seguir unas cuantas reglas prácticas, pues es absolutamente imprescindible que las cosas estén colocadas en el orden debido, y que no sobre ni falte ninguno de los símobolos de apertura y de cierre { y }, [ y ]

Utilizar una línea distinta para cada nodo, para cada campo y para cada valor de cada campo.

Page 166: Manual Vrml 2012

No es que sea obligatorio, pues de hecho se podría escribir todo el código en una sola línea, aunque esto no sería muy práctico e induciría a cometer errores.

Como comprobación, véase aquí el código del ejemplo anterior escrito en una sola línea (se han omitido las líneas de comentarios, pues éstas sí que requieren forzosamente estar en una línea aparte). Y véase aquí el escenario generado por ese código. Se puede comprobar que es exactamente el mismo que el generado por el código escrito en múltiples líneas.

Indentar cada línea, según su jerarquía.

(Para indentar, es muy útil utilizar la tecla tabuladora, que desplaza el cursor un número fijo de espacios).

Veamos lo que se quiere decir, observando el ejemplo anterior. El nodo Group, que es el nodo raíz, no está indentado. Este nodo tiene un sólo campo (children), que se indenta una vez. Children tiene como valor dos nodos Shape, que se indentan dos veces (o sea que ambos están al mismo nivel). Cada nodo Shape tiene a su vez dos campos (appearance y geometry), que se indentan tres veces. Estos últimos tienen sus respectivos campos, que se indentan cuatro veces, etc. etc.

Colocar cada símbolo de cierre en el nivel de indentación que le corresponda.

Así vemos en el ejemplo que el símbolo de cierre } de Group no tiene ninguna indentación (está situado al final del todo). El símbolo de cierre ] de children tiene una indentación (como el campo children). Los de los nodos Shape, tienen dos indentaciones, etc.

De esta manera, vemos que los símbolos de cierre están situados exactamente debajo del comienzo de la línea que le corresponde. De esta manera están perfectamente identificados, y sirve como control para no olvidarse de ninguno de ellos.

Poner las líneas de comentario necesarias al mismo nivel que lo que se comenta.

Así, en el ejemplo, el comentario "#Aquí empieza la caja:" se indenta dos veces, para que esté situado en el mismo nivel que el nodo Shape, que es el objeto del comentario.

Poniendo nombres propios a los nodos

Podemos observar en el ejemplo que se ha repetido dos veces el nodo Appearance, para dotar de la misma apariencia por defecto a los dos objetos (la caja y el cilindro).

No es tan grave en este caso, pero imaginemos que se quiere dotar de esa misma apariencia, por ejemplo a cinco objetos distintos (como va a ser el caso del ejemplo práctico de este capítulo). Entonces, habría que repetir cinco veces todo el nodo Appearance en cada uno de los cinco objetos, lo cual sería bastante engorroso, además de complicar innecesariamente el código.

Hay una solución prevista para simplificar estas repeticiones, y es que se puede definir un nodo que se piensa repetir en el código, poniéndole un nombre arbitrario.

Supongamos, por ejemplo, que se van a utilizar repetidamente en un escenario unos cilindros exactamente iguales (que podrían ser las columnas de una casa), y que dichos cilindros tienen el siguiente código:

Page 167: Manual Vrml 2012

Shape { appearance Appearance { material Material { } } geometry Cylinder { height 2 radius 0.5 }}

(Este es el código de un cilindro con la apariencia por defecto, de 2 unidades de alto y una base de radio 0.5)

Se puede definir, para el ámbito de un documento VRML, que este tipo de cilindro tenga un nombre arbitrario, por ejemplo ColumnaRepetida (o como se quiera, con tal de que comience por mayúscula), de la siguiente manera:

DEF ColumnaRepetida Shape { appearance Appearance { material Material { } } geometry Cylinder { height 2 radius 0.5 }}

Entonces, cada vez que se quiera usar este nodo en otra parte del documento, basta con poner lo siguiente:

USE ColumnaRepetida

En el ejemplo anterior de la caja y el cono, lo que está repetido es el nodo Appearance. Vamos a definirlo, en la primera ocasión que se utiliza con el nombre, por ejemplo, PorDefecto y en la segunda vez utilizar sólo el comando USE (se omiten las líneas de comentarios):

#VRML V2.0 utf8#Ejemplo de agrupación de una caja y un cono,#haciendo uso de los comandos DEF y USE.

Group { children [ Shape { appearance DEF PorDefecto Appearance { material Material { } } geometry Box { size 2 0.5 3 } }, Shape {

Page 168: Manual Vrml 2012

appearance USE PorDefecto geometry Cone { height 3 bottomRadius 0.75 } } ]}

En este caso concreto, la simplificación no ha sido muy grande (sólo un par de líneas menos de código), pero ha servido para ilustrar el concepto.

Ejercicio práctico

Para practicar con los conceptos aprendidos en este capítulo (nodo Group y comandos DEF y USE), se propone la realización de la pieza que se puede ver a la derecha (pulsándola se carga el escenario).

Nota:Al tratar de visualizar este ejemplo, puede ocurrir que inicialmente no se vea nada. La razón de esto es que algunos visualizadores (entre ellos el Cosmo Player 2.0) se sitúan en el centro mismo del escenario. En ese caso, es necesario retroceder, utilizando el mando Zoom.

Más adelante se verá la manera de forzar al visualizador para que se sitúe en el punto que más nos convenga.

Está compuesta por los siguientes objetos:

Una caja de 10x10x10 (un cubo) Una esfera de radio 7 Un cilindro de altura 0.5 y radio de la base 12.5 Otro cilindro de altura 20 y radio de la base 4 Otro cilindro de altura 30 y radio de la base 3 Otro cilindro de altura 60 y radio de la base 1

Guardar el documento VRML con el nombre de pieza07.wrl Pulsando aquí se puede ver el texto del documentodocumento.

#VRML V2.0 utf8

Page 169: Manual Vrml 2012

#Ejercicio práctico pieza07.wrl

Group { children [ Shape { appearance DEF PorDefecto Appearance { material Material { } } geometry Box { size 10 10 10 } }, Shape { appearance USE PorDefecto geometry Sphere { radius 7 } }, Shape { appearance USE PorDefecto geometry Cylinder { radius 12.5 height 0.5 } }, Shape { appearance USE PorDefecto geometry Cylinder { radius 4 height 20 } }, Shape { appearance USE PorDefecto geometry Cylinder { radius 3 height 30 } }, Shape { appearance USE PorDefecto geometry Cylinder { radius 1 height 60 } } ]}

6. Nodo Text

En los mundos virtuales será a menudo necesario utilizar textos para guiar al visitante (en forma de carteles, comentarios, paneles de control, etc.) Para ello existe un nodo específico, el nodo

Page 170: Manual Vrml 2012

Text que, al igual que los nodos primitivos, irá incrustado en el nodo Shape, como se verá más adelante.

Los textos son siempre planos y no tienen espesor. Se puede determinar el tipo de fuente, su estilo y tamaño, etc.

Estructura del nodo Text

Su estructura general es la siguiente:

Text {string ...fontStyle ...

}

Tiene, por tanto, dos campos:

string: (en inglés, fila). Su valor (los puntos suspensivos) es precisamente el texto que se quiere poner.

fontStyle: su valor (los puntos suspensivos) es un sub-nodo llamado FontStyle (obsérvese una vez más que el primero empieza por minúscula, por ser un campo, mientras que el segundo lo hace por mayúscula, por ser un nodo).

El campo fontStyle es opcional. Si se omite, el texto tendrá el estilo de fuente por defecto.

Veamos cada campo por separado:

Valor del campo string (el texto)

Se pone de esta manera:

string ["Esta es la primera fila de texto", "esta es la segunda fila", "etc."]

Como se puede ver, cada fila de texto va entre comillas, con una coma al final de cada línea, y todo ello englobado entre corchetes: [ y ]

Nodo FontStyle

Veamos su estructura con un ejemplo:

FontStyle {family "SERIF",style "BOLD",size 1spacing 1

}

Page 171: Manual Vrml 2012

En este ejemplo, el nodo FontStyle tiene los siguientes campos:

family: Determina la familia de fuente. Se puede escoger entre "SERIF", "SANS" o

"TYPEWRITER" (en inglés, máquina de escribir). Obsérvese que los nombres están en mayúsculas.

style: Se puede escoger entre "BOLD" (negrita), "ITALIC" (cursiva), "BOTH" (ambas, es decir, negrita y cursiva), o "NONE" (ninguna, es decir, ni negrita ni cursiva).

size: Determina el tamaño de la fuente, pero en unidades VRML. Es decir, que si se adopta que la unidad equivale a un metro (escala aconsejada, pero no obligatoria), en el caso del ejemplo las letras se supone que tienen un metro de altura.

spacing: Determina la separación entre líneas, también en unidades VRML.

Existen más campos que los que aparecen en este ejemplo, con los que se puede afinar aún más la disposición del texto:

justify: Determina la justificación del texto. Puede ser "BEGIN" (al comienzo, es decir a la izquierda), "MIDDLE" (en el medio, es decir, centrado) o "END" (al final, es decir, a la derecha).

otros: que se omiten aquí, pues están pensados para idiomas exóticos, como el chino (escritura en vertical), el árabe (escritura de derecha a izquierda), etc. Para la lista completa, se puede consultar la RFC 1766

Nodo Text completo

Poniendo ahora el nodo texto completo, con sus dos campos, queda de esta forma:

Text {

string ["Esta es la primera fila de texto","esta es la segunda fila","etc."]

fontStyle FontStyle {family "SERIF",style "BOLD",size 1spacing 1

}

}

Integrando el nodo Text en el nodo Shape

El nodo Text se incrusta en el nodo Shape, de la misma manera que se hacía con los nodos primitivos. En el capítulo anterior vimos que el nodo Shape tenía esta estructura:

Shape {appearance ...geometry ...

}

Page 172: Manual Vrml 2012

Vimos que los nodos primitivos se ponían como valor del campo geometry. Es lo mismo que vamos a hacer ahora:

Shape {appearance ...geometry Text { ... }

}

Aquí está de una manera resumida. Para desarrollarlo completamente, hay que poner como campo de appearance la apariencia por defecto (ver cap. anterior), y lógicamente, el nodo Text completo.

Puedes ver: el documento VRML y el escenario de realidad virtual con este texto.

Como se puede ver en la imagen, el texto se puede manipular como cualquier otro objeto (girándolo, etc.), ya que, en realidad, es un elemento plano de espesor cero.

Las letras tienen el color por defecto, ya que se ha utilizado la apariencia por defecto. Pero se puede hacer que tengan el color que se desee, según veremos más adelante.

Ejercicio práctico

Como ejercicio práctico de este capítulo, se a confeccionar el texto que aparece en primer término en el escenario planetas.wrl

El nodo Text va a tener sólo el campo string (no va a tener, por tanto el campo fontStyle). El valor del campo string van a ser las siguientes tres filas de texto:

"Bienvenido" "a WMaestro!" "aterriza en tu planeta preferido"

Para que queden las palabras centradas, se deben poner 14 espacios en blanco antes de la palabra Bienvenido, y 13 antes de la frase "a WMaestro!"

El documento VRML se debe guardar con el nombre de texto06.wrl, junto con los otros ejercicios.

Este es el documento y este el escenario.

VRML V2.0 utf8 #Ejercicio práctico texto06.wrl

Page 173: Manual Vrml 2012

Shape {appearance Appearance {

material Material { }}

geometry Text {string [" Bienvenido",

" a WMaestro!", "Aterriza en tu planeta preferido"]}

}

5. Nodo Shape

Como se indicó en el capítulo anterior, para crear un objeto visible se debe utilizar el nodo Shape.

Este nodo tiene dos campos: appearance y geometry. Con el primero se controla la apariencia del objeto (color, textura, iluminación, etc.) y con el segundo su geometría.

Por tanto, la estructura general del nodo es:

Shape {appearance ...geometry ...

}

Los puntos suspensivos representan los valores de cada campo.

El primer campo (appearance) es opcional, y se puede prescindir de él, lo que vamos a hacer de momento por motivo de sencillez en la explicación. O sea, que el nodo quedaría de esta manera:

Shape {geometry ...

}

Pero el valor del campo geometry (los puntos suspensivos) es precisamente uno de los cuatro nodos primitivos que hemos visto en el capítulo anterior (Box, Cone, Cylinder y Sphere).

Escojamos el primero de ellos (Box), del ejemplo del capítulo anterior, y pongámoslo como valor del campo geometry:

Shape {geometry Box {size 2 0.5 3}

}

Con esto hemos definido un objeto visible (aunque todavía sin ningún atributo de apariencia definido), que tiene la geometría de una caja de medidas 2x0.5x3

Page 174: Manual Vrml 2012

Hemos puesto el nodo Box en una sola línea, pero conviene que lo pongamos desarrollado en varias líneas, para irnos acostumbrando, pues es muy importante que los símbolos { y } estén colocados en el orden que les corresponde, y no olvidarse de ninguno de ellos:

Shape {geometry Box {

size 2 0.5 3}

}

Ahora ya estamos en condiciones de crear el primer documento VRML con el que se podrá ver el objeto con el visualizador, aunque todavía en unas condiciones bastante imperfectas, ya que todavía no tiene definido ningún atributo de apariencia.

Para crear el documento VRML sólo falta ponerle la línea de cabecera, y algún comentario si queremos:

#VRML V2.0 utf8 #Primer documento VRML #Caja sin apariencia definida

Shape {geometry Box {

size 2 0.5 3}

}

Se guarda con el nombre que se quiera, con la extensión .wrl

En este caso, va a ser cap05_caja.wrl Para verlo en el visualizador, basta con abrir este fichero en el navegador (con el menú Archivo/Abrir).

A la derecha se puede ver el resultado. Pulsando la imagen se carga el escenario de realidad virtual.

Como se puede observar en la imagen, las caras del objeto son de color blanco y no se distinguen unas de otras, pudiéndose apreciar sólamente el contorno del objeto.

Ahora vamos a dar el siguiente paso: suministrar al objeto unas cualidades de apariencia (aunque de momento sólo van a ser las que existen por defecto)

Poniendo la apariencia por defecto

Como se ha visto al comienzo del capítulo, el nodo Shape tiene también el campo appearance, del que habíamos prescindido de momento:

appearance ...

Page 175: Manual Vrml 2012

Tenemos que poner un valor (los puntos suspensivos) al campo appearance. No va a ser un número (o un conjunto de números), sino un nodo llamado Appearance.

Obsérvese la A mayúscula de Appearance, que indica que se trata de un nodo, mientras que en el caso de appearance la a minúscula indica que es un campo (del nodo Shape).

Veamos, primero por separado, la estructura de este nuevo nodo Appearance:

Appearance {material Material { }

}

Vemos que el nodo Appearance tiene, a su vez, un campo llamado material, cuyo valor es otro nodo, llamado Material, en el que se ha dejado en blanco su contenido (no hay nada entre los símbolos { y } del nodo Material), lo que hace que estén definidas las características por defecto de este nodo.

En un capítulo posterior aprenderemos a manipular el nodo Material, para definir sus características a nuestro gusto (color, luminosidad, transparencia, etc.)

Encajando todas las piezas

Todo lo anterior puede parecer a primera vista como algo muy complicado. Pero no lo es, si consideramos que, en realidad, los nodos son como módulos de información que encajan unos en otros, formando una red (de ahí su nombre).

Es decir, algo que puede ser muy complejo, tal como un mundo virtual, está compuesto de pequeñas y simples unidades de información (los nodos) que actúan como las piezas de un mecano.

Centrándonos en el caso concreto de la caja, vamos a ensamblar las distintas piezas. Primero, coloquemos el nodo Appearance como el valor del campo appearance:

appearance Appearance {material Material { }

}

Ahora ya podemos colocar este campo dentro del nodo Shape, en el documento VRML, con algunos comentarios que faciliten su comprensión:

#VRML V2.0 utf8 #Caja con la apariencia por defecto

Shape {

#Campo appearance:appearance Appearance {

material Material { }}

Page 176: Manual Vrml 2012

#Campo geometry:geometry Box {

size 2 0.5 3}

}

Se guarda como cap05_caja1.wrl

A la derecha se puede ver el resultado. Pulsando la imagen se carga el escenario.

Como se puede apreciar en la figura (y aún más manipulándola con el visualizador), la diferencia es notable. Ahora se distinguen perfectamente las caras de la caja, debido a que tienen una iluminación y textura adecuadas.

Siguiendo un proceso similar para el nodo primitivo Cone, visto en el capítulo anterior, el documento VRML para visualizarlo (también con la apariencia por defecto), sería el siguiente:

#VRML V2.0 utf8 #Cono con la apariencia por defecto

Shape {

#Campo appearance:appearance Appearance {

material Material { }}

#Campo geometry:geometry Cone {

height 3bottomRadius 0.75

}

}

Como se puede observar, el campo appearance es idéntico al caso anterior, sólo cambia el valor del campo geometry, que es el nodo Cone.

A la derecha se puede ver el resultado. Pulsando la imagen se carga el escenario.

Para completar los cuatro casos de geometría primitiva vistos en el capítulo anterior, vamos a ver los ejemplos para el cilindro y para la esfera. Se van a omitir sus documentos VRML, por ser totalmente similares a los

Page 177: Manual Vrml 2012

anteriores.

Pulsando cada imagen se carga el escenario:

Ejercicio práctico

A lo largo de los capítulos se van a ir proponiendo ejercicios prácticos relacionados con el tema visto. Con los los distintos ejercicios se va ir creando progresivamente el siguiente escenario de realidad virtual (pulsar la imagen para cargar el escenario):

que consiste en unos planetas (unos estáticos y otros en movimiento), y que al ser pulsados conducen a páginas Web determinadas.

Como ejercicios prácticos del presente capítulo, se deben crear los documentos VRML siguientes:

Uno que contenga una esfera de radio 10, con la apariencia por defecto, que se debe guardar con el nombre de planetas05.wrl

Otro, que contenga una caja, también con la apariencia por defecto, con las tres medidas (ancho, alto y fondo) iguales a la unidad (lo que hará que sea un cubo), que se deberá guardar como cuborot05.wrl

Page 178: Manual Vrml 2012

El primero va a ser el escenario general, y el segundo el cubo rotatorio, que se va a añadir dentro de él. Conviene crear una carpeta donde ir guardando los distintos ejercicios.

Estos son los textos de los dos documentos VRML:

planetas05.wrl cuborot05.wrl

y estos son los escenarios creados con esos documentos:

planetas05.wrl cuborot05.wrl

Nota:Si se trata de visualizar el primero de ellos, puede ocurrir que inicialmente no se vea la esfera. La razón de esto es que algunos visualizadores (entre ellos el Cosmo Player 2.0) se sitúan dentro de la esfera, que es relativamente grande. En ese caso, es necesario retroceder, utilizando el mando Zoom.

Más adelante se verá la manera de forzar al visualizador para que se sitúe en el punto que más nos convenga.

4. Nodos primitivos

Los nodos son los bloques de información básicos con los que se construye un mundo virtual. Vamos a ver la sintaxis de los nodos partiendo de los más sencillos, los nodos de geometría primitiva, o nodos primitivos, que son:

Box - caja Cone - cono Cylinder - cilindro Sphere - esfera

Con estas figuras geométricas básicas, agrupándolas y modificándolas convenientemente se pueden construir formas más complicadas (lo que se va a ver en los tres capítulos que forman la sección Agrupación de nodos).

Para formas realmente complejas, hay otros procedimientos para crear objetos, partiendo de puntos, líneas o caras (se verá en la sección Formas complejas).

Box

La estructura más general de un nodo es:

Box { ... }

Se escribe el nombre del nodo, en este caso Box, seguido del símbolo de apertura {

Page 179: Manual Vrml 2012

A continuación se escribe el campo, que es un atributo del nodo que podemos cambiar a voluntad, poniendo los valores que nos interesen. En este caso servirá para establecer las dimensiones de la caja, como se verá a continuación.

A continuación se escribe el símbolo de cierre }

Con respecto a los nombres, y en general cualquier otro comando usado en este lenguaje, se debe tener muy en cuenta que son sensibles a las mayúsculas y minúsculas. Es decir, se debe escribir Box y no box, o fontStyle y no fontstyle, etc.

Sustituyendo ahora los puntos suspensivos por el campo que define este nodo, que es size (tamaño) con sus valores correspondientes (las dimensiones), queda el nodo completado de esta forma:

Box {size 2 0.5 3}

Los números representan respectivamente la anchura, la altura y el fondo. Son dimensiones abstractas, pero es conveniente, aunque no obligatorio, suponer que son metros. El nodo, por tanto, define un paralelepído (una caja) de 2 m. de ancho, 0.5 m de alto y 3 m de fondo.

Se ha escrito el nodo en una sóla línea, debido a su sencillez y a que sólo tiene un campo, pero se podría haber escrito de esta otra forma:

Box { size 2 0.5 3 }

Cone

Veamos un ejemplo de este nodo, que define la geometría de un cono:

Cone { height 3 bottomRadius 0.75 }

Como se puede observar, tiene dos campos: height (altura), al que se le ha puesto el valor de 3, y bottomRadius (radio de la base) el de 0.75. Con estos dos valores queda perfectamente definido el cono.

Cylinder

Ejemplo del nodo que define un cilindro:

Cylinder { height 2 radius 1.5 }

Tiene dos campos: height (altura) y radius (radio)

Page 180: Manual Vrml 2012

Sphere

Ejemplo del nodo que define una esfera:

Sphere { radius 1 }

Tiene un solo campo, radius (radio) pues es suficiente para definir con él una esfera.

Utilización de estos nodos

Estos cuatro nodos de geometría primitiva, que acabamos de ver, no se pueden utilizar directamente ellos solos, sino que son parte integrante de otro nodo más general, el nodo Shape (forma), que veremos en el capítulo siguiente.

Es decir, si queremos crear el cono del ejemplo, sería incorrecto crear este documento VRML:

#VRML V2.0 utf8

#Este documento es incorrecto

Cone { height 3 bottomRadius 0.75 }

Suponiendo que lo guardáramos con el nombre de cono.wrl, por ejemplo, y tratáramos de ejecutarlo en un visualizador, nos daría error o no se vería nada.

El motivo de esto es que estos nodos definen únicamente la geometría de estos cuerpos, pero no dan ninguna indicación de cuál deberá ser su apariencia, es decir, su color, textura, iluminación, etc.

En cambio el nodo Shape se encarga de ambas cosas, ya que tiene dos campos: la apariencia y la geometría, en donde utiliza precisamente estos nodos que acabamos de ver. Es decir, estos nodos irán incrustados en el nodo Shape.

Este es el tema del capítulo siguiente, donde se comenzarán a crear los primero ejemplos de mundos virtuales.

Sintaxis de los nodos

Con los ejemplos anteriores podemos entender más fácilmente el concepto y la sintaxis (reglas para la correcta escritura) de los nodos, desde un punto de vista general.

Nombre {campo1 x y zcampo2 x

Page 181: Manual Vrml 2012

... }

El nodo es un bloque de información que tiene un Nombre (Box, Cone, etc.) Obsérvese que comienzan siempre por una letra mayúscula.

Englobados entre los símbolos { y } el nodo tiene uno o varios campos (size para el nodo Box, height y bottomRadius para el nodo Cylinder, etc.) Los campos son los atributos variables del nodo. Obsérvese que comienzan con una letra minúscula.

A continuación está el valor que le asignamos a ese campo, que es un número (o conjunto de números) Estos números se escriben con punto flotante (es decir, con decimales).

En ocasiones, en lugar de colocar como valor un número (o conjunto de números) se coloca todo un nodo. Esta noción, que puede parecer confusa de momento, se aclarará en el capítulo siguiente, donde se verá con detalle el nodo Shape.

3. Documentos VRML

Para crear un mundo de realidad virtual se utiliza un fichero de texto, creado con un procesador cualquiera de textos que se debe guardar con la extensión .wrl

Este fichero constituye un documento VRML, que será ejecutado por el visualizador, de manera completamente análoga a los documentos HTML, que son ficheros de texto con la extensión .html y que son ejecutados por los navegadores para visualizar las páginas del Web.

También se pueden crear estos documentos utilizando ciertos progamas editores de VRML, que los generan automáticamente, sin necesidad de saber programar en este lenguaje. Se hablará sobre estos programas más adelante.

Estructura de los documentos VRML

En líneas generales, un documento VRML contiene los siguientes elementos:

Línea de cabecera Comentarios al código Nodos

Línea de cabecera

Todo documento VRML debe comenzar necesariamente con la siguiente línea:

#VRML V2.0 utf8

Con esta línea inicial se hace la declaración de que el estándar empleado es el VRML 2.0. El identificativo utf8 sirve para permitir el uso de caracteres internacionales.

No se debe dejar ningún espacio en blanco antes del comienzo de la línea (antes del símbolo #), pues en caso contrario el visualizador no la reconocería, y daría error al ejecutar el documento VRML.

Page 182: Manual Vrml 2012

Comentarios al código

En todos los lenguajes se utilizan comentarios al código, no visibles en la pantalla, que son muy útiles como recordatorio de lo que se ha hecho y que facilitan los cambios futuros.

En este lenguaje los comentarios se escriben en una sola línea que comienza con el símbolo #. Ejemplo:

# Este es un comentario al código

Nodos

Los nodos son bloques de información que definen las características de un objeto concreto (su forma, su apariencia, etc.), o la relación entre distintos objetos. Sirven también para crear sonidos, el panorama de fondo, enlaces a otros mundos o a páginas Web, etc.

Es decir, son las unidades básicas que forman el mundo virtual, y pueden ser afinadas hasta el detalle deseado.

En el siguiente capítulo se verá su sintaxis y algunos ejemplos.

2. Equipamiento necesario

Para poder apreciar el VRML es preciso disponer, además de una conexión a Internet y de un navegador convencional del Web, de un visualizador de VRML. Si tienes una de las últimas versiones completas de los navegadores del Web más populares, el Netscape Navigator 4.0 o el Microsoft Internet Explorer 3.0 en adelante, probablemente tienes ya instalado, como un plug-in, un visualizador de VRML.

Por otra parte, es preciso disponer de una buena conexión con Internet y de un ordenador relativamente potente y con suficiente memoria RAM.

Visualizadores de VRML

Los usuarios del Netscape Communicator 4.01 tendrán probablemente ya instalado como plug-in de VRML el Cosmo Player de Silicon Graphics. Algunas versiones anteriores incluían en su lugar el Live3D, pero Netscape ha abandonado este programa. Quien lo tenga instalado deberá cambiarlo por el anterior (el Cosmo Player), pues el Live3D no funciona correctamente con el actual

Page 183: Manual Vrml 2012

estándar VRML 2.0

Se puede averiguar cuáles plug-ins están instalados en el Netscape, desplegando el menú Help/About Plug-ins (Ayuda/Acerca de los plug-ins).

La última versión del Cosmo Player es la 2.0 (para Win95/NT), y es con diferencia, el visualizador de VRML más aconsejable. Se puede obtener en esta página de Cosmo Software

Una vez obtenido el fichero, se debe ejecutar, y la instalación dentro del Netscape o Explorer se hará de forma automática.

Para moverse dentro del visualizador: básicamente se consigue arrastrando el ratón sobre él (o utilizando las teclas con flecha). En su parte inferior existe una consola de mandos para cambiar la manera de actuar. A la derecha hay un botón para cargar una página de ayuda (Help) muy detallada (en inglés).

Puedes encontrar, al final del índice de este manual, en la sección Ayuda visualizador un resumen de los mandos del Cosmo Player 2.0, y que por cargarse en el frame de la izquierda permanece siempre a la vista.

Conexión y equipo necesarios

Debes tener una conexión a Internet rápida, por lo menos de 28.800 bps. Si es más lenta, tendrás que soportar largas esperas. Lógicamente, si es aún más rápida, todavía mejor. Por ejemplo, los usuarios que dispongan de una conexión por medio RDSI (red digital de servicios integrados) apreciarán muchísimo más la realidad virtual que los que lo intenten con una lenta conexión de 14.400 bps.

Con respecto al ordenador, se debe disponer de por lo menos un microprocesador tipo Pentium corriendo a una velocidad de por lo menos 100 MHz. Menos que esto, simplemente no es lo suficentemente rápido como para poder apreciar la realidad virtual, pues de lo contrario se tendrán que soportar retrasos en la respuesta.

Y con respecto a la memoria RAM, el ordenador debe tener un mínimo de 16 megas para una buena visualización, pero 32 megas o más es muchísimo más conveniente.

Prueba de VRML

Para comprobar si tienes instalado en tu navegador el correspondiente visualizador de VRML, así como para ver cuál es el rendimiento de tu ordenador, puedes pulsar los siguientes enlaces, con los que se pueden cargar algunos ejemplos sencillos:

Arcos Silla Lata Web3D

A continuación, un ejemplo de aplicación del VRML para las páginas Web:

Page 184: Manual Vrml 2012

Pulsando esta imagen puedes cargar un mundo virtual que va a servir como entrada en tres dimensiones a WMaestro. Al pulsar algunos de los objetos (planetas), el usuario es transportado a la correspondiente página Web (WebMaestro, WebStore, etc.)

En los ejercicios prácticos de los distintos capítulos se explicará con detalle cómo crear este escenario de realidad virtual.

En el índice de este manual, puedes encontrar, en la sección "Ayuda visualizadores", un resumen de los mandos de ambos visualizadores, el del Netscape y el del Explorer.

Para salir del visualizador, deberás pulsar el icono de retorno del navegador que te conducirá de nuevo a esta página.

Si la prueba ha sido satisfactoria, puedes visitar estos sitios de Internet, que son recopilaciones de distintos escenarios de VRML y que te permitirán juzgar sobre las posibilidades que ofrece esta tecnología:

VRML Gallery Proteinman's Top Ten VRML2.0 Worlds

Page 185: Manual Vrml 2012
Page 186: Manual Vrml 2012