|
Buscador
Secciones
Otras zonas
Registro
Foros
Recomendamos
|
La cosas naturales, como los árboles, utilizan una tremenda cantidad de geometría para representar de forma segura todas la estructura de ramas, hojas y tronco. Una alternativa es usar un polígono texturado en lugar de la geometría. Esta técnica algunas veces es referida como la aproximación cartelera. Esto es cierto especialmente cuando se usa un comportamiento para orientar automáticamente el polígono texturado hacia el espectador para que sólo se vea el frente de la superficie texturada. Este comportamiento de orientación se llama comportamiento cartelera. Esta aproximación es efectiva cuando el objeto a representar por la textura está lejano para que las partes individuales del objeto visual no sean fácilmente distinguibles. Para el ejemplo del árbol, si el espectador está tan alejado que las ramas son dificiles de distinguir, no merece la pena gastar recursos de memoria y de cálculo para representar todas las hojas del árbol. Esta técnica está recomendada para cualquier aplicación que requiera visualizar objetos complejos en la distancia. Sin embargo, si el espectador puede aproximarse a la cartelera, a cierta distancia el grado de profundidad del polígono textura podría ser detectado por el espectador. El comportamiento de nivel de detalle (LOD) tiene una aplicación relacionada. Con LOD, los objetos visualmente complejos son representados por múltiples objetos visuales variando los niveles de detales (de ahí su nombre). La representación del objeto visual con menor nivel de detalle se usa cuando el espectador está lejos. La representación con más nivel de detalle se usa cuando el espectador está muy cerca. El comportamiento LOD cambia automáticamente entre las representación del objeto basándose en la distancia al espectador. Los comportamientos de cartelera y de nivel de detalle corresponden a clases extendidas desde Behavior que implementan estas aplicaciones comunes. Son posibles otros comportamientos especilizados y varios de ellos se pueden ver en la Figura 4-1. Por ejemplo, hay varias clases MouseBehavior que manipulan una transformación en respuesta a movimientos del ratón. Normalmente la transformación de la vista se cambia por el comportamiento del ratón para cambiar la vista en respuesta a una acción del ratón. Observa también como los comportamientos pueden encadenarse. Por ejemplo, los movimientos del ratón o las pulsaciones de teclas pueden usarse para cambiar la vista. En respuesta al movimiento de la vista, podrían tener lugar otros comportamientos como la cartelera, o el nivel de detalles. Afortunadamente, cada comportamiento se especifica de forma separada. Animación contra Interacción Como la distinción entre animación e interacción usada en este tutorial está bastante bien, aquí hay un ejemplo para clarificar esta distinción. Si un usuario navega en un programa donde se proporciona un comportamiento, la vista se moverá en respuesta a eventos del teclado y/o ratón. El movimiento de la plataforma de la vista es una interacción porque es el resultado directo de una acción del usuario. Sin embargo, otras cosas podrían cambiar como resultado del movimiento de la plataforma de la vista, (por ejemplo, comportamientos de cartelera o LOD). Los cambios causados como resultado del movimiento de la plataforma de vista son indirectamente causados por el usuario y por lo tanto son animaciones.
|
|
Sumario de Métodos de la Clase Behavior Behavior es una clase abstracta que contiene el marco de trabajo para los componentes de comportamiento en Java 3D. View getView() Devuelve la vista primaria asociada con este comportamiento. void initialize() Inicializa este comportamiento. void postId(int postId) Postea la identidad especificada. void processStimulus(java.util.Enumeration criteria) Procesa un estímulo para este comportamiento. void setEnable(boolean state) Activa o desactiva este comportamiento. void setSchedulingBoundingLeaf(BoundingLeaf region) Selecciona la región de límites del comportamiento con los límites del leaf especificado. void setSchedulingBounds(Bounds region) Selecciona la región de límites del comportamiento con los límites especificados. void wakeupOn(WakeupCondition criteria) Define este criterio de disparo del comportamiento. |
API ViewPlatform
Los Comportamientos están activos (dispuestos para ser disparados) sólo cuando sus límites (o BoundingLeaf) intersecciona con el volumen de activación de una ViewPlatform.
|
Lista Parcial de Métodos de la Clase ViewPlatform Estos métodos de la clase ViewPlatform obtienen y seleccionan el radio del volumen de activación (esfera). El valor por defecto es 62. float getActivationRadius() Obtiene el radio de activación del ViewPlatform. void setActivationRadius(float activationRadius) Selecciona el radio de activación del ViewPlatform que define un volumen de activación alrededor de la plataforma. |
Condiciones de Disparo: Cómo se Disparan los ComportamientosLos comportamientos activados se disparan por la ocurrencia de uno o más estimulos especificados. El estimulo de disparo para un comportamiento se especifica usando descendientes de la clase WakeupCondition.
La clase abstracta, WakeupCondition, es la base para todas las clases de disparo del API Java 3D. Cinco clases extienden WakeupCondition, una es la clase abstracta WakeupCriterion, las otras cuatro permiten la composición de múltiples condiciones de disparo en una única condición de disparo. La Figura 4-7 muestra el árbol de clases.

