You are on page 1of 33

1

VRML 2.0 con Java CAPÍTULO 16

Métodos y narrativas de
Dispositivos de Apoyo
2

VRML 2.0 con Java CAPÍTULO 16

Contenido CAPÍTULO 16

• La clase Input6D
• Los métodos nativos
• Definición de los prototipos
• El código de Java para el Nodo de secuencias de comandos
• cuaterniones
• Un archivo de ejemplo
• Problemas de rendimiento y disponibilidad
• Orientación futura

La clase Input6D
3

VRML 2.0 con Java CAPÍTULO 16

Input6D la clase será lo suficientemente generales como para apoyar


una amplia gama de dispositivos de entrada. Asimismo, ser
independiente del dispositivo y de plataforma independiente, puesto que
todas las dependencias serán manejadas por el nativo de los métodos
de la clase. Haremos la mayor parte del procesamiento de los datos de
sensor en Java, con el fin de reducir la cantidad de trabajo que tiene que
hacerse en los nativos y, por ende, los métodos que sean más fáciles de
aplicar.

Dado que puede haber múltiples dispositivos de entrada en una sola


máquina, necesitamos alguna forma de identificar dispositivos
específicos sin hacer ninguna hipótesis acerca de ellos. Lo haremos por
la asociación de un número de puerto con cada uno de ellos. El número
de puerto será un entero simple, que puede ser vinculado a un
dispositivo real de la utilización de algunos mecanismos específicos de
plataforma. Esto permite a los constructores-avatar simplemente decir:
"Jefe de seguimiento en el puerto es 0, el seguimiento de la mano
izquierda está en el puerto 1, y el seguimiento de la mano derecha en el
puerto 2," sin preocuparse de que los dispositivos que el usuario pasa a
tener instalado . El puerto será una variable de instancia de la clase
Input6D, ya que cada objeto de esa clase tendrá su propio puerto.

La clase Input6D tendrá también variables de instancia para el


almacenamiento de leer el último conjunto de valores de datos en bruto.
Las traducciones se almacenan en las variables rawX, rawY, y rawZ, y
las rotaciones se rawR, rawU, y rawV. También habrá un 32-bit de los
pabellones de los diferentes botones en el dispositivo, así como una
variable que los registros que el botón se presiona más recientemente.
Por último, tendremos un entero para almacenar el estado de la
operación más reciente en el dispositivo y un par de operaciones
booleanas para indicar si el dispositivo se ha desplazado desde la última
encuesta, y si el estado de sus botones ha cambiado:

/ / Clase para el manejo de 6 grados de libertad dispositivos

/ / Escrito por Bernie Roehl, febrero de 1997

