Professional Documents
Culture Documents
Conversion de archivos en
3-D y el uso de Java para
VRML
2
Contenido CAPÍTULO 12
• Escritura de Convertidores
• WorldToolKit NFF
• Quake MDL
• Animación Master SEG
• Orientación futura
Escritura de transformación
En este capítulo vamos a escribir tres programas de conversión, uno para cada
uno de los tres diferentes formatos de archivo:
Huelga decir que todos los programas de traducción será escrito en Java. Todo
el código fuente para estos convertidores se pueden encontrar en el CD-ROM
que viene con este libro.
WorldToolKit NFF
Formato de archivo
En otras palabras, NFF un archivo que contiene dos objetos (uno con 4 vértices
y 7 caras, la otra con 18 vértices y 12 caras) sería algo como esto:
NFF
versión 2.1
viewpos 7 12 56,7
viewdir 0 0 -1
Frodo
4
<vertex data>
7
<face data>
Bilbo
18
<vertex data>
12
<face data>
Vértice de datos
Como ejemplo, aquí hay un vértice que utiliza todas las funciones disponibles:
12,8 76,2 42,17 norma 0,2 0,4 0,7 rgb 0x4A7 uv 0,8 0,65
Cara de datos
Cada cara tiene un recuento del número de puntos en la cara (debe haber al
menos 3 puntos para definir una cara), seguido por el número de enteros que
el índice en el conjunto de vértices. Por ejemplo, 4 2 7 4 5 significa que hay
cuatro puntos a esta cara, y que los vértices son los puntos 2, 7, 4 y 5, en ese
orden. Que debe definirse en un fin de las agujas del reloj, como se ve desde la
parte frontal de la cara.
NFF Un solo archivo puede contener varios objetos, lo que significa que tendrá
que generar IndexedFaceSet múltiples nodos. Este no es un problema, pero
esto significa que vamos a tener varios nodos de forma, cada uno con un
IndexedFaceSet, lo que hace que el archivo VRML un poco detallado.
VRML 2.0 permite a un único nodo de la forma por la textura, mientras que un
archivo puede tener NFF múltiples texturas de cada objeto. Esta limitación en
VRML significa que tendrá que generar múltiples nodos de la forma de cada
objeto en el archivo-NFF una forma para cada textura, para cada objeto. Si hay
tres objetos en el archivo NFF, cada uno con cinco texturas, nos terminan
generando Forma 15 nodos.
En aras de la eficiencia, nos quiere poner a la lista de los vértices una sola vez
y luego usar una y otra vez, en lugar de poner la lista para cada forma que se
utiliza. Lo mismo puede decirse de las normales, colores, texturas y
coordenadas.
7
Desde VRML no nos permite mezclar y combinar por vértice y por colorear la
cara en un solo IndexedFaceSet, tenemos que poner dos IndexedFaceSet nodos
para cada objeto (con un vértice, por colorido y por una cara con colorante) . Si
cada objeto tiene dos tipos de rostros, nuestra estimación de 15 nodos de la
forma de nuevo el 30 de dobles.
Se pone peor. NFF maneja por vértice y cara normales por la misma forma que
los colores, y de nuevo carece de la capacidad de VRML para mezclar por
vértice y cara por las normales en un solo IndexedFaceSet. Ahora estamos
hasta el 60 Formas de NFF un solo archivo.
Coordenadas de textura
Un subconjunto razonable
Con un formato tan complejo y barroco como NFF, tenemos que hacer algunas
concesiones. Los compromisos que se va a hacer de la siguiente manera:
Hay dos maneras básicas para escribir un traductor: O bien usted puede
convertir los datos tal como lo lee, o puede analizar el archivo de entrada y
crear un conjunto de estructuras de datos en memoria que se pueda recorrer a
generar el archivo de salida.
El primer enfoque es apropiado cuando dos formatos son muy similares (por
ejemplo, NFF y el formato de GLP que se utiliza para describir los objetos
poligonales en muchas bibliotecas del freeware VR). Sin embargo, el NFF VRML
y formatos son tan diferentes que no tenemos más remedio que analizar todo
el NFF archivo y, a continuación, generar VRML de la memoria en las
estructuras de datos.
Vamos a crear una clase Java para cada uno de los principales tipos de datos se
encuentran en un archivo NFF: Vértice, Cara, Obj, textura, color, y la escena.
Tenga en cuenta que usamos en lugar de Obj objeto de evitar la confusión con
la clase de objetos en Java.
Una escena es básicamente todo un NFF archivo, que consta de todos los
objetos y el punto de vista de la versión más información. El constructor para
cada clase se utilizará para analizar el objeto de esa clase desde el archivo, y la
clase tendrá métodos para acceder a todos los datos pertinentes.
También vamos a crear una pequeña utilidad de clase que es capaz de leer las
líneas de un archivo NFF, saltarse el paso de los comentarios y líneas en
blanco. Creamos una clase aparte, ya que al analizar la funcionalidad de esta
base va a ser necesario por todas las otras clases que se escriba. Otra clase de
9
NFF paquete;
importación java.io. *;
DataInputStream entrada;
código.
La clase Vec3f
NFF paquete;
importación java.io. *;
importación java.util .*;
dirección, sino que también mantiene un vector que contiene todos los OBJS
que se encontraban en el archivo. Proporciona métodos para recuperar toda
esa información, incluyendo un recuento del número de objetos.
NFF paquete;
importación java.io. *;
importación java.util .*;
Obj la clase
NFF paquete;
importación java.io. *;
Lo mismo se hace con las caras, pero también hacer un poco de post-
procesamiento. Vamos a través de los vértices que forman la cara, la
comprobación para ver si alguno de ellos ha desaparecido o su color normal. Si
alguno de ellos es, nos ponemos una bandera que vamos a comprobar más
tarde cuando se exporta a VRML.
El Vertex Clase
NFF paquete;
importación java.io. *;
importación java.util .*;
Clase de color
NFF paquete;
color de 24 bits. En cualquier caso, los bits que cambio la cuantía apropiada en
la correcta dirección y la máscara ellos.
El Rostro de clase
NFF paquete;
importación java.io. *;
importación java.util .*;
La Clase de textura
NFF paquete;
Por supuesto, ahora las cosas se ponen difíciles. Tenemos que tomar ese
conjunto de estructuras de datos que Acabamos de construida y convertirla en
VRML. El algoritmo básico es el siguiente:
importación java.io. *;
importación java.util .*;
importación NFF .*;
clase pública nff2vrml {
public static void main (String args []) {
intentar {
D flujo de entrada;
if (args.length == 1)
d = new FileInputStream (args [0]);
algo más
d = System.in;
Escena Escena escena = new (nuevo DataInputStream (d));
dump_scene (escena);
21
}
catch (IOException e) (System.err.println (e);)
de capturas (NffSyntaxException e) (System.err.println (e);)
}
El dump_scene () Método
El dump_object () Método
Creamos un Grupo de nodo, que incluyen todos los nodos de forma estaremos
generando para este objeto. A continuación, a través de todos los rostros en el
objeto, la creación de una lista de las diferentes texturas nos encontramos.
Esta lista se almacena en un vector llamado texturas. También realizar un
seguimiento de si hay o no untextured caras.
}
return false;
}
Cualquier persona que no sea nula textura que pasa el partido () devuelve
verdadera prueba, todo lo devuelve falso.
El dump_textured_object () Método
Textura para cada objeto que un vertedero, hay cuatro posibles sub-objetos:
Vamos a generar una forma de nodo para cada uno, poniendo a un nodo que
haga referencia a la apariencia de la textura mapa.
El has_any () el método se usa para ver si hay algo para arrojar por una
combinación, si no hay, no se nada de volcado:
Textura para cada objeto que un vertedero, hay cuatro posibles sub-objetos:
Vamos a generar una forma de nodo para cada uno, poniendo a un nodo que
haga referencia a la apariencia de la textura mapa.
El has_any () el método se usa para ver si hay algo para arrojar por una
combinación, si no hay, no se nada de volcado:
El dump_ Métodos
Sólo la producción para generar esos rostros que coincidan con la configuración
de boolean use_v_normals y use_v_colors y también coincide con la textura que
se esté trabajando (una vez más utilizar nuestra Texture.match () para este
método). Vamos por los puntos en la cara, poner a cada uno, y virar un -1 en el
extremo (ya que ésa es la forma en VRML marca el final de una cara). Si una
cara es de doble cara (es decir, se ha establecido tanto en el archivo original
NFF), ponemos a los índices de nuevo en el orden inverso.
Dumping cara colores es similar, ya que tenemos que volcar los índices de
color en el mismo orden que los polígonos están en el archivo:
continuar;
}
else if (! texture.match (f.getTexture ()))
/ / Para ver un partido
continuar;
System.out.println ( "\ t \ t \ t \ t \ t" + i);
if (f.isDoublesided ())
System.out.println ( "\ t \ t \ t \ t \ t" + i);
}
System.out.println ( "\ t \ t \ t \ t]");
}
Una vez más, cómo Aviso DEF y USE vamos a guardar un espacio considerable
en el archivo de salida.
El dump_appearance () Método
Conclusiones
El NFF a VRML convertidor que hemos escrito aquí no es perfecto, y que puede
producir algunos muy grandes archivos de salida. Sin embargo, ilustra algunos
principios importantes en la conversión de formatos de archivo legado VR en
VRML.
Quake MDL
Antes de ir más lejos, es importante que te das cuenta de que los personajes
de la distribución oficial de Quake no son de dominio público, que son
propiedad de id Software, que posee los derechos de autor sobre los
personajes. No está permitido utilizarlos en sus propias aplicaciones a menos
que usted consigue el permiso expreso y por escrito de id Software.
Formato de archivo
Todos los datos para Quake se almacena en un único gran archivo, que se
compone de un gran número de subarchivos. Subfile cada uno tiene un nombre
de fichero y la longitud, así como una compensación en el conjunto de archivo.
En efecto, el archivo que contiene su propio sistema de ficheros.
Una persona de piel por lo general consta de dos partes. La mitad izquierda de
la imagen es para la parte frontal de la figura, y la mitad derecha de la imagen
es para la parte de atrás. Puede haber otras imágenes más pequeñas en el
mapa de textura y, por lo general en pares (como el anverso y el reverso de la
pistola del jugador).
Coordenadas de textura
Cada elemento tiene también una bandera que indica si este es coordinar la
textura de la "costura" entre la parte delantera y trasera texturas, cuando este
par de coordinar la textura se utiliza en un triángulo que hay en la parte
posterior de la figura, un offset horizontal de la mitad de los ancho de la
textura del mapa se añade al valor de s para que la imagen de la parte
posterior de la figura (en la mitad derecha de la imagen de textura) se hace
referencia en lugar de la parte delantera. Cuando esta misma textura coordinar
par se utiliza en un triángulo en la parte frontal de la figura, no compensado, se
añade, por lo que la mitad izquierda de la imagen de textura se hace
referencia.
Triángulo de Datos
La textura es coordinar los datos de inmediato seguido por los datos de los
triángulos. Este es un simple conjunto de triángulos, cada uno de los cuales
tiene tres valores de 32 bits que son los índices en la matriz para cada uno de
los vértices del triángulo de tres puntos. Esto es muy similar a la cara de datos
en formato NFF examinamos anteriormente, excepto que, en un archivo MDL,
las caras son siempre triángulos. El vértice real los datos se almacenan en cada
uno de animación, tal como se describe a continuación.
Cada cara tiene una bandera que indica si es parte de la parte delantera de la
modelo o de una parte de la espalda. Esta bandera se utiliza en conjunción con
la bandera onseam que está almacenado con la textura de los vértices, como
se ha descrito anteriormente.
Animación Marcos
Los marcos son almacenados en una simple matriz. Cada cuadro tiene un
nombre, un par de puntos que dan limitan el tamaño de la criatura de este
marco de animación, y un conjunto de vértices. Fotogramas de vez en cuando
vienen en grupos, con los plazos de información asociados con el grupo.
34
Todo esto parece bastante claro. Sin duda, este convertidor será más fácil de
escribir que la que hemos construido para el NFF formato? Bueno, no
necesariamente. Hay varios factores que hacen que el formato de Quake
complicado trabajar con él.
Pedidos byte
Todos los archivos están en Quake binario, y que utilizan los nativos de bytes
pedidos en la plataforma PC. Esta orden es la inversa de la utilizada por Java, lo
que significa que tendrá que girar la orden de cada byte entero y flotador que
leer el archivo.
Traslado de Vértices
Nuestro enfoque es escribir una pequeña, sencilla aplicación Java que puede
leer y extraer archivos de un archivo de Quake. Lo utilizaremos para extraer los
archivos de la línea de demarcación militar, y la utilización de una aplicación
Java para convertir cada archivo MDL en VRML.
que va a extraer sólo el archivo demon.mdl. Tenga en cuenta que primero debe
36
paquete terremoto;
importación java.io. *;
if (zerobyte> = 0)
subfilename =
subfilename.substring (0, zerobyte);
int offset = swap32 (quakefile.readInt ());
int size = swap32 (quakefile.readInt ());
if (cmd.charAt (0) == 't') {
if (subfilename.startsWith (prefijo))
System.out.println (tamaño + ""
+ Subfilename);
}
else if (subfilename.startsWith (prefijo)) {
System.out.println ( "Extraer"
+ Subfilename);
FileOutputStream out =
nuevo FileOutputStream (subfilename);
largo savedpos =
quakefile.getFilePointer ();
quakefile.seek (offset);
byte [] buffer = new byte [1024];
do {
int n = quakefile.read (buffer);
out.write (buffer, 0, n);
-= tamaño n;
) While (tamaño> 0);
quakefile.seek (savedpos);
}
}
}
Ahora pasan por el directorio de entradas. Para cada uno, se lee el nombre de
archivo de 50 bytes de información y convertirla en una cadena. Desde Quake
utiliza un C-estilo, nulo terminado cadena de caracteres para almacenar el
nombre del archivo, nos encontramos con el offset del primer byte cero y el
uso de la sub-hasta ese momento como nombre de archivo.
La clase Vec3
Vec3 la clase es similar a la Vec3f clase, sino que utiliza los readFlippedFloat ()
de la ByteFlipInputStream método para obtener sus valores:
paquete terremoto;
importación java.io. *;
Usted puede preguntarse por qué no acaba de volver a utilizar el Vec3f clase, y
40
añadir los métodos para hacer frente a la Quake-byte vuelta el pedido. Así,
sería la clase Vec3f menos genérico, ya que se sabe acerca de byte WAV y la
ByteFlipInputStream. Podríamos, sin embargo, han optado por hacer una
subclase Vec3 de Vec3f.
La clase ByteFlipInputStream
paquete terremoto;
importación java.io. *;
protegidas en DataInputStream;
super (entrada);
= entrada en;
= new byte buffer [4];
}
paquete terremoto;
importación java.io. *;
Note que estamos usando el método swap32 de nuevo, lo que sugiere que
probablemente deba estar en una clase separada.
El encabezado del archivo de salida se inicia con las letras BM (de mapa de
bits). Esto es seguido por el tamaño total del archivo, una palabra cero, el
desplazamiento de la imagen real, y el mapa de bits de cabecera. El mapa de
bits de cabecera tiene el tamaño de la cabecera, la anchura y la altura de la
imagen, y la información adicional que puede ser puesta a cero ya que los
valores por defecto serán asumidas por cualquier utilidad que lee ficheros BMP.
Esto es seguido por la paleta y finalmente por los propios píxeles. Como ya
comentamos anteriormente, los píxeles se organizan en una parte inferior a la
superior dirección, lo que significa que no necesitamos hacer nada con ellos
más allá del escribir a cabo.
43
La clase MDLFile
paquete terremoto;
importación java.io. *;
Una vez más, tenga en cuenta el control que ha hecho en contra de la firma.
Asimismo, para comprobar los archivos con un número de versión diferente, ya
que sólo admiten la versión 6. En particular, la versión 3 archivos no son
compatibles.
Las pieles, la textura vértices, triángulos, y el marco son leídos por todos los
constructores de sus clases correspondientes.
La piel de la clase
Una piel en un archivo MDL puede consistir en una serie de imágenes, dispuestas en una
secuencia temporal, que permiten el uso de mapas de texturas animadas. La piel de clase
almacena el número de tales imágenes, una variedad de las imágenes, una serie de códigos
para el momento en las imágenes, y las dimensiones de la piel. Cada imagen es un arreglo
de alto * ancho de bytes, por lo que el píxeles [] [] matriz es un conjunto de imágenes (que
no es bidimensional matriz de bytes).
Existen métodos de acceso para obtener la imagen de una persona y su tiempo, así como el
número de imágenes y las dimensiones de la piel. También hay un método para obtener un
píxel individual de una imagen concreta:
46
paquete terremoto;
importación java.io. *;
El constructor tiene la altura y la anchura de los valores que se lea el archivo de cabecera de
la línea de demarcación militar, junto con un puntero a la ByteFlipInputStream. La primera
palabra en la piel es una bandera, si es cero, sólo hay una foto con ningún momento los
valores. Si la bandera es un valor distinto de cero, es seguida por un recuento del número de
imágenes y una amplia gama de valores de tiempo (uno para cada foto).
La clase TextureVertex
paquete terremoto;
importación java.io. *;
paquete terremoto;
importación java.io. *;
48
El getPoint () devuelve el método de índice de un vértice del triángulo. Al igual que con el
TextureVertex clase, que convertir un entero de 32 bits a un valor pabellón Java booleano.
La clase FrameGroup
paquete terremoto;
importación java.io. *;
Si el tipo de bandera es un valor distinto de cero, por otro lado, las cosas son
más complejas. Leemos el número de subframes que siguen, los valores
mínimo y máximo para que el conjunto de marcos, el conjunto de códigos de
tiempo, y los marcos propios.
Todo esto puede parecer una reminiscencia de la forma en que leemos las
pieles, y los principios son los mismos. Sin embargo, la versión 3.2 de la
50
El Marco de la clase
paquete terremoto;
importación java.io. *;
La clase Trivertex
paquete terremoto;
importación java.io. *;
Vamos a dar algunas opciones que el usuario. Ellos pueden o no quieren que la
secuencias de animación, así que vamos a proporcionar un pabellón para
incluirlos. Que puede o no quiere los mapas de textura, por lo que vamos a
darles una bandera-t para que dicha función.
importación java.io. *;
importación java.util .*;
importación terremoto .*;
}
Mdl_filename cadena = new String (args [argnum]);
DataInputStream entrada = new DataInputStream {
new FileInputStream (mdl_filename));
MDL MDLFile = new MDLFile (entrada);
System.out.println ( "# VRML V2.0 utf8 \ n");
System.out.println ( "# de creación por mdl2wrl \ n");
System.out.println ( "# archivo original"
Mdl_filename + + "'");
System.out.println ( "# Los datos del archivo original:");
System.out.println ( "Modelo de radio # ="
Mdl.getRadius + ());
System.out.println ( "# = Escala"
Mdl.getScale + ());
System.out.println ( "# origen ="
Mdl.getOrigin + ());
System.out.println ( "# = Compensaciones"
Mdl.getOffsets + ());
System.out.println ( "#"
Mdl.getNumberOfVertices + ()
+ "Vértices");
System.out.println ( "#"
Mdl.getNumberOfTriangles + ()
+ "Triángulos");
System.out.println ( "#"
Mdl.getNumberOfFrameGroups + ()
+ "Frames");
System.out.println ( "#" + mdl.getNumberOfSkins ()
+ "Pieles, cada" mdl.getSkinWidth + () + "por"
Mdl.getSkinHeight + ());
System.out.println ();
si (animación)
System.out.println {
"Grupo de los niños ([DEF TOQUE TouchSensor ()");
System.out.println ( "Forma (");
alguien que está reuniendo una gran mundo que necesita para que se ejecute
en tiempo real velocidades). Si estamos poniendo a la animación (es decir, si la
animación del pabellón tiene establecido por la opción-a en la línea de
comandos) que también puso un TouchSensor nodo que nos permita iniciar y
detener la animación después. Por último, ponemos en el inicio de la Forma de
nodo que contendrá esta criatura.
El procesamiento de los mapas de textura y apariencia de la Generación del
Nodo
if (texturas) {
int dot_offset = mdl_filename.lastIndexOf ('.');
Basename mdl_filename.substring cadena = (0,
dot_offset);
byte [] = paleta load_palette ( "paleta");
for (int i = 0; i <mdl.getNumberOfSkins (); + + i) {
S = mdl.getSkin piel (i);
for (int j = 0;
j <s.getNumberOfPictures (); j + +) {
byte [] imagen = s.getPicture (j);
Filename = cadena
new String (basename + i
+ "_" + J + ". Bmp");
BMP.dump (nombre de archivo, imagen,
mdl.getSkinWidth (),
mdl.getSkinHeight (),
paleta);
if (i! = 0 | | j! = 0)
System.out.print ("#");
System.out.println {
"\ t \ ttexture ImageTexture {
url \ "" + filename + "\") ");
}
}
}
System.out.println ( "\ t \ (tmaterial Material");
System.out.println ( "\ t \ t \ tdiffuseColor 1 1 1");
55
A continuación, pasar por todas las pieles, y por cada piel que pasar por todas
las imágenes que en la piel. Para cada imagen, se genera un nombre de
archivo de la forma basenameN_M.bmp, donde N es el número de la piel y M es
el número de sub-imagen. Usamos el BMP clase que hemos debatido antes de
que se haga realidad la textura archivos.
Generación de la IndexedFaceSet
Nos enfrenta a degenerar salto (en los que se enfrenta a dos de los vértices
son idénticos). Para cada uno de no saltarse la cara, que emiten los mismos
índices, seguido de un -1 para indicar el final de una cara en VRML.
if (texturas) {
System.out.println ( "\ t \ ttexCoord TextureCoordinate (");
58
else {
if (mdl.getTextureVertex (t.getPoint (0)). isOnseam ())
System.out.print ((t.getPoint (0)
Mdl.getNumberOfVertices + ()) + "");
algo más
System.out.print (t.getPoint (0) + "");
if (mdl.getTextureVertex (t.getPoint (1)). isOnseam ())
System.out.print ((t.getPoint (1) +
Mdl.getNumberOfVertices + ()) + "");
algo más
System.out.print (t.getPoint (1) + "");
if (mdl.getTextureVertex (t.getPoint (2)). isOnseam ())
System.out.print ((t.getPoint (2)
+ Mdl.getNumberOfVertices ()));
algo más
System.out.print (t.getPoint (2));
}
System.out.println ( "-1");
}
System.out.println ( "\ t \ t]");
}
System.out.println ( "\ t)"); / / fin de IndexedFaceSet
System.out.println ("}"); / / fin de Forma
Generación de la animación
Hasta ahora hemos visto cómo generar una, textura versión de la criatura. ¿No
sería bueno hacer que se mueva?
60
si (animación) {
System.out.println ( "])"); / / final del Grupo de nodo con TouchSensor
/ / Comprobar marco para múltiples grupos
for (int i = 0; i <mdl.getNumberOfFrameGroups (), i) {
if (mdl.getFrameGroup (i). getNumberOfSubFrames ()! = 1) {
System.err.println {
"lo siento, varios grupos que no apoyaron marco");
System.exit (2);
}
}
Secuencia de la clase {
Cadena nombre protegidas;
protegidas int inicio, final;
61
Este código es un poco sutil, de modo que una explicación está en orden.
Sabemos que todos los grupos tienen un marco único conjunto de marcos
(desde que salió con un error que si no era cierto). Usamos un método especial
llamado getFrame () para acceder a las cero de un marco marco de grupo, ya
que es algo que tendrá que hacer mucho. Obtenemos el nombre del primer
cuadro, recorte cualquier trailing dígitos, y crear un nuevo marco de secuencia
a partir de cero.
Los principales valores son el índice dividido por el número de valores, en otras
palabras, si hay cinco cuadros, a continuación, las claves será 0 / 5, 1 / 5, 2 / 5,
3 / 5, 4 / 5, y 5 / 5 (o, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0).
Los valores son keyValue difícil. Para cada valor de clave, habrá tantos vértices
como hay vértices en la criatura, es decir, hay nvalues conjuntos de cada uno
de los vértices nvertices. Para cada uno de los cuadros a partir de la estructura
de esta secuencia (s.getStart ()) para nvalues cuadros, que emiten todos los
vértices (que habrá nvertices de ellos).
Observe que una vez más el uso emit_vertex (), ya que se encarga de la
ampliación y la traducción para nosotros.
La generación de los nodos NormalInterpolator
Este código es casi idéntica a lo que acabamos de examinar, salvo que una
tachuela en el interpolador _NI nombre en lugar de una _CI, y llame a
emit_normal () en lugar de emit_vertex ().
Generar el TimeSensor y Rutas
Y, por último, pasamos por algunos facultativos y generar rutas, una para cada
secuencia de animación. En cada caso, le VÍA TouchSensor que la vuelve a
añadir al principio de la la TimeSensor, de modo que al hacer clic sobre la
criatura hará que la secuencia. Dejamos hasta que el usuario descomentar
alguna de estas que son útiles y pegar un comentario frente a la omisión
TimeSensor nodo (s) de lo generado antes. El uso puede también, por
supuesto, cambiar el bucle de ajuste en cualquiera de los nodos para obtener
TimeSensor acción continua (especialmente útil para las acciones repetidas,
como caminar):
Y terminado.
Nota: debes descomentar TimeSensor uno de los nodos con el fin de obtener la
animación para trabajar.
Correr mdl2vrml
que también daría lugar a una o más de Windows. archivos BMP, que contiene
los mapas de texturas. Y, por supuesto, podría usar el comando
Figura 13-2 muestra una típica criatura sin el mapeo de texturas, y la Figura
13.3 muestra que con el mapeo de texturas.
Conclusiones
El Quake MDL convertidor que hemos presentado aquí es bastante completa. Como se
mencionó anteriormente, se puede modificar para producir un nodo MovieTexture cuando
un multipicture piel se encuentra, y usted podría incluso intentar hacer frente a grupos
marco que contengan más de un cuadro (aunque son muy raros, y probablemente no vale la
pena).
Una vez más, un recordatorio de que las criaturas son Quake propiedad de id Software, lo
que no se puede utilizar sin permiso. Sin embargo, si los demás usuarios crear servicios
para la producción de Quake criaturas, se le puede convertir a VRML, con mapas de
texturas y animación.
Animación Master utiliza un gran número de archivos diferentes para describir una figura.
Algunas de ellas están documentadas, pero, de nuevo, la documentación es muy limitado y
67
contiene algunos errores. En equidad a los autores de las especificaciones, que están
claramente destinados a ser no oficial "sugerencias" para los programadores más que parte
del producto en sí.
En esta sección vamos a limitarnos a la SEG el formato de archivo, que es producida por el
módulo de Escultura de la animación Maestro. Un segmento es una descripción
geométricas de una forma y se compone de una serie de splines.
Formato de archivo
El fichero comienza con una línea de cabecera, cuya primera cuatro personajes son SCUL
(para "escultura"). Estos personajes son seguidos por el número de versión, y luego un cero
y, a continuación, una plataforma de tipo bandera y otros tres ceros. El tipo de plataforma
es de 1 o 2 para Windows para PowerMac, las dos plataformas en las que la animación
Master está disponible. El número de versión es importante, ya que el formato de archivo
ha cambiado de una versión maestra de la animación a otra.
Tras la cabecera de línea es una línea que contiene un entero llamado segmento de
Identificación, que (no es sorprendente) se utiliza para identificar el segmento. La siguiente
línea contiene seis números de punto flotante que es el mínimo y máximo x, y, z y los
valores (en efecto, la caja de la serie de sesiones). Esto es seguido por una línea que
contenga la x, y y z de los valores de punto de giro de la serie de sesiones, y una línea que
contenga el número de splines.
Los splines siga estos cabecera líneas. Cada spline comienza con una línea que contenga un
recuento del número de puntos de control en la spline, seguido de los puntos de control
propios.
Según la documentación, cada punto de control debe comenzar con el punto de control id
(CPID). Sin embargo, el examen de este archivo se contradice, sino que parece que la línea
contiene el tipo y adjuntar banderas, seguido por el CPID. Aunque no dejó claro en la
documentación, parece que los tres valores se almacenan en una sola línea.
El pabellón es un tipo lógico OR de dos banderas: LISA (0x01) y LOOP (0x04). El buen
bandera indica que este punto de control debe ser suave en lugar de ser un ángulo agudo. El
LOOP bandera indica que este punto debería volver al circuito el primer punto de control
de la spline, que se utiliza generalmente (en su caso) en el último punto de control de la
spline.
Si concedemos la bandera tiene un valor distinto de cero, indica que este punto de control
está conectado a otro punto de control. Si este es el caso, la siguiente línea del archivo
contiene el CPID el punto de que este punto se adjunta a la. Si la bandera es igual a cero, la
siguiente línea contiene la x, y, z y los valores de este punto de control.
68
Esto es seguido por una línea que contenga la outalpha, outgamma, y outmag valores.
Outalpha Si el valor es cero, entonces outalpha por defecto a 100 y el outgamma y outmag
se ignoran y los valores por defecto a cero. Esto se repite con una línea que contenga la
inalpha, ingamma, inmag y valores, que por defecto de la misma manera.
Analizar los archivos de la SEG es fácil, pero hay muchos problemas en la conversión en
VRML. Todos estos desafíos se derivan de la falta de documentación sobre el formato de
archivo.
El alfa, gamma, y la magnitud valores tienen que ver con la curva de spline, pero la
documentación no explica qué tipo de spline se utiliza o cómo hacer la interpolación spline.
También es claro que no sólo la documentación de la forma en que el splines deben estar
conectados para formar parches. Esto hace que sea difícil teselar ellos, o incluso
convertirlos en polígonos.
A falta de documentación adicional, lo mejor que podemos hacer es convertir los puntos de
control en los vértices y splines en segmentos de línea.
Usaremos el mismo enfoque aquí como lo hicimos para el NFF y MDL analizadores. Que
habrá una clase para cada uno de los principales tipos de datos en un archivo SEG: Spline ",
ControlPoint, y del segmento. También existe una clase Vec3f utilidad.
La clase Vec3f
paquete de hachís;
importación java.io. *;
importación java.util .*;
El segmento de la clase
/ / Un AnimationMaster Segmento
paquete de hachís;
importación java.io. *;
importación java.util .*;
Spline "La clase es trivial, sino que lee un recuento del número de puntos de
control y, a continuación, utiliza el constructor ControlPoint leer cada punto de
control:
paquete de hachís;
importación java.io. *;
}
72
La clase ControlPoint
ControlPoint La clase almacena la cpid para el punto, tres Booleanos (el suave,
lazo, y adjuntar los pabellones) y seis valores spline (inalpha, ingamma, inmag,
outalpha, outgamma, y outmag). Los campos se han facilitado a los CPID en el
punto de control que está adjunta a, así como la x, y, z ubicación de este
punto, sólo uno de los dos realmente se utiliza para cualquier punto de control:
paquete de hachís;
importación java.io. *;
importación java.util .*;
importación java.io. *;
importación java.util .*;
importación hash .*;
La emisora de Vértices
Ahora vamos a través de todos los splines, y todos los puntos de control para
cada uno de los splines. Para cualquier punto de control que no está conectada
a otro (es decir, para cada uno que es un "real" en lugar de un punto de volver
a utilizar uno), almacenamos una referencia al punto de control de vectores en
una llamada coordenadas:
El siguiente paso es emitir todos estos puntos de control único como vértices,
con un nodo de coordenadas:
/ / Y emiten ellos
System.out.println ( "\ t \ t \ t \ tcoord Coordinar (");
System.out.println ( "\ t \ t \ t \ t \ tpoint [");
for (int k = 0; k <coordinates.size (); k + +) (
ControlPoint pt = (ControlPoint) coordinates.elementAt (k);
System.out.println ( "\ t \ t \ t \ t \ t \ t"
Pt.getX + () + "" + pt.getY () + "" + pt.getZ ()
+ "#" + Pt.getCPID ());
}
System.out.println ( "\ t \ t \ t \ t \ t]");
System.out.println ( "\ t \ t \ t \ t)");
La emisión de las líneas propias, vamos a través de los splines de uno en uno. Para cada
spline, corremos a través de los puntos de control. Si un punto se marca como adjunto,
esperamos hasta el punto que se adjunta a si este punto también es marcado como adjunto,
esperamos hasta el punto que se adjunta, y así sucesivamente. Esto es algo así como una
lista siguiente.
76
Una vez que hayamos encontrado un punto solteras, esperamos que en las coordenadas
matriz, que se corresponde uno a uno con el conjunto de vértices de coordenadas en el nodo
que emiten antes. El índice en la matriz se emite el siguiente punto a lo largo de la línea que
estamos generando. Si es el primer punto, hacemos un seguimiento de lo que tenemos en el
caso del ciclo al final de la spline:
Cuando llegamos a la final de la spline, ponemos un -1 para indicar el final de esta serie de
líneas.
Eso es todo. Para procesar un archivo SEG, corre mdl2vrml, de la siguiente manera:
Tenga en cuenta que se lee de su entrada estándar en lugar de tomar un nombre de archivo
en la línea de comandos.
El jefe de una figura humanoide que ha sido convertido mediante mdl2vrml se muestra en
la Figura 13.4.