Una condición de disparo para un objeto behavior se puede especificar como un criterio de disparo específico o como una combinación de criterios usando clases compuestas. Las siguientes secciones describen WakeupCondition y sus subclases.
WakeupConditionLa clase WakeupCondition proporciona dos métodos. El primer método, allElements, devuelve una lista enumeration de todos los criterios de disparo para el objeto WakeupCondition. El otro método, triggeredElements, enumera qué criterio ha causado que el comportamiento sea disparado. Este método podría ser muy útil en el método processStimulus de un objeto Behavior.
|
Sumario de Métodos de WakeupCondition La clase abstracta WakeupCondition es la base para todas las clases wakeup. Proporciona los siguientes métodos: Enumeration allElements() Devuelve una enumeración con todos los objetos WakeupCriterion en esta condición. Enumeration triggeredElements() Devuelve una enumeración de todos los objetos WakeupCriterion disparados en esta condición. |
WakeupCriterionWakeupCriterion es una clase abstracta para todas las clases wakeup. WakeupCriterion sólo proporciona un método: hasTriggered. Probablemente no necesitaremos usar este método ya que el método triggeredElements de WakeupCondition realiza esta operación por nosotros.
|
Sumario de Métodos de WakeupCriterion boolean hasTriggered() Devuelve true si el criterio disparó el comportamiento. |
Clases WakeupCriterion EspecíficasLa Tabla 4-2 presenta las 14 clases WakeupCriterion específicas. Estas clases se usan para especificar las condiciones de disparo de los objetos behavior. Los ejemplares de estas clases se usan individualmente o en combinaciones.
| Clase Criterio | Disparo |
|---|---|
| WakeupOnActivation | en la primera detección de una intersección del volumen de activación de un ViewPlatform con la región límite del objeto. |
| WakeupOnAWTEvent | cuando ocurre un evento AWT específico |
| WakeupOnBehaviorPost | cuando un objeto behavior envía un evento específico |
| WakeupOnCollisionEntry | en la primera detección de colisión del objeto especificaco con otro objeto del escenario gráfico. |
| WakeupOnCollisionExit | cuando el objeto especifico no colisiona con ningún otro objeto del escenario gráfico. |
| WakeupOnCollisionMovement | cuando el objeto especificado se mueve mientras colisiona con otro objeto del escenario gráfico |
| WakeupOnDeactivation | cuando el volumen de activación de un ViewPlatform deja de intereseccionar con los límites del objeto |
| WakeupOnElapsedFrames | cuando ha pasado un número determinado de frames |
| WakeupOnElapsedTime | cuando ha pasado un número de segundos determinado |
| WakeupOnSensorEntry | en la primera detección de cualquier sensor que intersecciona con los límites especificados |
| WakeupOnSensorExit | cuando un sensor que interseccionava con los límites del objeto deja de interseccionar con los límites especificados |
| WakeupOnTransformChange | cuando cambia la transformación dentro de un TransformGroup especificado |
| WakeupOnViewPlatformEntry | en la primera detección de intersección del volumen de activación de un ViewPlatform con los límites especificados |
| WakeupOnViewPlatformExit | cuando el volumen de activación de una vista deja de intereseccionar con los límites especificados |
Comentarios Generales sobre WakeupCriterion
Varias clases WakeupCriterion se disparan con la "primera detección" de un evento. Lo que significa que el criterio sólo se disparará una vez por cada evento. Por ejemplo, un objeto WakeupOnActivation disparará la intersección del volumen de activación de un ViewPlatform y la región de límites del objeto behavior asociado. Mientras que la intersección persista, el WakeupCondition no se disparará de nuevo. Lo mismo es cierto para cualquier marco secuencial. Hasta que Java 3D detecte que los volumenes no intereseccionan más no se podrá disparar de nuevo el WakeupCondition.
Hay varias parejas de clases WakeupCriterion correspondientes (Entry/Exit o Activation/Deactivation). Este criterio sólo se disparará en elternancias estrictas empezando con los criterios de Entry o Activation.
WakeupOnActivation
Es posible que una región de límites interseccione con el volumen de activación de un ViewPlatform tan brevemente que no sea detectada. Consecuentemente, no se disparará ninguna condición de Activation o Deactivation. Bajo estas circunstancias, el comportamiento no se activa nunca.
|
Sumario de Constructores de WakeupOnActivation Extiende: WakeupCriterion Esta clase especifica la condición de disparo en la primera detección de una interesección del volumen de activación de un ViewPlatform con la región límite de su objeto. WakeupOnActivation está emparejado con WakeupOnDeactivation que veremos más adelante. WakeupOnActivation() Construye un nuevo criterio WakeupOnActivation. |
WakeupOnAWTEvent
Varias de las clases WakeupCriterion tienen constructores y métodos dependientes del disparo. Por ejemplo, WakeupOnAWTEvent tiene dos constructores y un método. Los constructores permiten la especificación de eventos AWT usando constantes de clases AWT. El método devuelve el array de eventos AWT consecutivos que causaron el disparo.
|
Sumario de Constructores de WakeupOnAWTEvent Extiende: WakeupCriterion Esta clase especifica el disparo de un Behavior cuando ocurre un evento AWT específico. WakeupOnAWTEvent(int AWTId) Construye un nuevo objeto WakeupOnAWTEvent, donde AWTId es uno de KeyEvent.KEY_TYPED, KeyEvent.KEY_PRESSED, KeyEvent.KEY_RELEASED, MouseEvent.MOUSE_CLICKED, MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, MouseEvent.MOUSE_MOVED, MouseEvent.MOUSE_DRAGGED, o uno de los otros muchos valores de eventos. WakeupOnAWTEvent(long eventMask) Construye un nuevo objeto WakeupOnAWTEvent usando valores ORed EVENT_MASK. Estos valores son: KEY_EVENT_MASK, MOUSE_EVENT_MASK, MOUSE_MOTION_EVENT_MASK, u otros valores. |
|
Sumario de métodos de WakeupOnAWTEvent AWTEvent[] getAWTEvent() Recupera el array de eventos AWT consecutivos que ocasionaron el disparo. |
WakeupOnBehaviorPost
La condición WakeupOnBehaviorPost junto con el método postID de la clase Behavior proporcionan un mecanismo a través del cual se pueden coordinar los comportamientos. Un objeto Behavior puede postear un valor entero ID particular. Otro comportamiento puede especificar su condición de disparo, usando un WakeupOnBehaviorPost, cómo enviando un ID particular desde un objeto Behavior específico. Esto permite la creacción de objetos Behavior parentales como que uno abra una puerta y otro diferente la cierre. Para esta materia, incluso se pueden formular comportamientos más complejos usando comportamientos y coordinación posterior.
|
Sumario de Constructores de WakeupOnBehaviorPost Extiende: WakeupCriterion Esta clase especifica un disparo de un objeto Behavior cuando un comportamiento específico postea un evento específico. WakeupOnBehaviorPost(Behavior behavior, int postId) Construye un nuevo criterio WakeupOnBehaviorPost. |
Como un WakeupCondition puede estar compuesto por varios objetos WakeupCriterion, incluyendo más de un WakeupOnBehaviorPost, los métodos para determinar la especificidad son necesarios para interpretar un evento de disparo.
|
Sumario de Métodos de WakeupOnBehaviorPost Behavior getBehavior() Devuelve el comportamiento especificado en este constructor. int getPostId() Recupera el posId especificado en el WakeupCriterion. Behavior getTriggeringBehavior() Devuelve el comportamiento que disparo este evento. int getTriggeringPostId() Devuelve el postId que causó el disparo del comportamiento. |
El Fragmento de Código 4-3 y el Fragmento de Código 4-4 muestran un código parcial para un programa de ejemplo que usa posteo de comportamientos para coordinar comportamientos. El ejemplo abre y cierra una puerta. El código incluye una clase: OpenBehavior, y el código que crea los dos objetos behavior. El segundo objeto es un ejemplar de CloseBehavior, que es casi un duplicado exacto de OpenBehavior. En CloseBehavior, la condición es compartida en el método initialization (y el comportamiento opuesto completado).
1. public class OpenBehavior extends Behavior{
2.
3. private TransformGroup targetTG;
4. private WakeupCriterion pairPostCondition;
5. private WakeupCriterion AWTEventCondition;
6.
7. OpenBehavior(TransformGroup targetTG){
8. this.targetTG = targetTG;
9. AWTEventCondition = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
10. }
11.
12. public void setBehaviorObjectPartner(Behavior behaviorObject){
13. pairPostCondition = new WakeupOnBehaviorPost(behaviorObject, 1);
14. }
15.
16. public void initialize(){
17. this.wakeupOn(AWTEventCondition);
18. }
19.
20. public void processStimulus(Enumeration criteria){
21. if (AWTEventCondition.hasTriggered()){
22. // make door open – code excluded
23. this.wakeupOn(pairPostCondition);
24. postId(1);
25. } else {
26. this.wakeupOn(AWTEventCondition);
27. }
28. }
29.
30. } // end of class OpenBehavior
1. // inside a method to assemble the scene graph ... 2. 3. // create the relevant objects 4. TransformGroup doorTG = new TransformGroup(); 5. OpenBehavior openObject = new OpenBehavior(doorTG); 6. CloseBehavior closeObject = new CloseBehavior(doorTG); 7. 8. //prepare the behavior objects 9. openObject.setBehaviorObjectPartner(closeObject); 10. closeObject.setBehaviorObjectPartner(openObject); 11. 12. // set scheduling bounds for behavior objects – code excluded 13. 14. // assemble scene graph – code excluded 15.
Los objetos de estas dos clases responderán en estricta alternancia a los eventos de pulsación de teclas. El comportamiento OpenBehavior se disparará en respuesta a la primera pulsación. En su respuesta, señala el comportamiento CloseBehavior y selecciona su condición de disparo para que sea una señal para este objeto. El objeto CloseBehavior selecciona su condición de disparo para que sea una pulsación de tecla en respuesta a la señal desde el objeto OpenBehavior. Puedes encontrar un programa de ejemplo en DoorApp.java.
La siguiente pulsación de tecla dispara el objeto CloseBehavior. Este objeto ahora realiza la misma función que acaba de realizar el objeto OpenBehavior: envía una señal y resetea su propia condición de disparo. El objeto CloseBehavior cierra la puerta en respuesta a la pulsación de tecla. De vuelta a las condiciones iniciales, la siguiente pulsación empezará de nuevo todo el proceso.
WakeupOnCollisionEntry
Java 3D puede detectar la colisión de objetos en el mundo virtual. Hay tres clases WakeupCriterion útiles para procesar la colisión de objetos: WakeupOnCollisionEntry, WakeupOnCollisionMovement, y WakeupOnCollisionExit.
Un Criterio WakeupOnCollisionEntry se disparará cuando un objeto colisione por primera vez. Luego, el criterio WakeupOnCollisionMovement disparará (potencialmente varios disparos) mientras dos objetos están en colisión hay un movimiento relativo entre los objetos. Finalmente, un sólo WakeupOnCollisionExit se diparará cuando finalice la colisión.
Java 3D sólo puede manejar una colisión por cada objeto a la vez. Una vez que se ha detectado una colisión de un objeto, las colisiones con otros objetos no se detectarán hasta que finalice la primera colisión. También puede ocurrir que una colisión sea tan breve que no sea detectada y por lo tanto no se disparará ninguna condición.
La detección de colisiones es más compleja que esta discusión sobre las condiciones de disparo. Sin embargo este tutorial no cubre la detección de colisiones en detalle, para esto puedes referirte a la Especificación del API Java 3D.
|
Sumario de Constructores de WakeupOnCollisionEntry Extiende: WakeupCriterion Esta clase especifica un disparo en la primera detección de colisión de un objeto especificado con otro objeto en el escenario gráfico. También puedes ver: WakeupOnCollisionMovement, y WakeupOnCollisionExit. WakeupOnCollisionEntry(Bounds armingBounds) Construye un nuevo criterio WakeupOnCollisionEntry. WakeupOnCollisionEntry(Node armingNode) Construye un nuevo cirterio WakeupOnCollisionEntry. WakeupOnCollisionEntry(Node armingNode, int speedHint) Construye un nuevo criterio WakeupOnCollisionEntry, donde speedHint es:
WakeupOnCollisionEntry(SceneGraphPath armingPath) Construye un nuevo criterio WakeupOnCollisionEntry con USE_BOUNDS como velocidad de choque. WakeupOnCollisionEntry(SceneGraphPath armingPath, int speedHint) Construye un nuevo criterio WakeupOnCollisionEntry, donde speedHint es USE_BOUNDS o USE_GEOMETRY. |
WakeupOnCollisionExit
|
Sumario de Constructores de WakeupOnCollisionExit Extiende: WakeupCriterion Esta clase especifica un disparo cuando se termina la colisión de un objeto especificado con otro objeto en el escenario gráfico. También puedes ver: WakeupOnCollisionMovement, y WakeupOnCollisionExit. WakeupOnCollisionExit(Bounds armingBounds) Construye un nuevo criterio WakeupOnCollisionExit. WakeupOnCollisionExit(Node armingNode) Construye un nuevo criterio WakeupOnCollisionExit. WakeupOnCollisionExit(Node armingNode, int speedHint) Construye un nuevo criterio WakeupOnCollisionExit, donde speedHint es:
WakeupOnCollisionExit(SceneGraphPath armingPath) Construye un nuevo criterio WakeupOnCollisionExit. WakeupOnCollisionExit(SceneGraphPath armingPath, int speedHint) Construye un nuevo criterio WakeupOnCollisionExit, donde speedHint es USE_BOUNDS, o USE_GEOMETRY. |
|
Sumario de Métodos de WakeupOnCollisionExit Bounds getArmingBounds() Devuelve los límites del objeto usado en la especificación de la condición de colisión. SceneGraphPath getArmingPath() Devuelve el path usado en la especificación de la condición de colisión. Bounds getTriggeringBounds() Devuelve el objeto Bounds que causó la colisión. SceneGraphPath getTriggeringPath() Devuelve el path que describe el objeto que causó la colisión. |
WakeupOnCollisionMovement
|
Sumario de Constructores de WakeupOnCollisionMovement Extiende: WakeupCriterion Esta clase especifica un disparo cuando el objeto especificado se mueve durante la colisión con otro objeto en el escenario gráfico. También puedes ver: WakeupOnCollisionEntry, y WakeupOnCollisionExit. WakeupOnCollisionMovement(Bounds armingBounds) Construye un nuevo criterio WakeupOnCollisionMovement. WakeupOnCollisionMovement(Node armingNode) Construye un nuevo criterio WakeupOnCollisionMovement. WakeupOnCollisionMovement(Node armingNode, int speedHint) Construye un nuevo criterio WakeupOnCollisionMovement, donde speedHint es:
WakeupOnCollisionMovement(SceneGraphPath armingPath) Construye un nuevo criterio WakeupOnCollisionMovement. WakeupOnCollisionMovement(SceneGraphPath armingPath, int speedHint) Construye un nuevo criterio WakeupOnCollisionMovement, donde speedHint es USE_BOUNDS, o USE_GEOMETRY. |
|
Sumario de Métodos de WakeupOnCollisionMovement Bounds getArmingBounds() Devuelve el objeto Bounds usado para especificar la condición de colisión. SceneGraphPath getArmingPath() Devuelve el path usado en la especificación de la condición de colisión. Bounds getTriggeringBounds() Devuelve el objeto Bounds que causó la colisión. SceneGraphPath getTriggeringPath() Devuelve el path que describe el objeto que causó la colisión. |
WakeupOnDeactivation
|
Sumario de Constructores de WakeupOnDeactivation Extiende: WakeupCriterion Esta clase especifica un disparo para la primera detección de que el volumen de activación deja de interseccionar con la región de límites de este objeto. También puedes ver WakeupOnActivation. WakeupOnDeactivation() Construye un nuevo criterio WakeupOnDeactivation. |
WakeupOnElapsedFrames
El objeto WakeupOnElapsedFrames se usa para disparar un objeto activo después de que haya pasado un número especificado de frames. Un frameCount de 0 especifica que se dispare en el siguiente frame.
|
Sumario de Constructores de WakeupOnElapsedFrames Extiende: WakeupCriterion Esta clase especifica un disparo cuando han pasado un número especificado de frames. WakeupOnElapsedFrames(int frameCount) Construye un nuevo criterio WakeupOnElapsedFrames. |
|
Sumario de Métodos de WakeupOnElapsedFrames int getElapsedFrameCount() Devuelve el contador de marcos WakeupCriterion que fue utilizado cuando se construyó este objeto. |
WakeupOnElapsedTime
Java 3D no puede garantizar el tiempo exacto entre disparos para un criterio WakeupOnElapsedTime. Un disparo ocurrirá en el momento especificado, o muy cercano.
|
Sumario de Constructores de WakeupOnElapsedTime Extiende: WakeupCriterion Esta clase especifica un disparo después de que hayan pasado un número de milisegundos especificado. WakeupOnElapsedTime(long milliseconds) Construye un nuevo criterio WakeupOnElapsedTime. |
|
Sumario de Métodos de WakeupOnElapsedTime long getElapsedFrameTime() Devuelve el valor de tiempo que se utilizó en la construcción de este objeto. |
WakeupOnSensorEntry
En Java 3D, cualquier dispositivo de entrada distinto del teclado o el ratón es un sensor. Un sensor es un concepto abstracto para un dispositivo de entrada. Cada sensor tiene un punto caliente definido en el sistema de coordenadas del sensor. La intersección del punto caliente de un sensor con una región puede detectarse con las clases WakeupOnSensorEntry y WakeupOnSensorExit.
Es posible que un sensor entre y salga de una región armada tan rápidamente que ninguna de las condiciones se dispare.
|
Sumario de Constructores de WakeupOnSensorEntry Extiende: WakeupCriterion Esta clase especifica un disparo en la primera detección de la intersección de cualquier sensor con los límites especificados. WakeupOnSensorEntry(Bounds region) Construye un nuevo criterio WakeupOnEntry. |
|
Sumario de Métodos de WakeupOnSensorEntry Bounds getBounds() Devuelve la especificación de límites de este objeto. |
WakeupOnSensorExit
|
Sumario de Constructores de WakeupOnSensorExit Extiende: WakeupCriterion Esta clase especifica un disparo en la primera detección de que un sensor que previamente intereseccionaba con los límites deja de intereseccionar con los límites especificados. También puedes ver WakeupOnSensorEntry. WakeupOnSensorExit(Bounds region) Construye un nuevo criterio WakeupOnExit. |
|
Sumario de Métodos de WakeupOnSensorExit Bounds getBounds() Devuelve la especificación de límites de este objeto. |
WakeupOnTransformChange
El criterio WakeupOnTransformChange es útil para detectar cambios en la posición o la orientación de objetos visuales en el escenario gráfico. Este criterio ofrece un alternativa a usar el método postId para crear comportamientos coordinados. Es especialmente útil cuando el comportamiento con el cual se desea coordinar ya está escrito, por ejemplo las utilidades de comportamientos presentadas anteriormente.
|
Sumario de Constructores de WakeupOnTransformChange Extiende: WakeupCriterion Esta clase especifica un disparo cuando cambia la transformación dentro de un TransformGroup especificado. WakeupOnTransformChange(TransformGroup node) Construye un nuevo criterio WakeupOnTransformChange. |
|
Sumario de Métodos de WakeupOnTransformChange TransformGroup getTransformGroup() Devuelve el nodo TransformGroup usado en la creacción de este WakeupCriterion |
WakeupOnViewPlatformEntry
La detección de la intersección del ViewPlatform con una región especificada se hace posible con las clases del criterio de WakeupOnViewPlatfomEntry y de WakeupOnViewPlatformExit.
Es posible que el límite especificado interseccione con un volumen de la activación de ViewPlatform tan brevemente que no sea detectada. En este caso ni se accionan las condiciones de WakeupOnViewPlatformEntry ni de WakeupOnViewPlatformExit.
|
Sumario de Constructores de WakeupOnViewPlatformEntry Extiende: WakeupCriterion Esta clase especifica un disparo en la primera intersección del ViewPlatform con los límites especificados. WakeupOnViewPlatformEntry(Bounds region) Construye un nuevo criterio WakeupOnEntry. |
|
Sumario de Métodos de WakeupOnViewPlatformEntry Bounds getBounds() Devuelve la especificación de límites de este objeto. |
WakeupOnViewPlatformExit
|
Sumario de Constructores de WakeupOnViewPlatformExit Extiende: WakeupCriterion Esta Class especifica un disparo en la primera detección de un Viewplatform que deja de interseccionar con el límite especificado. También puedes ver WakeupOnViewPlatformEntry. WakeupOnViewPlatformExit(Bounds region) Construye un nuevo criterio WakeupOnExit. |
|
Sumario de Métodos de WakeupOnViewPlatformExit Bounds getBounds() Devuelve la especificación de límites de este objeto |
WakeupCondition CompositionVarios objetos WakeupCriteron pueden componer un solo WakeupCondition usando las cuatro clases presentadas en esta sección. Las primeras dos clases permiten la composición de un WakeupCondition desde una colección de objetos WakeupCriterion que son lógicamente ANDed u ORed juntos, respectivamente. El tercero y siguientes permiten la composición de ejemplares de las dos primeras clases en objeto WakeupCondition más complejos.
WakeupAnd
|
Sumario de Constructores de WakeupAnd Extiende: WakeupCondition Esta clase especifica cualquier número de criterios de disparo que son (AND) juntos de forma lógica. WakeupAnd(WakeupCriterion[] conditions) Construye una nueva condición WakeupAnd. |
WakeupOr
|
Sumario de Consctructores de WakeupOr Extiende: WakeupCondition Esta clase especifica cualquiere número de criterios de disparo que son (OR) juntos de forma lógica. WakeupAnd(WakeupCriterion[] conditions) Construye una nueva condición WakeupOr. |
WakeupAndOfOrs
|
Sumario de Consctructores de WakeupAndOfOrs Extiende: WakeupCondition Esta clase especifica cualquier número de criterios de disparo WakeupOr que son (AND) juntos de forma lógica. WakeupAndOfOrs(WakeupOr[] conditions) Construye una nueva condición WakeupAndOfOrs. |
WakeupOrOfAnds
|
Sumario de Consctructores de WakeupOrOfAnds Extiende: WakeupCondition Esta clase especifica cualquier número de criterios de disparo WakeupAnd que son (OR) juntos de forma lógica. WakeupOrsOfAnds(WakeupAnd[] conditions) Construye una nueva condición WakeupOrOfAnds. |
Clases de Comportamientos Útiles para la Navegación por TecladoHasta este momento, el espectador ha estado en una localización fija con una orientación fija. El poder mover el espectador es una capacidad importante en muchas aplicaciones de los gráficos 3D. Java 3D es capaz de mover el espectador. De echo hay clases utilitarias de Java 3D que implementan esta funcionalidad.
La Figura 4-8 muestra la rama gráfica básica para un universo virtual de Java 3D. En esta figura, se considera la plataforma de la visión transform. Si se cambia la transformación, el efecto es mover, o reorientar, o ambas, al espectador. De esto, podemos ver que el diseño básico de la navegación del teclado es simple: hacemos que un objeto behavior cambie la transformación de la vista de la plataforma en respuesta a los movimientos dominantes.
Este diseño simple es exactamente el modo de trabajo de las clases utilitarias del teclado de Java 3D. Por supuesto podríamos construir nuestro propio comportamiento de navegación del teclado. El resto de esta sección explica cómo utilizar las clases de la navegación del teclado de Java 3D.