clase pública Input6D (


protegidas int puerto; / / establecido por el constructor
4

VRML 2.0 con Java CAPÍTULO 16

/ / Leer encuesta ():


flotador rawX protegidas, rawY, rawZ;
flotador rawR protegidas, rawU, rawV;
int botones protegidas;
int whichButton protegidas;
int estado protegidas;
protegidas boolean cambiado;
boolean buttonChanged protegidas;

Los valores de obtener materias primas a escala, que se compensan, y,


en general, procesados de diferentes maneras a fin de llegar a las
lecturas de la realidad que se informó a la aplicación. Vamos a
almacenar estos valores transformados como variables de instancia:

/ / Valores transformados:
protegidas flotar x, y, z;
protegidas flotar r, u, v;

Cada dispositivo tendrá una serie de información básica sobre sí mismo,


algunos de los cuales vamos a utilizar en Input6D y algunos de los
cuales vamos a ofrecer simplemente a la aplicación. Esta información
consta de una descripción legible por humanos del dispositivo, un
recuento del número de botones en el dispositivo, el rango de los límites
de cada uno de los seis DOF, y el punto central para cada DOF. También
vamos a mantener en torno a una bandera para mostrar que el
dispositivo ha sido correctamente inicializado:

/ / Conjunto de configuración ():


Cadena descripción protegidas; / / nombre y la descripción
int nbuttons protegidas; / / número de botones
minX protegidas flotador, maxX, minY, maxY, minZ, maxZ;
flotador minR protegidas, maxR, minu, maxU, minV, maxV;
flotador centerX protegidas, centerY, centerZ;
flotador centerR protegidas, centerU, centerV;
boolean allsWell protegidas;

La solicitud podrá así quieren los datos de la escala, por lo que


proporcionar un factor de escala para cada DOF. Estos a 1.0 por defecto,
pero pueden ser fácilmente modificados por la aplicación según sea
5

VRML 2.0 con Java CAPÍTULO 16

necesario.

/ / Conjunto de la demanda:
protegidas flotar XScale = 1 septies, yScale = 1 septies, zScale = 1F;
protegidas rScale flotador = 1 septies, uScale = 1 septies, vScale = 1F;

Como se ha explicado anteriormente, un dispositivo de entrada puede


proporcionar un control directo sobre los seis grados de libertad o control de la
tasa de cambio de los valores. Vamos a mantener dos banderas, una para la
traducción y para una rotación, que indique si el dispositivo de control o el
valor de la tasa de cambio. Dado que el tipo de cambio se basará en el tiempo
transcurrido entre lecturas consecutivas del dispositivo, también tendremos
que hacer un seguimiento de si el dispositivo de la última encuesta:

protegidas accumulateTranslations boolean = false;


protegidas accumulateRotations boolean = false;
largo lastPolled protegidas;

Eso es todo para la variables de instancia. Hay una serie de métodos de


acceso:

flotador público getX () (return x;)


flotador público Gety () (return y;)
flotador público Getz () (return z;)
flotador público getR () (return r;)
flotador público getU () (return u;)
flotador público getV () (return v;)
público int getButton () (return whichButton;)
público int getButtons () (return botones;)
público int getStatus () (return estado;)
público hasChanged boolean () (return cambiado;)
público buttonHasChanged boolean () (return buttonChanged;)

public void setX (float valor) (x = valor;)


public void setY (float valor) (valor = y;)
public void setZ (float valor) (z = valor;)
public void setR (float valor) (r = valor;)
public void Setu (float valor) (u = valor;)
public void setV (float valor) (v = valor;)

getDescription public String () (return descripción;)


público int getNumberOfButtons () (return nbuttons;)
público int getPort () (return puerto;)
6

VRML 2.0 con Java CAPÍTULO 16

public void setPort (int p) (puerto = p;)


flotador público getScaleX () (return XScale;)
flotador público getScaleY () (return yScale;)
flotador público getScaleZ () (return zScale;)
public void setScaleX (float x) (XScale = x;)
public void setScaleY (float y) (yScale = y;)
public void setScaleZ (float z) (z = zScale;)

flotador público getScaleR () (return rScale;)


flotador público getScaleU () (return uScale;)
flotador público getScaleV () (return vScale;)
public void setScaleR (float r) (rScale = r;)
public void setScaleU (float u) = u uScale (;)
public void setScaleV (float v) (vScale = v;)

público getAccumulateTranslations boolean () (


accumulateTranslations retorno;
)

público getAccumulateRotations boolean () (


accumulateRotations retorno;
)

public void setAccumulateTranslations (boolean valor) (


accumulateTranslations = valor;
)

public void setAccumulateRotations (boolean valor) (


accumulateRotations = valor;
)

Tenga en cuenta que el setX (), setY (), y otras funciones sólo son pertinentes si
se acumulan las pabellón esté definido. Por ejemplo, si la solicitud se quiere
restablecer las rotaciones a cero, puede utilizar el setR (), Setu (), y setV () los
métodos para hacerlo. Si el dispositivo no está en el modo de acumular
rotaciones, estos métodos tienen poco efecto, porque la próxima vez que lea el
dispositivo de un nuevo conjunto de valores se definirán.

Habrá dos métodos nativos. Uno de ellos creó el dispositivo, al restaurar si es


necesario, y el otro dispositivo de la encuesta para los nuevos valores. Estas
serán examinadas en detalle más adelante en este capítulo. Por ahora, basta
con observar que tienen los nativos de palabras clave en frente de ellos para
indicar que su aplicación es en realidad escrito en C o algún otro idioma. El
nativeSetup () método es llamado sólo desde Input6D.setup (), que es
7

VRML 2.0 con Java CAPÍTULO 16

generalmente llamado sólo desde el constructor:

privado nativo vacío nativeSetup ();


privado nativo vacío nativePoll ();

público Input6D (int prt) (


port = prt;
configuración ();
)

La configuración () llamadas a los métodos nativeSetup (), comprueba el


estado de resultado, y establece la designación para el dispositivo de entrada
para ser un mensaje de error si existe algún problema. Si todo está bien, el
programa de instalación () entonces el dispositivo de las encuestas y utiliza los
valores iniciales en bruto como el centro puntos. Tenga en cuenta que esto
supone que el dispositivo está en su "descanso" o "cero" posición en el tiempo
de inicio:

public void setup () (


allsWell = true;
nativeSetup ();
if (estado! = 0) (
descripción = "No se pudo inicializar; código de error" estado;
allsWell = false;
)
/ / Leer los valores iniciales, como el uso CenterPoint
= buttonChanged cambiado = false;
nativePoll ();
lastPolled = System.currentTimeMillis ();
centerX = rawX; centerY = rawY; centerZ = rawZ;
centerR = rawR; centerU = rawU; centerV = rawV;
maxX -= centerX; maxY -= centerY; maxZ -= centerZ;
maxR -= centerR; maxU -= centerU; maxV -= centerV;
minX -= centerX; minY -= centerY; minZ -= centerZ;
minR -= centerR; minu -= centerU; minV -= centerV;
if (maxX == 0) maxX = 1, si (minX == 0) minX = -1;
if (maxY == 0) maxY = 1, si (minY == 0) minY = -1;
if (maxZ == 0) maxZ = 1, si (minZ == 0) minZ = -1;
if (maxR == 0) maxR = 1, si (minR == 0) minR = -1;
if (maxU == 0) maxU = 1, si (minu == 0) minu = -1;
if (maxV == 0) maxV = 1, si (minV == 0) minV = -1;
)

Los valores mínimos y máximos son fijados por el nativeSetup () el método, y


8

VRML 2.0 con Java CAPÍTULO 16

nosotros inmediatamente compensado por el valor del punto central para cada
DOF. Dado que será el punto central de restar los valores de cada muestra, tal
como lo ha leído, estamos seguros de que efectivamente toma la posición de
centrado en el canal es cero, y sus valores mínimo y máximo se ajustará en
consecuencia.

Dado que algunos dispositivos pueden apoyar menos de seis grados de


libertad, y los valores mínimo y máximo para los canales sin aplicarse puede
ser cero, se añade un control y establecer los valores en consecuencia.

El dispositivo de votación se realiza llamando a la encuesta () método.


Se realiza un seguimiento de la última vez que el dispositivo fue
encuestados, con el fin de la escala de valores de entrada cuando el
accumulateTranslations o accumulateRotations banderas se establecen:

public void encuesta () (


/ / Actualizar el lastPolled tiempo
ahora System.currentTimeMillis largo = ();
= largo deltaT ahora - lastPolled;
= lastPolled ahora;
if (allsWell == false) (/ / no inicializadas
status = -1;
retorno;
)
/ / Encuesta el dispositivo
= buttonChanged cambiado = false;
nativePoll ();
if (! cambiado)
retorno;

El nativePoll () método es llamado, que se actualizarán los valores a lo


largo de la materia prima con el botón y whichButton campos. Si el
cambio de bandera no ha sido establecida, entonces el crudo valores
son los mismos que fueron la última vez nativePoll () se ha llamado, por
lo que no hay necesidad de procesar de nuevo.

El siguiente paso es cambiar el valor bruto de modo que el punto central


es cero, entonces por la escala de factores de escala y dividir por el
rango. Si el valor bruto es negativo, el intervalo mínimo es utilizado
como el divisor, de lo contrario, el alcance máximo se utiliza:
9

VRML 2.0 con Java CAPÍTULO 16

/ / Cambio de centro
rawX -= centerX; rawY -= centerY; rawZ -= centerZ;
rawR -= centerR; rawU -= centerU; rawV -= centerV;
/ / Escala y en condiciones de gama
flotador dx = rawX XScale * / ((rawX <0)?-minX: maxX);
dy = yScale flotar rawY * / ((rawY <0)?-minY: maxY);
flotador dz = zScale * rawZ / ((rawZ <0)?-minZ: maxZ);
dr = rScale flotar rawR * / ((rawR <0)?-minR: maxR);
del flotador = uScale * rawU / ((rawU <0)? minu-: maxU);
dv = vScale flotar rawV * / ((rawV <0)?-minV: maxV);

El paso final es comprobar si los valores están siendo "acumulado", es


decir, comprobar si el dispositivo de control de los valores directamente
o controle su tasa de cambio. Si es esto último, los valores que se
computan sólo se escalan por el tiempo transcurrido (convertidos a
segundos de dividir entre 1000) y se añaden a los valores actuales de
las distintas variables. Si es la primera, los nuevos valores adquiridos se
almacenan directamente en las variables de instancia:

/ / Acumular
if (accumulateTranslations) (
dx = x + * deltaT / 1000;
y + = dy * deltaT / 1000;
+ z = dz * deltaT / 1000;
)
else (
x = dx;
y = dy;
z = dz;
)
if (accumulateRotations) (
r + = dr * deltaT / 1000;
u + = du * deltaT / 1000;
v + = * deltaT dv / 1000;
)
else (
r = dr;
u = du;
v = dv;
)
10

VRML 2.0 con Java CAPÍTULO 16

(System.loadLibrary estática ( "Input6D");)


)

Observe que tenemos un inicializador estático que se carga la biblioteca


Input6D, que en Windows 95 se llamará Input6D.DLL. Biblioteca que
contendrá el código que implementa los métodos nativos.
El Nativo de Métodos

Input6D.DLL El archivo contiene los dos métodos nativos que se


discutieron anteriormente. Esto sirve para aislarlos bien del resto del
código que habrá una biblioteca dinámica Input6D en cada plataforma, y
un usuario puede agregar el soporte para dispositivos inusual por
proporcionar una Input6D que aplicar a sí mismos.

Nuestra aplicación será diseñado para Windows 95, ya que es, de lejos,
la plataforma más popular. Vamos a estar usando DirectInput, que es
esencialmente un conjunto mejorado de mando de las rutinas en
Windows 95 que admita dispositivos con hasta seis grados de libertad y
múltiples botones. Vamos a guardar nuestro métodos nativos en un
archivo llamado I6DImp.c, que serán compilados y vinculados, como se
muestra más adelante en este capítulo.

Los detalles de la aplicación, por supuesto, varían de una plataforma a


otra. Esta es una razón por la cantidad de trabajo realizado en los
métodos nativos se mantiene al mínimo, ya que el código debe volver a
aplicarse en cada plataforma.
El nativeSetup () Método

El nativeSetup () método es muy sencillo:

# include "Input6D.h"
# include <windows.h>
# include <string.h>

vacío Input6D_nativeSetup (struct HInput6D * obj)


(
ClassInput6D * = datos unhand (obj);
JOYCAPS gorras;
11

VRML 2.0 con Java CAPÍTULO 16

datos-> status = joyGetDevCaps (datos-> puerto, y gorras, sizeof


(gorras));
if (datos-> estado! = 0)
retorno;
datos-> minX = caps.wXmin; datos> maxX = caps.wXmax;
de datos> = minY caps.wYmin; de datos> = maxY caps.wYmax;
datos-> minZ = caps.wXmin; de datos> maxZ = caps.wZmax;
datos-> minR = caps.wRmin; de datos> maxR = caps.wRmax;
de datos> = minu caps.wUmin; de datos> maxU = caps.wUmax;
datos-> minV = caps.wVmin; de datos> maxV = caps.wVmax;
datos-> nbuttons = caps.wNumButtons;
de datos> = makeJavaString descripción (
caps.szPname, strlen (caps.szPname));
)

Cuando se llama a este nativo de Java método, que pasa el mango del
objeto Input6D como parámetro. El unhand () macro gira el mango en un
puntero de tipo C, de manera que pueda ser utilizado para acceder a
variables de instancia del objeto. Que macro, y una serie de aspecto
algo extraño tipos de datos, son todos Input6D.h definidas en el archivo
que se genera automáticamente para usted por javah.

Un Windows 95 JOYCAPS se define la estructura, que se completará con


las capacidades del dispositivo, seleccione joystick. Observe que el
número de puerto que la solicitud se especifica en el constructor para el
objeto Input6D se pasa directamente a la joyGetDevCaps () de rutina. Si
el valor de retorno de rutina que es distinto de cero, sino que está
almacenado en el campo de estado de la Input6D objeto.

Si todo va bien, los valores mínimo y máximo se copian desde la


estructura que fue rellenado por el joystick conductor. El número de
botones es también más copiados, como es el nombre del conductor
(con la makeJavaString () de rutina).

El nativePoll () Método

El nativePoll () el método es muy similar a nativeSetup () y es casi tan sencilla:

vacío Input6D_nativePoll (struct HInput6D * este)


(
12

VRML 2.0 con Java CAPÍTULO 16

ClassInput6D * = datos unhand (este);


JOYINFOEX información;
info.dwSize = sizeof (info);
info.dwFlags = JOY_RETURNALL;
datos-> status = joyGetPosEx (datos-> puerto, & info);
datos-> rawX = info.dwXpos;
datos-> rawY = info.dwYpos;
datos-> rawZ = info.dwZpos;
datos-> rawR = info.dwRpos;
datos-> rawU = info.dwUpos;
datos-> rawV = info.dwVpos;
de datos> = 1 ha cambiado; / / true
if (datos-> botones! = info.dwButtons) (
de datos> = info.dwButtons botones;
datos-> whichButton = info.dwButtonNumber;
datos-> buttonChanged = 1; / / true
)
)

Un JOYINFOEX struct es creada, que mantendrá los datos del dispositivo


DirectInput. Es necesario decirle a Windows el tamaño de la estructura de
datos en el primer campo de la estructura y establecer un conjunto de
banderas en el segundo campo para que el conductor sabe que los datos que
deben regresar desde el dispositivo. En este caso, queremos que todos los
datos que tiene.

El valor de retorno de joyGetPosEx () es usado como el estado del dispositivo.


Todos los valores se copian más, y el cambio de bandera se establece. Una
aplicación más inteligente que comprobar si alguno de los valores de los datos
han cambiado, y sólo establece el cambio de pabellón en caso necesario, lo
que podría mejorar el desempeño en general, puesto que la aplicación tendría
que hacer menos trabajo, si sabían que no habían llegado los nuevos datos.

Por último, los botones están en comparación a su valor anterior para ver si
alguno de ellos han cambiado. Si los botones han cambiado, los nuevos valores
se leen, y el pabellón buttonChanged el valor true, que en este caso es 1, ya
están representados por Booleanos C largo tipos de datos en un método nativo.

El apoyo a múltiples tipos de dispositivos

A primera vista, puede parecer que nos limitamos a nosotros mismos a un solo
tipo de controlador de dispositivo, en este caso DirectInput. Que en realidad no
es el caso.
13

VRML 2.0 con Java CAPÍTULO 16

Si un usuario tiene alguna inusual dispositivo para el que ha escrito un


controlador, que puede modificar I6DImp.c a fin de que las llamadas de su
propio código para algunos números de puerto y DirectInput para otros.
Obviamente, esto debe ser manejado tanto en el nativeSetup () y nativePoll ()
métodos.

Por ejemplo, nativePoll () puede ser escrito como sigue:

vacío Input6D_nativePoll (struct HInput6D * este)


(
ClassInput6D * = datos unhand (este);
switch (datos-> puerto) (
case 0:
caso 1:
el caso 2:
readDirectInput (datos-> puerto, datos);
break;
caso 3:
readHeadTrackerDevice (datos-> puerto - 3, de datos);
break;
case 4:
caso 5:
readMyFunkyDevice (datos-> puerto - 4, datos);
break;
por defecto:
datos-> status = -1;
break;
)
)

En este caso, el readDirectInput () de rutina podría ser el mando de la lectura


de código que le hemos analizado anteriormente; readHeadTrackerDevice ()
sería una rutina de leer el seguimiento de algunos cascos de visualización, y
readMyFunkyDevice () sería una rutina de leer algún otro dispositivo de entrada
que no es apoyada por DirectInput.
Compilación de los métodos nativos

Hay una serie de pasos involucrados en la compilación de los métodos nativos


para su uso con Java. También hay un número específico de la plataforma y
compilador de cuestiones específicas que deben tratarse.

Si bien no es posible identificar todos los problemas en todas las diferentes


plataformas, es interesante el paso a través del proceso de, al menos, una
plataforma para ver lo que algunos de los escollos son. En este caso, vamos a
14

VRML 2.0 con Java CAPÍTULO 16

estar usando Watcom C al compilar nuestro código nativo.

La versión de Windows 95 JDK 1.0.2 está diseñado para trabajar con Microsoft
Visual C + + versión 2.0 o posterior. Las versiones anteriores del compilador de
Microsoft no son compatibles directamente, ni otros tales como compiladores
Watcom. Esto lleva a algunos problemas, pero afortunadamente hay soluciones
para todos ellos.
Primer paso: Compilar el código de Java

Comenzamos por compilar Input6D.java nuestro archivo:

javac Input6D.java

Esto, por supuesto, produce una Input6D.class archivo. Luego de que el


proceso utilizando el archivo de clase javah utilidad. Lo hacemos dos veces,
una para generar un archivo Input6D.h, y una vez para generar Input6D.c (un
"tonto" archivo que contiene la capa rutinas que llamar a nuestra aplicación de
métodos de los nativos):

javah Input6D
javah-talones Input6D

Segundo paso: Compilar el código C

Siguiente tenemos que compilar el archivo Input6D.c que acaba de crear, así
como el archivo que contiene I6DImp.c nuestros métodos nativos. Usando
Watcom C 10,6 o superior, debería ser sencillo, de empezar por asegurarse de
que el archivo de cabecera de Java son los directorios mencionados en la
variable de entorno INCLUYE:

=% serie INCLUYE INCLUYE%; \ java \ include; \ java \ include \ win32

Luego compilar el código usando la opción "-bd" Watcom opción que indica que
estamos creando un archivo DLL:

wcc386-bd Input6D.c

Es en este punto que se empieza a ejecutar en problemas. Lo primero que


observamos es que uno de los archivos de cabecera se suministra con el JDK,
typedef_md.h, no compila porque utiliza un tipo de datos que no es estándar C.
Que tipo de datos es Int64, uno de 64-bit que está disponible sólo en las
últimas versiones de Microsoft C + +. Que puedan existir en cualquier
compilador que se está usando y, de ser así, puede tener un nombre diferente.
Si tu compilador tiene una de 64-bit tipo de datos, pero no lo llaman Int64,
15

VRML 2.0 con Java CAPÍTULO 16

tendrá que modificar el archivo typedefs_md.h en consecuencia.

En el caso de Watcom C, no es de 64-bit tipo de datos. Eso significa que no


será capaz de manejar Java largo enteros en nuestros métodos nativos. Puesto
que no está utilizando en esta aplicación, que no es gran pérdida. Simplemente
vamos a modificar para cambiar el typedefs_md.h dos referencias a Int64
simplemente en int. Recuerde, sin embargo, que hacer esto hará que cualquier
nativo de los métodos que utilizan enteros de 64 bits para romper. Las líneas
en cuestión \ java \ include \ win32 \ typedefs_md.h son

typedef __int64int64_t;
typedef __int64 uint64_t sin firmar;

Que se convierten en

typedef int int64_t;


typedef unsigned int uint64_t;

Ahora intentar compilar de nuevo. Mucho mejor! Compilamos I6DImp.c de la


misma manera:

wcc386-bd I6DImp.c

Hasta ahora, todo bien.

Paso Tres: Construir la biblioteca compartida

A raíz de la designación en los archivos de ayuda Watcom, creamos un


archivo llamado enlazador directiva Input6D.lnk que tiene este aspecto:

sistema nt_dll InitInstance terminstance


exportación Input6D_nativePoll
exportación Input6D_nativeSetup
biblioteca javai.lib
archivo Input6D
archivo I6DImp

El javai.lib archivo es la biblioteca de rutinas de interfaz de Java que se


utilizan métodos por los nativos. Ahora intenta vincular:

wlink @ Input6D
16

VRML 2.0 con Java CAPÍTULO 16

Y tenemos referencias sin resolver! Resulta que el compilador Watcom


normalmente añade un guión bajo (_) al final de todos los símbolos
externos, lo que significa que no coinciden correctamente con los
símbolos que utiliza Java. Sin embargo, hay una solución: podemos
añadir un # pragma a cada símbolo, para informar al compilador
Watcom que no queremos que los símbolos mangling. Hay dos pragmas
necesarias en I6DImp.c, uno para cada uno de los dos métodos nativos:

# pragma Input6D_nativePoll a los "*"


# pragma Input6D_nativeSetup a los "*"

Observe que el método de nombres al comienzo con el nombre de la


clase. Hay cuatro pragmas talones necesarios en el archivo, Input6D.c:

# pragma Java_Input6D_nativeSetup_stub a los "*"


# pragma Java_Input6D_nativePoll_stub a los "*"
# pragma Input6D_nativeSetup a los "*"
# pragma Input6D_nativePoll a los "*"

Ahora podemos recompilar y enlace, y estamos casi allí. Hay un


problema pendiente: una referencia a la pendiente makeJavaString ()
método. Poner \ java \ lib en la variable de entorno LIB permite al
compilador Watcom encontrar el archivo javai.lib, y sabemos que
makeJavaString () es de allí, así que ¿por qué el compilador no puede
encontrar?

La respuesta es que el archivo javai.lib está diseñado para el compilador


de Microsoft, y estamos utilizando el compilador Watcom.
Afortunadamente, la biblioteca de C Watcom utilidad puede leer un
archivo DLL y crear una biblioteca:

wlib javai.lib + \ java \ bin \ javai.dll

Esto hace el truco. Ya no es necesario establecer la variable de LIB, y


ahora podemos enlazar de nuevo y nuestra DLL. ¡Éxito!

Aquí hay un makefile que hace todo el trabajo por nosotros:

Input6D.dll: Input6D.obj I6DImp.obj javai.lib


17

VRML 2.0 con Java CAPÍTULO 16

wlink @ Input6D

Input6D.obj: Input6D.c
wcc386-bd-5-i = f: \ java \ include-i = f: \ java \ include \ win32
Input6D.c

I6DImp.obj: I6DImp.c Input6D.h


wcc386-bd-5-i = f: \ java \ include-i = f: \ java \ include \ win32
I6DImp.c

Input6D.h: Input6D.class
javah Input6D

Input6D.c: Input6D.class
javah-talones Input6D
copia + Input6D.c pragma tmp
copia tmp Input6D.c
del tmp

Input6D.class: Input6D.java
javac Input6D.java
javai.lib: \ java \ bin \ javai.dll
wlib javai + \ java \ bin \ javai.dll

limpio:
del *. obj
del *. lib
del *. dll
del *. exe
del Input6D.c
del Input6D.h
del *. clase
del *.$$$$$$

Pragma el archivo sólo contiene las cuatro líneas que tenemos que
añadir a la Input6D.c antes del inicio de la compilación.
La definición de los prototipos

Input6D nuestra clase puede ser aplicado directamente en los scripts de


Java, y, de hecho, que a menudo la forma en que se utilizará. Por otra
18

VRML 2.0 con Java CAPÍTULO 16

parte, ya que no sabe nada acerca de VRML, la clase es útil para una
variedad de otras aplicaciones, también.

Sin embargo, hay suficiente para los usos Input6D en VRML que tiene
sentido para encapsular la funcionalidad en un prototipo. Nuestro PROTO
hará más fácil para los constructores de todo el mundo simplemente
para utilizar el nodo, sin tener que saber nada acerca de Java.

El propio PROTO tiene este aspecto:

# VRML V2.0 utf8

PROTO Input6DOF [
SFInt32 campo puerto 0
campo SFBool accumulateTranslations FALSE
campo SFBool accumulateRotations FALSE
SFVec3f translationScale campo 1 1 1
campo SFVec3f rotationScale 3,14159 3,14159 3,14159
SFBool campo habilitado TRUE
eventIn SFBool set_enabled
eventIn SFBool set_accumulateTranslations
eventIn SFBool set_accumulateRotations
eventIn SFBool nivel
eventIn SFBool casa
eventIn SFTime pollTime
eventOut SFString descripción
eventOut SFVec3f posición
eventOut SFRotation orientación
eventOut SFInt32 botones
eventOut SFInt32 whichButton
eventOut SFBool button1
eventOut SFBool button2
eventOut SFBool Button3
eventOut SFBool button4
eventOut SFBool button5
eventOut SFBool button6
eventOut SFBool button7
eventOut SFBool button8
]
(
19

VRML 2.0 con Java CAPÍTULO 16

Script (
url "Read6DOF.class"
SFInt32 campo puerto es el puerto
campo SFBool accumulateTranslations ES accumulateTranslations
campo SFBool accumulateRotations ES accumulateRotations
campo SFVec3f translationScale ES translationScale
campo SFVec3f rotationScale ES rotationScale
SFBool campo habilitado está habilitado
eventIn SFBool set_enabled ES set_enabled
eventIn SFBool set_accumulateTranslations ES
set_accumulateTranslations
eventIn SFBool set_accumulateRotations ES
set_accumulateRotations
eventIn SFBool nivel es el nivel
eventIn SFBool casa es casa # profunda!
eventIn SFTime pollTime ES pollTime
eventOut SFString descripción descripción
eventOut SFVec3f posición es la posición
eventOut SFRotation orientación orientación
eventOut SFInt32 botones botones ES
eventOut SFInt32 whichButton ES whichButton
eventOut SFBool button1 ES button1
eventOut SFBool button2 ES button2
eventOut SFBool Button3 ES Button3
eventOut SFBool button4 ES button4
eventOut SFBool button5 ES button5
eventOut SFBool button6 ES button6
eventOut SFBool button7 ES button7
eventOut SFBool button8 ES button8
)
)

El PROTO resulta ser nada más que un nodo de secuencias de


comandos, y se puede usar en cualquier lugar de comandos de un nodo
que puede aparecer en un archivo VRML.

Hay varios campos que son las mismas que las diversas variables de
instancia de la clase Input6D: puerto, accumluateTranslations, acumular-
Rotaciones, translationScale, y rotationScale. También hay habilitado un
20

VRML 2.0 con Java CAPÍTULO 16

campo que controla si el sensor se activa Input6DOF-es decir, la


generación de eventos. Hay eventIns para varios de estos campos.

También hay eventIns para reajustar el sensor de orientación (nivel) y la


traducción (en casa). Como se mencionó anteriormente, el nivel sólo
tiene sentido si accumulateRotations es TRUE, y el hogar sólo tiene
sentido si se acumulan-Translations es TRUE.

Lo más importante eventIn es pollTime, lo que indica que es tiempo de


tomar otra lectura. Esta ruta suele ser desde el momento de salida de
un TimeSensor.

El campo de descripción devuelto por el Input6D clase está disponible en


la descripción eventOut. Todas las demás corresponden a eventOuts
dinámicamente el cambio de valores: posición, orientación, y la situación
de los botones.

El botón de información de estado es muy útil y está disponible en una


variedad de formas. Los botones eventOut es un entero de 32 bits con
un bit por botón, lo que da a la mayoría de la información sino en la
forma menos conveniente. Sin embargo, puede resultar útil para un
desarrollador que quiere escribir un script que tiene acceso a toda la
información del estado de botón. Tener en cuenta, por supuesto, que son
muy pocos los dispositivos tendrán hasta en 32 botones.

El whichButton eventOut da el número del botón que se presiona, más


recientemente, y no en libertad. Si no se presiona el botón, el valor es
cero, de lo contrario, es un botón de número a partir del 1. Este campo
permite un número arbitrario de botones a utilizar, no sólo 32. El campo
whichButton puede enviarse a la whichChoice ámbito de un nodo Switch,
para seleccionar una representación de un objeto. El campo de
enclavamiento, de ser verdad, hace que el último botón presionado a
permanecer en el valor de whichButton el campo hasta que otro se pulsa
el botón, de lo contrario, el campo vuelve a cero tan pronto como se
suelta el botón.

Y, por último, hay un eventOut para cada uno de los primeros ocho
botones. Esto permite que los botones específicos para ser enviado a los
21

VRML 2.0 con Java CAPÍTULO 16

distintos nodos. Se pueden utilizar para activar o desactivar las luces, va


comenzar animaciones, y mucho más. Usted puede incluso VÍA
eventOuts botón derecho a la Input6DOF nodo. Por ejemplo, puede VÍA
un botón para el nivel eventIn a fin de que los niveles de apretar el
botón del objeto. Puede VÍA accumulateTranslation a un botón para que
pueda mover el punto de vista temporalmente lejos de la cabeza de tu
avatar y regresar automáticamente al soltar el botón. Ideal para un
"fuera del cuerpo" experiencia!
El código de Java para el Nodo de secuencias de comandos

Read6DOF El guión es muy sencillo. Hay una serie de variables de


instancia que corresponden a campos en el prototipo, así como una
inicializar () método que crea el objeto y Input6D establece sus campos
sobre la base de los campos de la PROTO. También se referencia a los
diversos eventOuts, ya vamos a estar usando un lote:

/ / Guión de lectura 6 grados de libertad dispositivos de entrada

/ / Escrito por Bernie Roehl, febrero de 1997

importación vrml .*;


importación vrml.node .*;
importación vrml.field .*;

clase pública se extiende Read6DOF Guión (


Input6D dispositivo;
boolean permitido;
booleano de enganche;
SFVec3f posición;
SFRotation orientación;
SFInt32 botones;
SFInt32 whichButton;
SFBool [] = buttonArray nuevo SFBool [8];

public void inicializar () (


int puerto = ((SFInt32) getField ( "puerto")). getValue ();
dispositivo = new Input6D (puerto);

/ / Establecer la acumulación de banderas


device.setAccumulateTranslations (
22

VRML 2.0 con Java CAPÍTULO 16

((SFBool) getField ( "accumulateTranslations")). GetValue ());


device.setAccumulateRotations (
((SFBool) getField ( "accumulateRotations")). GetValue ());

/ / Obtener la traducción escala


SFVec3f vec = (SFVec3f) getField ( "translationScale");
flotado [] = new escala flotado [3];
vec.getValue (escala);
device.setScaleX (escala [0]);
device.setScaleY (escala [1]);
device.setScaleZ (escala [2]);

/ / Obtener la rotación escala


SFVec3f rvec = (SFVec3f) getField ( "rotationScale");
flotado [] = new rscale flotar [3];
rvec.getValue (rscale);
device.setScaleR (rscale [0]);
device.setScaleU (rscale [1]);
device.setScaleV (rscale [2]);

/ / Inicializa permitido bandera


habilitado = ((SFBool) getField ( "permitido")). getValue ();

/ / Inicializar bandera de enganche


de enganche = ((SFBool) getField ( "enganche")). getValue ();

/ / Establecer la descripción
SFString descripción = (SFString) getEventOut ( "descripción");
description.setValue (device.getDescription ());

/ / Obtener las referencias a la salida de los campos


posición = (SFVec3f) getEventOut ( "posición");
orientación = (SFRotation) getEventOut ( "orientación");
botones = (SFInt32) getEventOut ( "botones");
whichButton = (SFInt32) getEventOut ( "whichButton");
for (int i = 1; i <= 8; i)
buttonArray [i-1] = (SFBool) getEventOut ( "botón" i);
)
23

VRML 2.0 con Java CAPÍTULO 16

También hay eventIns para reajustar el sensor de orientación (nivel) y la


traducción (en casa). Como se mencionó anteriormente, el nivel sólo
tiene sentido si accumulateRotations es TRUE, y el hogar sólo tiene
sentido si se acumulan-Translations es TRUE.

Lo más importante eventIn es pollTime, lo que indica que es tiempo de


tomar otra lectura. Esta ruta suele ser desde el momento de salida de
un TimeSensor.

El campo de descripción devuelto por el Input6D clase está disponible en


la descripción eventOut. Todas las demás corresponden a eventOuts
dinámicamente el cambio de valores: posición, orientación, y la situación
de los botones.

El botón de información de estado es muy útil y está disponible en una


variedad de formas. Los botones eventOut es un entero de 32 bits con
un bit por botón, lo que da a la mayoría de la información sino en la
forma menos conveniente. Sin embargo, puede resultar útil para un
desarrollador que quiere escribir un script que tiene acceso a toda la
información del estado de botón. Tener en cuenta, por supuesto, que son
muy pocos los dispositivos tendrán hasta en 32 botones.

El whichButton eventOut da el número del botón que se presiona, más


recientemente, y no en libertad. Si no se presiona el botón, el valor es
cero, de lo contrario, es un botón de número a partir del 1. Este campo
permite un número arbitrario de botones a utilizar, no sólo 32. El campo
whichButton puede enviarse a la whichChoice ámbito de un nodo Switch,
para seleccionar una representación de un objeto. El campo de
enclavamiento, de ser verdad, hace que el último botón presionado a
permanecer en el valor de whichButton el campo hasta que otro se pulsa
el botón, de lo contrario, el campo vuelve a cero tan pronto como se
suelta el botón.

Y, por último, hay un eventOut para cada uno de los primeros ocho
botones. Esto permite que los botones específicos para ser enviado a los
distintos nodos. Se pueden utilizar para activar o desactivar las luces, va
comenzar animaciones, y mucho más. Usted puede incluso VÍA
eventOuts botón derecho a la Input6DOF nodo. Por ejemplo, puede VÍA
un botón para el nivel eventIn a fin de que los niveles de apretar el
24

VRML 2.0 con Java CAPÍTULO 16

botón del objeto. Puede VÍA accumulateTranslation a un botón para que


pueda mover el punto de vista temporalmente lejos de la cabeza de tu
avatar y regresar automáticamente al soltar el botón. Ideal para un
"fuera del cuerpo" experiencia!
El código de Java para el Nodo de secuencias de comandos

Read6DOF El guión es muy sencillo. Hay una serie de variables de


instancia que corresponden a campos en el prototipo, así como una
inicializar () método que crea el objeto y Input6D establece sus campos
sobre la base de los campos de la PROTO. También se referencia a los
diversos eventOuts, ya vamos a estar usando un lote:

/ / Guión de lectura 6 grados de libertad dispositivos de entrada

/ / Escrito por Bernie Roehl, febrero de 1997

importación vrml .*;


importación vrml.node .*;
importación vrml.field .*;

clase pública se extiende Read6DOF Guión (


Input6D dispositivo;
boolean permitido;
booleano de enganche;
SFVec3f posición;
SFRotation orientación;
SFInt32 botones;
SFInt32 whichButton;
SFBool [] = buttonArray nuevo SFBool [8];

public void inicializar () (


int puerto = ((SFInt32) getField ( "puerto")). getValue ();
dispositivo = new Input6D (puerto);

/ / Establecer la acumulación de banderas


device.setAccumulateTranslations (
((SFBool) getField ( "accumulateTranslations")). GetValue ());
device.setAccumulateRotations (
((SFBool) getField ( "accumulateRotations")). GetValue ());
25

VRML 2.0 con Java CAPÍTULO 16

/ / Obtener la traducción escala


SFVec3f vec = (SFVec3f) getField ( "translationScale");
flotado [] = new escala flotado [3];
vec.getValue (escala);
device.setScaleX (escala [0]);
device.setScaleY (escala [1]);
device.setScaleZ (escala [2]);

/ / Obtener la rotación escala


SFVec3f rvec = (SFVec3f) getField ( "rotationScale");
flotado [] = new rscale flotar [3];
rvec.getValue (rscale);
device.setScaleR (rscale [0]);
device.setScaleU (rscale [1]);
device.setScaleV (rscale [2]);

/ / Inicializa permitido bandera


habilitado = ((SFBool) getField ( "permitido")). getValue ();

/ / Inicializar bandera de enganche


de enganche = ((SFBool) getField ( "enganche")). getValue ();

/ / Establecer la descripción
SFString descripción = (SFString) getEventOut ( "descripción");
description.setValue (device.getDescription ());

/ / Obtener las referencias a la salida de los campos


posición = (SFVec3f) getEventOut ( "posición");
orientación = (SFRotation) getEventOut ( "orientación");
botones = (SFInt32) getEventOut ( "botones");
whichButton = (SFInt32) getEventOut ( "whichButton");
for (int i = 1; i <= 8; i)
buttonArray [i-1] = (SFBool) getEventOut ( "botón" i);
)

El processEvent () método responde a pollTime eventIns tal y como era de


esperar. Si el sensor no está habilitada, el pollTime los eventos son
simplemente ignorados. En caso contrario, el dispositivo está encuestados y un
control de errores. Si los valores han cambiado, processEvent () establece la
26

VRML 2.0 con Java CAPÍTULO 16

nueva posición de la x, y, z los valores y leer desde el dispositivo. Se hace lo


mismo para las rotaciones, pero ya hay más generales que participan, por
primera vez controles para el caso de no común a todos los de rotación. De lo
contrario, utiliza algunos quaternion rutinas para convertir los tres ángulos de
rotación que se leen desde el dispositivo en el eje angular forma utilizada por
SFRotations en VRML. Esta es la sobrecarga adicional que queremos evitar en
todo caso los ángulos de cero. El código quaternion se describe más adelante
en este capítulo:

public void processEvent (Event ev) (


if (ev.getName (). es igual a ( "pollTime")) (
if (! permitido) / / no hacer nada si no nos permitió
retorno;
device.poll ();
if (device.getStatus ()! = 0) / / error de dispositivo
retorno;
if (device.hasChanged ()) (
position.setValue (
device.getX (), device.getY (), device.getZ ());
r = device.getR flotador ();
u = device.getU flotador ();
v = device.getV flotador ();
if (r == 0 & & u == 0 & & v == 0) / / sin rotación
orientation.setValue (0, 0, 1, 0);
else (
Quaternion q = new quaternion (u, r, v);
orientation.setValue (q.toAxisAndAngle ());
)
)
if (device.buttonHasChanged ()) (
int b = device.getButtons ();
if (! enclavamiento | | device.getButtons ()! = 0)
whichButton.setValue (device.getButton ());
for (int i = 0; i <8; i)
buttonArray [i]. SetValue ((b & (1 <<i))! = 0);
buttons.setValue (device.getButtons ());
)
)

El botón de código se ejecuta sólo cuando el cambio realmente botones estado.


Si estamos de enganche, nos fijamos el valor whichButton. También se que si
un botón está presionado, incluso si no estamos de enganche. Las ocho salidas
botón se establecen, como es el de 32-bit int que representa a todos los
botones.
27

VRML 2.0 con Java CAPÍTULO 16

Tenemos otros eventos de proceso, pero aviso que ponemos la pollTime


primero en nuestro caso-si otra escalera. Esto se debe a que será de lejos la
más común eventIn, por lo que tiene sentido para reducir al mínimo el tiempo
de procesamiento de cheques de inmediato.

El otro eventIns son bastante evidentes, ya que simplemente diferentes


variables de instancia y / o llamar a los métodos de la Input6D objeto:

else if (ev.getName (). es igual a ( "permitido"))


habilitado = ((ConstSFBool) ev.getValue ()). getValue ();
else if (ev.getName (). es igual a ( "nivel")) (
/ / Establecer todas las rotaciones a cero
si (((ConstSFBool) ev.getValue ()). getValue ()) (
device.setR (0);
device.setU (0);
device.setV (0);
)
)
else if (ev.getName (). es igual a ( "casa")) (
/ / Conjunto todas las traducciones a cero
si (((ConstSFBool) ev.getValue ()). getValue ()) (
device.setX (0);
device.setY (0);
device.setZ (0);
)
)
else if (ev.getName (). es igual a ( "set_accumulateTranslations")) (
device.setAccumulateTranslations (
((ConstSFBool) ev.getValue ()). GetValue ());
)
else if (ev.getName (). es igual a ( "set_accumulateRotations")) (
device.setAccumulateRotations (
((ConstSFBool) ev.getValue ()). GetValue ());
)
)

Cuaterniones

Cuaterniones son interesantes objetos matemáticos, que se utilizan a menudo


en gráficos por ordenador para representar a las rotaciones. Son más
compactos que las matrices de rotación (cuatro valores en lugar de nueve) y en
muchos casos son más eficientes. Asimismo, evitar la rotación de ciertos tipos
de problemas, si eres curioso acerca de este tema, ver los gráficos de libros de
28

VRML 2.0 con Java CAPÍTULO 16

texto para averiguar acerca de la "Gimbal candado" problema.

NOTA: Una descripción de las matemáticas detrás de cuaterniones es más


allá del alcance de este libro, sino un texto estándar de gráficos, tales como
gráficos de ordenador Principios y Práctica de Foley, van Dam, Feiner, y Hughs
(Addison-Wesley, 1990), debería dar que todos los antecedentes que usted
necesita.

Cuaterniones son similares al eje angular de la representación de VRML, en el


que hay un vector de tres elementos y un número que se corresponde con el
ángulo. Ellos pueden ser fácilmente convertidos al eje angular de la forma y
viceversa. Sin embargo, es mucho más fácil que se acumule el eje angular es
la forma, que es la razón por la que está utilizando aquí.

Usted puede recordar que después de leer los tres ángulos de rotación del
dispositivo de entrada, son convertidos a un quaternion y, a continuación, al
eje angular forma:

Quaternion q = new quaternion (u, r, v);


orientation.setValue (q.toAxisAndAngle ());

Este hace uso de uno de los constructores quaternion disponible en nuestra


clase:

/ / Quaternion rutinas

/ / Inspira en Gavin Bell rotation.c

clase pública quaternion (

flotado [] = new flotado valor [4];

public String toString () (


valor devuelto [0] + "" + valor [1] + ""
+ Valor [2] + "" + valor [3];
)

público quaternion (float [] q) (


valor [0] = q [0]; valor [1] = q [1];
valor [2] = q [2], valor [3] = q [3];
)

público quaternion (float [] eje, el ángulo de flotación) (


29

VRML 2.0 con Java CAPÍTULO 16

s = flotado (float) Math.sin (ángulo / 2);


for (int i = 0; i <3; + + i)
valor [i] = eje [i] * s;
valor [3] = (float) Math.cos (ángulo / 2);
)

público quaternion (char eje, el ángulo de flotación) (


valor [3] = (float) Math.cos (ángulo / 2);
valor [0] = valor [1] = valor [2] = 0.0F;
switch (eje) (
case 'x': case 'X':
valor [0] = (float) Math.sin (ángulo / 2); break;
case 'y': case 'Y':
valor [1] = (float) Math.sin (ángulo / 2); break;
case 'z': case 'Z':
valor [2] = (float) Math.sin (ángulo / 2); break;
)
)

público quaternion (guiñada flotador, float pitch, float roll) (


Quaternion q;
if (guiñada! = 0) (
q = new quaternion ( 'Y', de orientación);
if (campo! = 0)
q.multiply (nuevo quaternion ( 'X', tono));
if (roll! = 0)
q.multiply (nuevo quaternion ( 'Z' roll));
)
else if (paso! = 0) (
q = new quaternion ( 'X', brea);
if (roll! = 0)
q.multiply (nuevo quaternion ( 'Z' roll));
)
algo más
q = new quaternion ( 'Z' roll);
valor [0] = q.value [0]; valor [1] = q.value [1];
valor [2] = q.value [2], valor [3] = q.value [3];
)

El quaternion clase contiene una serie de cuatro flotadores para almacenar el


quaternion sí mismo. El primer constructor de llena en estos cuatro valores
directamente. El segundo eje-convierte un ángulo de la representación en un
quaternion. La tercera se refiere brevemente a los tres casos más comunes: la
rotación sobre una de las x, y, z o ejes. El cuarto y último constructor, que es la
30

VRML 2.0 con Java CAPÍTULO 16

que usamos en Read6DOF, tiene los tres ángulos de rotación y las aplica en el
orden de orientación, tono, rollo (es decir, gira alrededor de la x, y, z o ejes). Lo
hace mediante la construcción de cuaterniones y multiplicando cada uno de
ellos juntos. El código se ha estructurado a fin de evitar la multiplicación
cuando no es necesario, que es de nuevo un examen de eficiencia, ya que la
multiplicación de código es bastante complejo e implica un gran número de
múltiplos:

multiplicar vacío (quaternion q) (


flotado [] tmp = new flotar [4];
tmp [0] = q.value [3] * valor [0] + q.value [0] * valor [3]
+ Q.value [1] * valor [2] - q.value [2] * valor [1];
tmp [1] = q.value [3] * valor [1] + q.value [1] * valor [3]
+ Q.value [2] * valor [0] - q.value [0] * valor [2];
tmp [2] = q.value [3] * valor [2] + q.value [2] * valor [3]
+ Q.value [0] * valor [1] - q.value [1] * valor [0];
tmp [3] = q.value [3] * valor [3] - q.value [0] * valor [0]
- Q.value [1] * valor [1] - q.value [2] * valor [2];
valor [0] = tmp [0]; valor [1] = tmp [1];
valor [2] = tmp [2], valor [3] = tmp [3];
)

El último método en nuestra clase quaternion es el que convierte en un eje


quaternion forma de ángulo:

público flotar [] toAxisAndAngle () (


flotado [] = new flotado bis [4];
aa [3] = (float) Math.acos (valor [3]) * 2;
s = flotado (float) Math.sin (aa [3] / 2);
for (int i = 0; i <3; + + i)
aa [i] = valor [i] / s;
regresar aa;
)

Esto es sólo la inversa de la operación que se utilizó en el segundo constructor.

Una muestra del archivo

El siguiente archivo VRML te da una idea de los diversos usos de los Input6DOF
nodo. Está destinado a servir como punto de partida para sus proyectos;
descomentar las distintas vías, al final del archivo para ver lo que hacen:

# VRML V2.0 utf8


31

VRML 2.0 con Java CAPÍTULO 16

EXTERNPROTO Input6DOF [
SFInt32 campo puerto
SFBool accumulateTranslations campo
SFBool accumulateRotations campo
SFVec3f translationScale campo
SFVec3f rotationScale campo
SFBool campo habilitado
SFBool campo de enclavamiento
eventIn SFBool set_enabled
eventIn SFBool set_accumulateTranslations
eventIn SFBool set_accumulateRotations
eventIn SFBool nivel
eventIn SFBool casa
eventIn SFTime pollTime
eventOut SFString descripción
eventOut SFVec3f posición
eventOut SFRotation orientación
eventOut SFInt32 botones
eventOut SFInt32 whichButton
eventOut SFBool button1
eventOut SFBool button2
eventOut SFBool Button3
eventOut SFBool button4
eventOut SFBool button5
eventOut SFBool button6
eventOut SFBool button7
eventOut SFBool button8
] "Input6DOF.wrl"

DEF NI NavigationInfo ()

Punto de vista de la posición (0 0 10)

DirectionalLight (dirección -1 0 0)

DEF TS TimeSensor (bucle TRUE)

Transformar (DEF TR
niños pequeños
DEF SW Switch (
whichChoice 0
elección [
(Grupo)
32

VRML 2.0 con Java CAPÍTULO 16

Forma (
Un aspecto DEF Aspecto (
material Material (diffuseColor 1 0 0)
)
geometría recuadro ()
)
Forma (Un aspecto USO geometría Esfera ())
Forma (Un aspecto USO geometría Cilindro ())
Forma (Un aspecto USO geometría Cono ())
]
)
)
# (DEF SENSOR Input6DOF
# AccumulateRotations TRUE
# RotationScale .314159 .314159 .314159
#)

DEF SENSOR Input6DOF (


accumulateTranslations TRUE
translationScale .314159 .314159 .314159
# Enclavamiento TRUE
)

VÍA TS.time A SENSOR.pollTime


VÍA SENSOR.position A TR.translation
VÍA SENSOR.orientation A TR.rotation
VÍA SENSOR.whichButton A SW.whichChoice
# SENSOR.button2 VÍA A SENSOR.accumulateTranslations
# SENSOR.button3 VÍA A SENSOR.home

Problemas de rendimiento y disponibilidad

Hay dos cuestiones importantes a considerar cuando se utiliza este código:


rendimiento y disponibilidad.

El rendimiento es una cuestión cada vez que usan Java. El código no se


presenta aquí la mayor parte del trabajo en Java, en aras de la portabilidad. La
ventaja es que un desarrollador puede añadir soporte para un nuevo
dispositivo simplemente escribir un par de 10-línea C funciones. La desventaja
es que la sobrecarga de uso de Java puede ser un problema, especialmente en
áreas críticas de latencia-como cabeza de seguimiento.

Hay varias cosas que podríamos hacer para mejorar el rendimiento. Puesto que
está utilizando métodos nativos de todos modos, no se había ningún daño en la
33

VRML 2.0 con Java CAPÍTULO 16

aplicación del código en C. quaternion De hecho, gran parte de la funcionalidad


de Input6D.java podría ser trasladado a C, aunque no está claro cuánto de una
ganancia de rendimiento en realidad resultado.

La disponibilidad cuestión deriva del hecho de que el modelo de seguridad


utilizado en la mayoría de los navegadores Web puede evitar el uso de
métodos a todos los nativos. Los ejemplos en este capítulo se probaron
utilizando la versión independiente de la realidad de líquidos, y puede que no
funcionen en un VRML plug-in para un navegador Web. Por supuesto, si estás
utilizando un dispositivo de entrada de 6 DOF, las probabilidades son que usted
está usando Netscape algo distinto de todos modos.

Otro aspecto de la disponibilidad que es un motivo de preocupación es el


hecho de que no todas las máquinas virtuales Java de manejar los métodos
nativos de la misma manera. Concretamente, el código compilado bajo el sol
JDK 1.0.2 no funciona con la máquina virtual de Microsoft, y viceversa. La única
solución en este momento es compilar en dos ocasiones y que el usuario
instale el correcto para su navegador. Tenga en cuenta que algunos
navegadores (como líquido realidad, que se utilizó para probar el código en
este capítulo) están disponibles en dos versiones: una que utiliza el JDK de Sun
y uno que utiliza Microsoft.

La verdadera solución a ambos problemas es que el nodo Input6DOF que se


construirán en el propio navegador de VRML. Ya no sería necesario VÍA eventos
pollTime a la entrada, ya que el navegador se aseguraría de que el nodo
responde cada vez que el dispositivo de entrada cambia de estado. Los gastos
generales sería eliminado, ya que el dispositivo de apoyo sería en código
nativo. El problema de seguridad también desaparecer, ya que no DLL locales
tendría que ser cargado.
Orientación futura

El código presentado en este capítulo está diseñado para hacer más fácil para
usted para apoyar DOF 6 dispositivos de entrada en las aplicaciones Java y
mundos VRML.

Si encuentra útil este código, o si el apoyo para desarrollar otros dispositivos u


otras plataformas, por favor, mándenme una línea (mi dirección de correo
electrónico está broehl@ece.uwaterloo.ca). La última versión de este código, y
los otros proyectos de este libro, se puede encontrar en mi sitio Web:
http://ece.uwaterloo.ca/ ~ broehl / vrml.

You might also like