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 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 0
	field 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 0
				children 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 0
	children Paraguas { colorBaston 0.2 0 0 colorTela 0 0.2 0.1 }
}

Transform {
	translation -8 0 0
	children 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 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:

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


PROTO Banquillo [
	field SFColor colorPatas 1 1 0
	field SFColor colorAsiento 0 0 1
	field SFVec3f proporciones 1 1 1
	field SFVec3f posicion 0 0 0
]
{
	PROTO Pata [
		field SFColor colorPata 1 1 0
		field SFVec3f posicion 0 0 0
	]
	{
		Transform {
			translation IS posicion
			children Shape {
				geometry Cylinder { radius 0.1 height 1 }
				appearance Appearance { material Material { diffuseColor IS colorPata } }
			}
		}
	}

	Transform {
		translation IS posicion
		scale IS proporciones
		children [
			Shape { # Asiento
				geometry 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 defecto
Banquillo { 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 }

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 0
	children Shape {
		geometry Box { size 3 3 3 }
		appearance USE MiRojo
	}
}
Transform {
	translation 2 0 0
	children 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 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 0
	children Shape {
		geometry Box { size 3 3 3 }
		appearance USE MiRojo
	}
}
Transform {
	translation 2 0 0
	children Shape {
		geometry Sphere { radius 2 }
		appearance USE MiRojo
	}
}


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.




< Anterior | Menú ^ | Siguiente >