Cómo Navegar en un SimpleUniverse
Podría ser que pensaramos que necesitar el acceso a los grupos de objeto Transform de la plataforma significa abandonar la utilidad SimpleUniverse. Sin embargo, SimpleUniverse, y las clases relacionadas, proporcionan una combinación de métodos para extraer el objeto ViewPlatformTransform. Por lo tanto, podemos tener nuestro SimpleUniverse y navegar en él también!
Específicamente, la siguiente línea de código extrae el ViewPlatformTransform de un objeto de SimpleUniverse, su.
TransformGroup vpt = su.getViewingPlatform().getViewPlatformTransform();
Programa de Ejemplo de KeyNavigatorBehaviorEs fácil utilizar la clase de utilidad KeyNavigatorBehavior en un programa de Java 3D. Esta sección demuestra el uso de la clase en el programa del ejemplo de KeyNavigatorApp.java. En este programa podemos ver que los pasos necesarios para usar la clase KeyNavigatorBehavior son esencialmente idénticos a los de usar cualquier clase de comportamiento. Los pasos para usar KeyNavigatorBehavior se resumen en la siguiente lista.
Como cualquier problema de programación, hay una variedad de maneras de implementar los pasos de esta receta. Un acercamiento es incorporar estos pasos en el método de createSceneGraph. El Fragmento de Código 4-5 muestra los pasos de la receta según la implementación para el programa del ejemplo de KeyNavigatorApp.java.
1. public BranchGroup createSceneGraph(SimpleUniverse su) {
2. // Create the root of the branch graph
3. TransformGroup vpTrans = null;
4.
5. BranchGroup objRoot = new BranchGroup();
6.
7. objRoot.addChild(createLand());
8.
9. // create other scene graph content
10.
11.
12. vpTrans = su.getViewingPlatform().getViewPlatformTransform();
13. translate.set( 0.0f, 0.3f, 0.0f); // 3 meter elevation
14. T3D.setTranslation(translate); // set as translation
15. vpTrans.setTransform(T3D); // used for initial position
16. KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(vpTrans);
17. keyNavBeh.setSchedulingBounds(new BoundingSphere(
18. new Point3d(),1000.0));
19. objRoot.addChild(keyNavBeh);
20.
21. // Let Java 3D perform optimizations on this scene graph.
22. objRoot.compile();
23.
24. return objRoot;
25. } // end of CreateSceneGraph method of KeyNavigatorApp
La ejecución del paso 1 de la receta en el método de createSceneGraph requiere el acceso al grupo de transformación de ViewPlatform. Esta implementación pasa el objeto SimpleUniverse (línea 34 del Fragmento de Código 4-6) al método createSceneGraph que lo hace disponible para tener acceso a la transformación de ViewPlatform (la línea 12 del Fragmento de Código 4-5).
Pasar el objeto SimpleUniverse al método de createSceneGraph permite acceder a otras características de la rama gráfica de la vista de SimpleUniverse, tales como PlatformGeometry, ViewerAvatar, o de agregar un BoundingLeaf a la rama gráfica de la vista.
La líneas 13 a 15 del Fragmento de Código 4-5 proporcionan una posición inicial para el espectador. En este caso, el espectador se mueve a una posición 0,3 metros sobre el origen del mundo virtual. Esto es solamente una posición inicial, y de ninguna manera limita la posición futura o la orientación del espectador.
26. public KeyNavigatorApp() {
27. setLayout(new BorderLayout());
28. Canvas3D canvas3D = new Canvas3D(null);
29. add("Center", canvas3D);
30.
31. // SimpleUniverse is a Convenience Utility class
32. SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
33.
34. BranchGroup scene = createSceneGraph(simpleU);
35.
36. simpleU.addBranchGraph(scene);
37. } // end of KeyNavigatorApp (constructor)
Cómo Crear una Aplicación Universal de un Comportamiento
Como con cualquier objeto comportamiento, el objeto KeyNavigtorBehavior está solo activo cuando sus límites interseccionan con el volumen de activación de un ViewPlatform. Esto puede estar particularmente limitado para un comportamiento de navegación, donde el comportamiento debe siempre estar activado. El Capítulo 3 discute una solución a este problema usando un BoundingLeaf.
Clases KeyNavigatorBehavior y KeyNavigatorLa utilidad de navegación del teclado se implementa como dos clases. En el tiempo de ejecución hay dos objetos. El primer objeto es el objeto KeyNavigatorBehavior, el segundo es un objeto KeyNavigator. La segunda clase no se documenta aquí ya que ni el programador ni el cliente deben saber que existe la segunda clase u objeto.
El objeto KeyNavigatorBehavior realiza todas las funciones típicas de una clase de comportamiento, excepto que llama al objeto KeyNavigator para realizar la función de processStimulus. La clase KeyNavigator toma el AWTEvent y lo procesa bajo al nivel de pulsaciones de teclas individuales. La Tabla siguiente muestra el efecto de las pulsaciones de teclas individuales. KeyNavigator implementa el movimiento con aceleración.
Movimientos de KeyNavigatorBehavior
| Tecla | Movimiento | Movimiento Alt-tecla |
|---|---|---|
| <- | rotar a la izquierda | traslación lateral izquierda |
| -> | rotar a la derecha | traslación lateral derecha |
| ^ | mover hacia adelante |
|
| v | mover hacia atrás |
|
| PgUp | rotar arriba | translación hacia arriba |
| PgDn | rotar abajo | translación hacia abajo |
| + | aumenta la distancia de salto (y vuelve al origen) |
|
| - | reduce la distancia de salto |
|
| = | vuelve al centro del universo |
|
|
Sumario de Constructores de KeyNavigatorBehavior Paquete: com.sun.j3d.utils.behaviors.keyboard Extiende: Behavior Esta clase es un sencillo comportamiento que invoca el KeyNavigator para modificar la transformación de la vista de la plataforma. KeyNavigatorBehavior(TransformGroup targetTG) Construye un nuevo comportamiento de navegación por teclado que opera sobre el grupo de transformación especificado. |
|
Sumario de Métodos de KeyNavigatorBehavior void initialize() Sobreescribe el método initialize de Behavior para configurar los criterios de disparo. void processStimulus(java.util.Enumeration criteria) Sobreescribe el método stimulus de Behavior para manejar el evento. |
Clases de Utilidad para Interactuar con el RatónEl paquete de comportamientos de ratón (com.sun.j3d.utils.behaviors.mouse) contiene las clases del comportamiento en las cuales el ratón se utiliza como entrada de información para la interacción con los objetos visuales. Incluyendo las clases para traslaciones (moviéndose en un plano paralelo a la placa de la imagen), enfocando (que mueve hacia atrás y adelante), y los objetos visuales que rotan en respuesta a los movimientos del ratón.
La siguiente tabla resume las tres clases específicas del comportamiento del ratón incluidas en el paquete. Además de estas tres clases, está la clase abstracta MouseBehavior, y el interface MouseCallback. Esta clase abstracta y el interface se utilizan en la creación de las clases específicas del comportamiento del ratón y son útiles para crear comportamientos personalizados del ratón.
Sumario de las clases espécificas de MouseBehavior
| Clase MouseBehavior | Acción en Respuesta a la Acción del Ratón | Acción del ratón |
|---|---|---|
| MouseRotate | rota el objeto visual sin moverlo | botón izquierdo pulsado con movimiento del ratón |
| MouseTranslate | translada el objeto visual en un plano paralelo al plato de imagen | boton derecho pulsado con movimiento del ratón |
| MouseZoom | translada el objeto visual en un plano orthogonal al plato de imagen | botón central pulsado con movimiento del ratón |
Usar las Clases de Comportamiento del RatónLa clases de comportamientos específicos del ratón son fáciles de usar; es esencialmente lo mismo que el de otras clases de comportamientos. La siguiente lista representa la receta para usarlas:
Como con algunas otras recetas, los pasos no tienen que ser realizados en el orden dado. El paso dos se debe realizar antes del tres, del cuatro, y del cinco; los otros pasos se pueden realizar en cualquier orden. También, los pasos dos y tres se pueden combinar usando un constructor diferente.
El Fragmento de Código 4-7 presenta el método createSceneGraph del programa del ejemplo de MouseRotateApp.java. El escenario gráfico incluye el objeto ColorCube. El usuario puede rotar el ColorCube usando el ratón debido a la inclusión de un objeto MouseRotate en el escenario gráfico.
1. public class MouseRotateApp extends Applet {
2.
3. public BranchGroup createSceneGraph() {
4. // Create the root of the branch graph
5. BranchGroup objRoot = new BranchGroup();
6.
7. TransformGroup objRotate = new TransformGroup();
8. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
9. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
10.
11. objRoot.addChild(objRotate);
12. objRotate.addChild(new ColorCube(0.4));
13.
14. MouseRotate myMouseRotate = new MouseRotate();
15. myMouseRotate.setTransformGroup(objRotate);
16. myMouseRotate.setSchedulingBounds(new BoundingSphere());
17. objRoot.addChild(myMouseRotate);
18.
19. // Let Java 3D perform optimizations on this scene graph.
20. objRoot.compile();
21.
22. return objRoot;
23. } // end of CreateSceneGraph method of MouseRotateApp
La misma receta funcionará para las otras clases de comportamiento del ratón. De hecho los tres comportamientos se pueden utilizar en la misma aplicación que funciona en el mismo objeto visual. Puesto que cada uno de los comportamientos del ratón lee el transform fuente antes de escribirlo, sólo se necesita un objeto TransformGroup incluso con tres comportamientos de ratón. El programa del ejemplo de MouseRotateApp.java hace apenas eso.
El siguiente ejemplo muestra cómo dos comportamientos del ratón trabajan en un solo mundo virtual. El programa MouseRotate2App.java del ejemplo crea un escenario gráfico con dos objetos ColorCube uno junto al otro en el mundo virtual. Cada uno de los ColorCubes tiene un objeto MouseRotate asociado a él. Puesto que ambos objetos de comportamiento del ratón están activos, cuando el usuario hace clic y mueve el ratón, ambos ColorCubes rotan.
Si no quisieramos que ambos objetos rotaran, hay dos soluciones: 1) cambiar la posición del espectador, o cambiar los límites del comportamiento, de modo que solamente un comportamiento sesté activo, o 2) usar un mecanismo de selección para aislar el comportamiento.
Fundamentos del Comportamiento del RatónLas clases específicas de comportamiento del ratón (MouseRotate, MouseTranslate, y MouseZoom) son extensiones de la clase abstracta MouseBehavior e implementan el interface MouseCallback.
La Clase Abstracta MouseBehavior
Esta clase abstracta se presenta aquí en el evento que deseamos ampliarlo para escribir una clase personaliza de comportamiento del ratón. El método SetTransformGroup() es probablemente el único que utilizarán los usuarios de un ejemplar de MouseBehavior. Los otros métodos se crearón para los autores de las clases de comportamientos personalizados del ratón.
|
Sumario de Métodos de MouseBehavior La clase base para todos los manipuladores de ratón (puedes ver MouseRotate y MouseZoom para ejemplos). void initialize() Inicializa el comportamiento. void processMouseEvent(java.awt.event.MouseEvent evt) Maneja eventos del ratón. void processStimulus(java.util.Enumeration criteria) Todos los manipuladores de ratón deben implementar este método de Behavior (para responder a los estimulos). void setTransformGroup(TransformGroup transformGroup) Selecciona el TransformGroup para el comportamiento. void wakeup() Dispara manualmente el comportamiento. |
Interface MouseCallback
Una clase que implementa este interfaz proporciona al método transformChanged que será llamado cuando cambie el transform fuente de la manera especificada. Cada uno de los tres comportamientos específicos del ratón implementa esta clase. Un programador simplemente puede reemplazar el método transformChanged de una de esas clases para especificar un método que se llamará cuando se modifique el transform.
|
Sumario de Métodos del Interface MouseBehaviorCallback Paquete: com.sun.j3d.utils.behaviors.mouse void transformChanged(int type, Transform3D transform) Las clases que implementan este interface que se registran con un MouseBehaviors serán llamadas cada vez que el comportamient actualice el Transform. El tipo es uno de MouseCallback.ROTATE, MouseCallback.TRANSLATE, o MouseCallback.ZOOM. |
Clases Específicas de Comportamientos de RatónMouseRotate
Un escenario gráfico que incluye un objeto MouseRotate permite que el usuario rote objetos visuales en el mundo virtual. Los programas de ejemplo MouseRotateApp, MouseRotate2App, y MouseBehaviorApp demuestran el uso de esta clase.
|
Sumario de Constructores de MouseRotate Paquete: com.sun.j3d.utils.behaviors.mouse Extiende: MouseBehavior MouseRotate es un objeto de comportamiento de Java3D que deja a los usuarios controlar la rotación de un objeto mediante una pulsación del botón izquierdo del ratón. Para utilizar esta utilidad, primero creamos un TransformGroup sobre el que operará este comportamiento. El usuario puede rotar cualquier objeto hijo del TransformGroup fuente. MouseRotate() Crea un comportamiento mouseRotate por defecto. MouseRotate(TransformGroup transformGroup) Crea un comportamiendo dando el transformgroup. MouseRotate(int flags) Crea un comportamiento con las banderas seleccionadas, donde las banderas son:
|
|
Sumario de Métodos de MouseRotate void setFactor(double factor) Selecciona el factor multiplicador para los movimientos en los ejes x e y al valor factor void setFactor(double xFactor, double yFactor) Selecciona el factor multiplicador para los movimientos en los ejes x e y a los valores xFactor e yFactor respectivamente. void setupCallback(MouseBehaviorCallback callback) El método que se llama cada vez que se actualiza el transformgroup void transformChanged(Transform3D transform) Los usuarios pueden sobreescribir este método que es llamado cada vez que el comportamiento actualiza el transformgroup. La implementación por defecto no hace nada. |
MouseTranslate
Un escenario gráfico que incluye un objeto MouseTranslate permite que el usuario mueva objetos visuales en un plano paralelo a la placa de la imagen en el mundo virtual.
|
Sumario de Constructores de MouseTranslate Paquete: com.sun.j3d.utils.behaviors.mouse Extiende: MouseBehavior MouseTranslate es un objeto comportamiento de Java3D que permite a los usuarios controlar la traslación (X,Y) de un objeto mediante un movimiento de arrastre del ratón con el botón derecho. MouseTranslate() Crea un comportamiento de movimiento por defecto. MouseTranslate(TransformGroup transformGroup) Crea un comportamiento de movimiento dando un transformgroup. MouseTranslate(int flags) Crea un comportamiento de movimiento con banderas, donde las banderas son:
|
|
Sumario de Métodos de MouseTranslate void setFactor(double factor) Selecciona el factor multiplicador para los movimientos en los ejes x e y al valor factor void setFactor(double xFactor, double yFactor) Selecciona el factor multiplicador para los movimientos en los ejes x e y a los valores XFactor e yFactor respectivamente. void setupCallback(MouseBehaviorCallback callback) El método que se llama cada vez que se actualiza el transformgroup void transformChanged(Transform3D transform) Los usuarios pueden sobreescribir este método que es llamado cada vez que el comportamiento actualiza el transformgroup. La implementación por defecto no hace nada. |
MouseZoom
Un escenario gráfico que incluye un objeto MouseZoom permite a los usuarios mover objetos visuales en un plano orthogonal al plato de imagen en un mundo virtual.
|
Sumario de Constructores de MouseZoom Paquete: com.sun.j3d.utils.behaviors.mouse Extiende: MouseBehavior MouseZoom es un objeto de comportamiento Java3D que permite a los usuarios controlar la traslación en el eje Z de un objeto mediante un movimiento de arrastre del ratón con el botón central (alt-tecla en el PC con el ratón de dos botones). MouseZoom() Crea un comportamiento de zoom con ratón por defecto. MouseZoom(TransformGroup transformGroup) Crea un comportamiento de zoom dando el transformgroup. MouseZoom(int flags) Crea un comportamiento de zoom con banderas, donde las banderas son:
|
|
Sumario de Métodos de MouseZoom void setFactor(double factor) Selecciona el factor multiplicador del movimiento sobre el eje Z al valor factor. void setupCallback(MouseBehaviorCallback callback) El método que se llama cada vez que se actualiza el transformgroup void transformChanged(Transform3D transform) Los usuarios pueden sobreescribir este método que es llamado cada vez que el comportamiento actualiza el transformgroup. La implementación por defecto no hace nada. |
MouseNavigationLas tres clases específicas de comportamiento del ratón se pueden utilizar para crear un universo virtual en el cual el ratón se utilice para la navegación. Cada una de las clases específicas del comportamiento del ratón tiene un constructor que toma un solo parámetro entero para las banderas. Cuando se utiliza MouseBehavior.INVERT_INPUTS como argumento a este constructor, el comportamiento del ratón responde en la dirección opuesta. Este comportamiento inverso es apropiado para cambiar el transform ViewPlatform. Es decir las clases del comportamiento del ratón se pueden utilizar para el control navegacional.
El programa de ejemplo MouseNavigatorApp.java utiliza casos de las tres clases específicas del comportamiento del ratón para la interacción navegacional. El Fragmento de Código 4-8 muestra el método createSceneGraph de este programa del ejemplo.
El TransformGroup fuente para cada uno de los objetos del comportamiento del ratón es el ViewPlatform transform. El objeto SimpleUniverse es un argumento al método createSceneGraph de modo que se puedan alcanzar los objetos transform de ViewPlatform.
1. public BranchGroup createSceneGraph(SimpleUniverse su) {
2. // Create the root of the branch graph
3. BranchGroup objRoot = new BranchGroup();
4. TransformGroup vpTrans = null;
5. BoundingSphere mouseBounds = null;
6.
7. vpTrans = su.getViewingPlatform().getViewPlatformTransform();
8.
9. objRoot.addChild(new ColorCube(0.4));
10. objRoot.addChild(new Axis());
11.
12. mouseBounds = new BoundingSphere(new Point3d(), 1000.0);
13.
14. MouseRotate myMouseRotate = new
MouseRotate(MouseBehavior.INVERT_INPUT);
15. myMouseRotate.setTransformGroup(vpTrans);
16. myMouseRotate.setSchedulingBounds(mouseBounds);
17. objRoot.addChild(myMouseRotate);
18.
19. MouseTranslate myMouseTranslate = new
MouseTranslate(MouseBehavior.INVERT_INPUT);
20. myMouseTranslate.setTransformGroup(vpTrans);
21. myMouseTranslate.setSchedulingBounds(mouseBounds);
22. objRoot.addChild(myMouseTranslate);
23.
24. MouseZoom myMouseZoom = new
MouseZoom(MouseBehavior.INVERT_INPUT);
25. myMouseZoom.setTransformGroup(vpTrans);
26. myMouseZoom.setSchedulingBounds(mouseBounds);
27. objRoot.addChild(myMouseZoom);
28.
29. // Let Java 3D perform optimizations on this scene graph.
30. objRoot.compile();
31.
32. return objRoot;
33. } // end of createSceneGraph method of MouseNavigatorApp
Los objetos bounds para los objetos de comportamientos de ratón se especifican como un BoundingSphere con un radio de 1000 metros. Si el usuario se sale de esta esfera, los objetos comportamiento se desactivarán.
PickingEn el programa de ejemplo MouseNavigatorApp.java, ambos objetos ColorCube giran en respuesta a acciones del usuario. En esta aplicación, no hay forma de manipular los cubos de forma separada. "Picking" (Elección) le da al usuario una forma de interactuar con objetos visuales individuales en la escena.
Picking (elección) está implementado por un comportamiento tipicamente disparado por eventos de botones del ratón. En la selección de un objeto visual, el usuario sitúa el puntero del ratón sobre el objeto elegido y pulsa el botón del ratón. El objeto behavior se dispara por la pulsación de este botón y empieza la operación de selección. Se proyecta un rayo dentro del mundo virtual desde la posición del puntero del ratón paralela con la proyección. Se calcula la intersección de este rayo con los objetos del mundo virtual. El objeto visual que interseccione más cerca al plato de la imagen se selecciona para interacción. La Figura 4-11 muestra un rayo de selección proyectado en un mundo virtual.

En algunos casos la interacción no se hace directamente con el objeto seleccionado, sino con un objeto en el camino del escenario gráfico hasta el objeto. Por ejemplo, al seleccionar un objeto ColorCube para rotación, este objeto no se manipula, se manipula el objeto TransformGroup que hay sobre el ColorCube en el path del escenario gráfico. Por otro lado, su la operación de selección selecciona un objeto visual para el que se pensó un cambio de color, entonces el objeto visual seleccionado es requerido.
La determinación del objeto para un posterior procesamiento no siempre es sencilla. Si in objeto visual cúbico que va a ser rotado está compuesto por seis objetos Shape3D individuales junto con seis objetos TransformGroup, como en el escenario gráfico de la Figura 4-12, no es el objeto TransformGroup sobre el objeto Shape3D interseccionado el que necesita ser modificado. El 'cubo' se rota por la manipulación del objeto TransformGroup que es hijo del objeto BranchGroup en el escenario gráfico. Por esta razón, el resultado de algunas operaciones de selección es devolver el path del escenario gráfico para su posterior procesamiento.

La comprobación de intersecciones es necesita mucho cálculo. Por lo tanto, la selección es cara y se vuelve más cara con la complejidad del escena. El API Java 3D proporciona varias formas para que un programador pueda limitar la cantidad de cálculos realizados por la selección. Una forma importante es através de las capacidades y atributos de los nodos del escenario gráfico. Si un nodo es o no elegible se selecciona con el método setPickable() de la clase. Un nodo con setPickable() seleccionado a false no es elegible ni ninguno de sus hijos tampoco. Consecuentemente, estos nodos no se tienen en cuenta cuando se calculan las intersecciones.
Otra característica relacionada con la selección en la clase Node es la capacidad ENABLE_PICK_REPORTING. Esta capacidad sólo se aplica a nodos Group. Cuando se selecciona para un grupo, este objeto group siempre será incluido en el escenario gráfico devuelto por una operación de selección. Los nodos Group no se necesitan para unidades en un escenario gráfico que serán excluidas cuando la capacidad no está seleccionada. No tener seleccionado correctamente los nodos del escenario gráfico es un fuente común de frustacciones en el desarrollo de aplicaciones que utilizan operaciones de selección.
|
Lista Parcial de Métodos de Node Extiende: SceneGraphObject Subclases: Group, Leaf La clase Node proporciona una clase abstracta para todos los nodos Group y Leaf. Porporciona un marco de trabajo común para construir un escenario gráfico Java 3D, especificamente volúmenes, y las capacidades de selección y colisión. void setBounds(Bounds bounds) Selecciona los límites geométricos de un nodo. void setBoundsAutoCompute(boolean autoCompute) Activa/desactiva el cálculo automático de los límites geométricos de un nodo. setPickable(boolean pickable) Cuando se selecciona a true este nodo puede ser elegido. Cuando se selecciona a false indica que este nodo y sus hijos no son elegibles. |
|
Lista Parcial de Capacidades de Node ENABLE_PICK_REPORTING Especifica que este nodo será reportado en el SceneGraphPath si ocurre una selección. Esta capacidad es sólo aplicable para nodos Group; es ignorado para nodos leaf. El valor por defecto para nodos Group es false. Los nodos interiores no necesitan ser únicos en un SceneGraphPath que no tiene seleccionado ENABLE_PICK_REPORTING serán excluidos del SceneGraphPath. ALLOW_BOUNDS_READ | WRITE
ALLOW_PICKABLE_READ | WRITE
|
Otra forma en la que un programador puede reducir el cáculo de selección es usar pruebas de interesección de límites en vez de pruebas de intersecciones geométricas. Varias clases relacionadas con la selección (pick) tiene constructores y/o métodos con un parámetro que se selecciona a uno de: USE_BOUNDS o USE_GEOMETRY. Cuando se selecciona USE_BOUNDS, la selección está determinada usando los límites de los objetos visuales, no la geometría real. La determinación de una selección usando los límites es significativamente más sencilla (computacionalmente) para todo excepto para las formas geométricas sencillas y por lo tanto, resulta en un mejor rendimiento. Por supuesto, la pérdida es que la selección no es tan precisa cuando se utilizan límites para su determinación.
Una tercera técnica de programación para reducir el coste de cálculo para la selección es limitar el ámbito de la prueba de selección a la porcion relevante del escenario gráfico. En cada clase de utilidad de selección se selecciona un nodo como el raíz para el gráfico a testear. Este nodo no es necesariamente el raíz de la rama de contenido gráfico. Por el contrario, el nodo pasado debería ser el raíz de la subrama de contenido que sólo contiene objetos elegibles, si es posible. Esta consideración pordría ser una mayor factor de determinación en la construcción de un escenario gráfico para algunas aplicaciones.
Usar las Clases de Utilidad de PickingHay dos aproximaciones básicas para usar las características de selección de Java 3D, usar objetos de clases picking, o crear clases picking personalizadas y usar ejemplares de estas clases. El paquete picking incluye clases para pick/rotate, pick/translate, y pick/zoom. Es decir, un usuario puede elegir y rotar un objeto presionando el botón del ratón cuando el puntero está sobre el objeto deseado y entonces arrastra el ratón (mientras mantiene pulsado el botón). Cada una de estas clases de picking usa un botón diferente del ratón haciendo posible el uso de objeto para las tres clases de picking en la misma aplicación simultáneamente.
Cómo un objeto comportamiento picking operará sobre cualquier objeto del escenario gráfico (con las capacidades apropiadas), sólo se necesita proporcionar un objeto picking. Las dos siguientes líneas de código son todo lo que necesitamos incluir en un programa Java 3D para usar las clases de selección:
PickRotateBehavior behavior = new PickRotateBehavior(root, canvas, bounds); root.addChild(behavior);
El objeto behavior monitorizará cualquier evento de selección en el escenario gráfico (bajo el nodo raíz) y meneja los arrastres y pulsaciones del ratón. El root proporciona la porción del escenario gráfico a chequear para la selección, el canvas se situa donde está el ratón, y bounds son los límites del objeto de comportamiento picking.
Receta para usar las clases de utilidades de picking.
Riesgos de Programación cuando se usan Objetos Picking
Los Riesgos más comunes incluyen; olvidarse de incluir el objeto behavior en el escenario gráfico, y no seleccionar los límites apropiados del objeto.
Otro problema común es no seleccionar las capacidades apropiadas para los objetos del escenario gráfico. Hay otros dos problemas menores, que deberíamos chequear si nuestra aplicación no funciona. Uno es no seleccionar apropiadamente el raíz del escenario gráfico. Otro problema potencial es no seleccionar apropiadamente el canvas. Ninguno de estos errores de programación generarán un aviso o mensaje de error.
Programa de Ejemplo MousePickApp
El Fragmento de Código 4-9 muestra el método createSceneGraph de la aplicación MousePickApp.java. Este programa usa un objeto PickRotate para proporcionar interacción.
Observa que como la construcción del objeto picking requiere un objeto Canvas3D, el método createSceneGraph difiere de versiones anteriores por la inclusión del parámetro canvas. Por supuesto, también cambia la correspondiente invocación a createSceneGraph.
1. public BranchGroup createSceneGraph(Canvas3D canvas) {
2. // Create the root of the branch graph
3. BranchGroup objRoot = new BranchGroup();
4.
5. TransformGroup objRotate = null;
6. PickRotateBehavior pickRotate = null;
7. Transform3D transform = new Transform3D();
8. BoundingSphere behaveBounds = new BoundingSphere();
9.
10. // create ColorCube and PickRotateBehavior objects
11. transform.setTranslation(new Vector3f(-0.6f, 0.0f, -0.6f));
12. objRotate = new TransformGroup(transform);
13. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
14. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
15. objRotate.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
16.
17. objRoot.addChild(objRotate);
18. objRotate.addChild(new ColorCube(0.4));
19.
20. pickRotate = new PickRotateBehavior(objRoot,canvas, behaveBounds);
21. objRoot.addChild(pickRotate);
22.
23. // add a second ColorCube object to the scene graph
24. transform.setTranslation(new Vector3f( 0.6f, 0.0f, -0.6f));
25. objRotate = new TransformGroup(transform);
26. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
27. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
28. objRotate.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
29.
30. objRoot.addChild(objRotate);
31. objRotate.addChild(new ColorCube(0.4));
32.
33. // Let Java 3D perform optimizations on this scene graph.
34. objRoot.compile();
35.
36. return objRoot;
37. } // end of createSceneGraph method of MousePickApp
Este código es similar al de MouseRotate2App.java, pero es distinto en muchas cosas. Primero, en este programa sólo se usa un objeto behavior, mientras que MouseRotate2App usaba dos objetos behavior - uno por cada objeto visual. Aunque el código es similar, el comportamiento es diferente. Este programa permite al usuario seleccionar un objeto e interactuar con él. MouseRotate2App rotaba los dos objetos o ninguno.
El API Corazón de Clases Picking de Java 3DHay tres niveles de clases picking en Java 3D. El API corazón de Java 3D proporciona la menor funcionalidad. El paquete de utilidad picking proporciona clases de comportamientos generales, elegibles para personalización. El paquete picking también proporciona clases picking específicas que pueden usarse directamente en programas Java 3D.
Las clases corazón incluyen PickShape y SceneGraphPath, y métodos de BranchGroup y Locale. Estas clases proporcionan el mecanismo para especificar una forma usada en la comprobación de intersecciones con objetos visuales. Esta sección presenta el API de las clases PickShape y SceneGraphPath, y las clases y métodos relacionados.
Clases PickShape
Esta clase abstracta no proprociona ni constructores ni métodos. Proporciona abstracción para cuatro subclases: PickBounds, PickRay, PickSegment, y PickPoint.
|
PickShape Subclases Conocidas: PickBounds, PickRay, PickSegment, PickPoint Una clase general para describir un forma de selección que puede usarse con métodos de selección de BranchGroup y Locale. |
PickBounds
Los objetos PickBounds representan un límite para testear elecciones. Como una subclase de PickShape, los objetos PickBounds se usan con BranchGroup y Locale así como con clases del paquete picking.
|
Sumario de Constructores de PickBounds Extiende: PickShape Un límite para suministrar a los métodos de selección de BranchGroup y Locale. PickBounds() Crea un PickBounds. PickBounds(Bounds boundsObject) Crea un PickBounds con los límites especificados. |
|
Sumario de Métodos de PickBounds Bounds get() Obtiene el boundsObject desde este PickBounds. void set(Bounds boundsObject) Selecciona el boundsObject dentro de este PickBounds. |
PickPoint
Los objetos PickPoint representan un punto para selección. Como una subclase de PickShape, los objetos PickBounds se usan con BranchGroup y Locale así como con clases del paquete picking.
|
Sumario de Constructores de PickPoint Extiende: PickShape Suministra un punto a los métodos de selección de BranchGroup y Locale PickPoint() Crea un PickPoint en (0, 0, 0). PickPoint(Point3d location) Crea un PickPoint en location. |
|
Sumario de Métodos de PickPoint void set(Point3d location) Selecciona la posición de este PickPoint. Existe un método get correspondiente. |
PickRay
Los objetos PickRay representan un rayo (un punto y una dirección) para selección. Como una subclase de PickShape, los objetos PickBounds se usan con BranchGroup y Locale así como con clases del paquete picking.
|
Sumario de Constructores de PickRay Extiende: PickShape PickRay es una encapsulación de un rayo para pasarlo a los métodos de selección en BranchGroup y Locale PickRay() Crea un PickRay con origen y dirección de (0, 0, 0). PickRay(Point3d origin, Vector3d direction) Crea un rayo desde origin con dirección a direction. |
|
Sumario de Métodos de PickRay void set(Point3d origin, Vector3d direction) Selecciona el rayo que apunte desde origin en dirección direction. Existe el correspondiente método get. |
PickSegment
Los objetos PickSegment representan un segmento de línea (definida por dos puntos) para selección. Como una subclase de PickShape, los objetos PickBounds se usan con BranchGroup y Locale así como con clases del paquete picking.
|
Sumario de Constructores de PickSegment Extiende: PickShape PickRay es una encapsulación de un segmento pasado a los métodos de selección de BranchGroup y Locale PickSegment() Crea un PickSegment. PickSegment(Point3d start, Point3d end) Crea un PickSegment desde el punto start hata el punto end. |
|
Sumario de métodos de PickSegment void set(Point3d start, Point3d end) Selecciona el segmento desde el punto start hasta el punto end. Existe el correspondiente método get. |
SceneGraphPath
La clase SceneGraphPath se usa en la mayoría de las aplicaciones de selección. Esto es porque normalmente la selección implica encontrar un camino de escenario gráfico en el que se encuentra un objeto para permite la manipulación del objeto o de un objeto TransformGroup en el path.
Un objeto SceneGraphPath representa el camino del escenario gráfico hacia el objeto elegido permitiendo la manipulación del objeto o de un objeto TransformGroup en el camino del objeto.
|
Introducción a SceneGraphPath Un objeto SceneGraphPath representa el camino desde un Locale hasta un nodo temrinal en el escenario gráfico. Este camino consiste en un Locale, un nodo terminal, y un array de nodos internos que están en el path desde el Locale hasta el nodo terminal. El nodo terminal podría ser un nodo Leaf o un nodo Group. Un SceneGraphPath válido debe identificar únicamente un ejemplar de un nodo terminal. Para nodos que no están bajo un SharedGroup, el SceneGraphPath mínimo consiste en el Locale y el propio nodo terminal. Para nodos que están bajo un SharedGroup, el SceneGraphPath mínimo consiste en el Locale, el nodo terminal, y una lista de todos los nodos Link en el camino desde el Locale hacia el nodo terminal. Un SceneGraphPath opcionalmente podría contener otros nodos interiores que están en el camino. Un SceneGraphPath se verifica contra errores cuando se envía como argumento a otros métodos de Java 3D. En el array de nodos internos, el nodo en el índice 0 es el nodo más cercano al Locale. El índice se incrementa a lo largo del camino hacia el nodo terminal, con el nodo de índice longitud-1 siendo el nodo más cercano la nodo terminal. El array de nodos no contiene ni el Locale (que no es un nodo) ni el nodo terminal. |
|
Sumario de Constructores de SceneGraphPath Cuando un SceneGraphPath es devuelto desde métodos de selección o colisión de Java 3D, también contiene el valor del objeto transform LocalToVworld del nodo terminal que era en efecto en el momento en que ocurrió la colisión o la selección. Obherva que ENABLE_PICK_REPORTING y ENABLE_COLLISION_REPORTING están desactivados por defecto. Esto significa que los métodos de selección y colisión devolverán el SceneGraphPath mínimo por defecto. SceneGraphPath() Construye un objeto SceneGraphPath con parámetros por defecto. SceneGraphPath(Locale root, Node object) Construye un nuevo objeto SceneGraphPath. SceneGraphPath(Locale root, Node[] nodes, Node object) Construye un nuevo objeto SceneGraphPath. |
|
Lista Parcial de Métodos de SceneGraphPath boolean equals(java.lang.Object o1) Devuelve true si el objeto o1 es del tipo SceneGraphPath y todos los datos miembros de o1 son iguales a los miembros de datos correspondientes en este SceneGraphPath y si los valores de transformación son iguales. Transform3D getTransform() Devuelve una copia del transform asociado con este SceneGraphPath; devuelve null si no hay transform. int hashCode() Devuelve un número 'hash' basado en los valores de los datos de este objeto. boolean isSamePath(SceneGraphPath testPath) Determina si dos objetos SceneGraphPath representan el mismo path del escenario grafico; algún objeto podría incluir un subconjunto diferente de nodos internos; sólo los nodos links internos, Locale, y el propio nodo son comparados. int nodeCount() Recupera el número de nodos de este path. void set(SceneGraphPath newPath) Selecciona los valores del path al path especificado. void setLocale(Locale newLocale) Selecciona el Locale de este path a los Locale especificado. void setNode(int index, Node newNode) Reemplaza el nodo en el índice especificado con newNode. void setNodes(Node[] nodes) Selecciona el objeto nodo de este path con los objetos nodos especificados. void setObject(Node object) Selecciona el nodo terminal de este path al objeto nodo especificado. void setTransform(Transform3D trans) Selecciona el componente transform de este SceneGraphPath al valor del transform pasado. java.lang.String toString() Devuelve una representación string de este objeto; el string contiene los nombres de las clases de todos los nodos en el SceneGraphPath, el método toString() de cualquier usuario asociado, también imprime el transform si no es nulo. |
Métodos de Selección de BranchGroup y Local
En los siguientes bloques de referencia están los métodos de las clases BranchGroup y Local para chequeo de intersección con objetos PickShape. Este es el nivel de cálculo de selección más bajo proporcionado por el API Java 3D.
|
Métodos de selección de BranchGroup y Locale para su uso con PickShape SceneGraphPath[] pickAll(PickShape pickShape) Devuelve un array que referencia todos los ítems que son elegibles bajo este BranchGroup que intereseccionan con PickShape. El array resultante no está ordenado. SceneGraphPath[] pickAllSorted(PickShape pickShape) Devuelve un array ordenado de referencias a todos los ítems elegibles que interseccionan con el pickShape. Element [0] referencia el ítem más cercano al origen de PickShape, con los elementos siguientes alejándose del origen. Nota: si pickShape es del tipo PickBounds, el array resultante no está ordenado. SceneGraphPath pickClosest(PickShape pickShape) Devuelve un SceneGraphPath que referencia el ítem elegible que está más cercano al origen de pickShape. Nota: si pickShape es del tipo PickBounds, la respuesta es cualquier nodo elegible debajo de este BranchGroup. SceneGraphPath pickAny(PickShape pickShape) Devuelve una referencia a cualquir ítem elegible debajo de este BranchGroup que intersecciona con pickShape. |
Clases Generales del Paquete PickingIncluidas en el paquete com.sun.j3d.utils.behaviors.picking hay varias clases de comportamientos generales y específicos. Las clases generales son útiles para crear nuevos comportamientos de selección, entre las que se incluyen PickMouseBehavior, PickObject, y PickCallback. Las clases específicas de comportamiento del ratón, presentadas en la siguiente sección, son subclases de PickMouseBehavior.
Clase PickMouseBehavior
Esta es la clase base para los comportamientos de selección específicos proporcionados en el paquete. También es útil para extender clases de comportamientos de selección personalizados.
|
Sumario de Métodos de PickMouseBehavior Paquete: com.sun.j3d.utils.behaviors.picking Extiende: Behavior Clase base que permite a los programadores añadir selección y manipulación del ratón en un escenario gráfico (puedes ver PickDragBehavior para un ejemplo de cómo extender esta clase base). void initialize() Este método debería ser sobreescrito para proporcionar estado inicial y la condición de disparo inicial. void processStimulus(java.util.Enumeration criteria) Este método debería sobreescribirse para proporcionar el comportamiento en respuesta a una condición de disparo. void updateScene(int xpos, int ypos) Las subclases deberían implementar esta función update. |
Clase PickObject
La clase PickObject proporciona métodos para determinar qué objeto fué seleccionado por una operación de selección del usuario. Una amplia variedad de métodos resulta de las distitnas formas posibles de aplicaciones de selección. Es útil crear clases de selección personalizadas.
|
Sumario de Constructores de PickObject Paquete: com.sun.j3d.utils.behaviors.picking Extiende: java.lang.Object Contiene métodos para ayudar en la selección. Un PickObject se crea dando un Canvas3D y un BranchGroup. SceneGraphObjects bajo el BranchGroup especificado pueden chequearse para determinar si han sido seleccionados. PickObject(Canvas3D c, BranchGroup root) Crea un PickObject. |
|
Lista Parcial de Métodos de PickObject PickObject tiene numerosos métodos para el cálculo de intersecciones de un pickRay con objeto del escenario gráfico. Algunos de los métodos sólo difieren en un parámetro. Por ejemplo el segundo método pickAll (no listado) existe con el firma de método: SceneGraphPath[] pickAll(int xpos, int ypos, int flag), donde flag es uno de: PickObject.USE_BOUNDS, o PickObject.USE_GEOMETRY. Esta lista ha sido ordenada para excluir los métodos con parámetros de bandera. Estos métodos son idénticos a los incluidos en esta lista con la diferencia del parámetro bandera. Estos métodos son: pickAll, pickSorted, pickAny, y pickClosest. PickShape generatePickRay(int xpos, int ypos) Crea un PickRay que empieza en la posición del espectador y apunta dentro de la escena en dirección a (xpos, ypos) especificados en el espacio de la ventana. SceneGraphPath[] pickAll(int xpos, int ypos) Devuelve un array que referencia todos los ítems que son elegibles debajo del BranchGroup (especificado en el constructor de PickObject) que interseccionan con un rayo que empieza en la posición del espectador y apunta dentro de la escena en dirección (xpos, ypos) especificados en el espacio de la ventana. SceneGraphPath[] pickAllSorted(int xpos, int ypos) Devuelve un array ordenado de referencias a todos los ítems Pickable bajo el BranchGroup (especificado en el constructor de PickObject) que interesecciona con el rayo que empieza en la posición del espectador y apunta a la dirección de (xpos, ypos) en el espacio de la ventana. SceneGraphPath pickAny(int xpos, int ypos) Devuelve una referencia a cualquier ítem que sea elegible debajo del BranchGroup (especificado en el constructor de PickObject) que interesecciona con el rayo que empieza en la posición del espectador y apunta a la dirección (xpos, ypos) en el espacio de la ventana. SceneGraphPath pickClosest(int xpos, int ypos) Devuelve una referencia al ítem que está más cercano al espectador y es elegible bajo el BranchGroup (especificado en el constructor de PickObject) que interesecciona con el rayo que empieza en la posición del espectador y apunta a la dirección (xpos, ypos) en el espacio de la ventana. Node pickNode(SceneGraphPath sgPath, int node_types) Devuelve una referencia a un nodo elegible que es del tipo especificado que está contenido en el SceneGraphPath especificado. Donde node_types es la OR lógica de uno o más: PickObject.BRANCH_GROUP, PickObject.GROUP, PickObject.LINK, PickObject.MORPH, PickObject.PRIMITIVE, PickObject.SHAPE3D, PickObject.SWITCH, PickObject.TRANSFORM_GROUP. Node pickNode(SceneGraphPath sgPath, int node_types, int occurrence) Devuelve una referencia a un nodo elegible que es del tipo especificado que está contenido en el SceneGraphPath especificado. Donde node_types está definido en el método anterior. El parámetro occurrence indica qué objeto devolver. |
Interface PickingCallback
El interface PickingCallback proporciona un marco de trabajo para extender una clase de selección existente. En particular cada una de las clases específicas implementa este interface permitiendo al programador proporcionar un método que sea llamado cuando la operación de selección tenga lugar.
|
Sumario de Métodos del Interface PickingCallback Paquete: com.sun.j3d.utils.behaviors.pickingvoid transformChanged(int type, TransformGroup tg) Llamado por el Behavior Pick qu |