📄 examineviewerbehavior.java
字号:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* ExamineViewerBehavior
*
* @version 1.0, 98/04/16
**/
/**
* Wakeup on mouse button presses, releases, and mouse movements and
* generate transforms in an "examination style" that enables the user
* to rotate, translation, and zoom an object as if it is held at
* arm's length. Such an examination style is similar to the "Examine"
* navigation type used by VRML browsers.
*
* The behavior maps mouse drags to different transforms depending
* upon the mosue button held down:
*
* Button 1 (left)
* Horizontal movement --> Y-axis rotation
* Vertical movement --> X-axis rotation
*
* Button 2 (middle)
* Horizontal movement --> nothing
* Vertical movement --> Z-axis translation
*
* Button 3 (right)
* Horizontal movement --> X-axis translation
* Vertical movement --> Y-axis translation
*
* To support systems with 2 or 1 mouse buttons, the following
* alternate mappings are supported while dragging with any mouse
* button held down and zero or more keyboard modifiers held down:
*
* No modifiers = Button 1
* ALT = Button 2
* Meta = Button 3
* Control = Button 3
*
* The behavior automatically modifies a TransformGroup provided
* to the constructor. The TransformGroup's transform can be set
* at any time by the application or other behaviors to cause the
* examine rotation and translation to be reset.
*/
// This class is inspired by the MouseBehavior, MouseRotate,
// MouseTranslate, and MouseZoom utility behaviors provided with
// Java 3D. This class differs from those utilities in that it:
//
// (a) encapsulates all three behaviors into one in order to
// enforce a specific "Examine" symantic
//
// (b) supports set/get of the rotation and translation factors
// that control the speed of movement.
//
// (c) supports the "Control" modifier as an alternative to the
// "Meta" modifier not present on PC, Mac, and most non-Sun
// keyboards. This makes button3 behavior usable on PCs,
// Macs, and other systems with fewer than 3 mouse buttons.
public class ExamineViewerBehavior
extends ViewerBehavior
{
// Previous cursor location
protected int previousX = 0;
protected int previousY = 0;
// Saved standard cursor
protected Cursor savedCursor = null;
/**
* Construct an examine behavior that listens to mouse movement
* and button presses to generate rotation and translation
* transforms written into a transform group given later
* with the setTransformGroup( ) method.
*/
public ExamineViewerBehavior( )
{
super( );
}
/**
* Construct an examine behavior that listens to mouse movement
* and button presses to generate rotation and translation
* transforms written into a transform group given later
* with the setTransformGroup( ) method.
*
* @param parent The AWT Component that contains the area
* generating mouse events.
*/
public ExamineViewerBehavior( Component parent )
{
super( parent );
}
/**
* Construct an examine behavior that listens to mouse movement
* and button presses to generate rotation and translation
* transforms written into the given transform group.
*
* @param transformGroup The transform group to be modified
* by the behavior.
*/
public ExamineViewerBehavior( TransformGroup transformGroup )
{
super( );
subjectTransformGroup = transformGroup;
}
/**
* Construct an examine behavior that listens to mouse movement
* and button presses to generate rotation and translation
* transforms written into the given transform group.
*
* @param transformGroup The transform group to be modified
* by the behavior.
* @param parent The AWT Component that contains the area
* generating mouse events.
*/
public ExamineViewerBehavior( TransformGroup transformGroup,
Component parent )
{
super( parent );
subjectTransformGroup = transformGroup;
}
/**
* Respond to a button1 event (press, release, or drag).
*
* @param mouseEvent A MouseEvent to respond to.
*/
public void onButton1( MouseEvent mev )
{
if ( subjectTransformGroup == null )
return;
int x = mev.getX( );
int y = mev.getY( );
if ( mev.getID( ) == MouseEvent.MOUSE_PRESSED )
{
// Mouse button pressed: record position
previousX = x;
previousY = y;
// Change to a "move" cursor
if ( parentComponent != null )
{
savedCursor = parentComponent.getCursor( );
parentComponent.setCursor(
Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) );
}
return;
}
if ( mev.getID( ) == MouseEvent.MOUSE_RELEASED )
{
// Mouse button released: do nothing
// Switch the cursor back
if ( parentComponent != null )
parentComponent.setCursor( savedCursor );
return;
}
//
// Mouse moved while button down: create a rotation
//
// Compute the delta in X and Y from the previous
// position. Use the delta to compute rotation
// angles with the mapping:
//
// positive X mouse delta --> positive Y-axis rotation
// positive Y mouse delta --> positive X-axis rotation
//
// where positive X mouse movement is to the right, and
// positive Y mouse movement is **down** the screen.
//
int deltaX = x - previousX;
int deltaY = y - previousY;
if ( deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA ||
deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA )
{
// Deltas are too huge to be believable. Probably a glitch.
// Don't record the new XY location, or do anything.
return;
}
double xRotationAngle = deltaY * XRotationFactor;
double yRotationAngle = deltaX * YRotationFactor;
//
// Build transforms
//
transform1.rotX( xRotationAngle );
transform2.rotY( yRotationAngle );
// Get and save the current transform matrix
subjectTransformGroup.getTransform( currentTransform );
currentTransform.get( matrix );
translate.set( matrix.m03, matrix.m13, matrix.m23 );
// Translate to the origin, rotate, then translate back
currentTransform.setTranslation( origin );
currentTransform.mul( transform1, currentTransform );
currentTransform.mul( transform2, currentTransform );
currentTransform.setTranslation( translate );
// Update the transform group
subjectTransformGroup.setTransform( currentTransform );
previousX = x;
previousY = y;
}
/**
* Respond to a button2 event (press, release, or drag).
*
* @param mouseEvent A MouseEvent to respond to.
*/
public void onButton2( MouseEvent mev )
{
if ( subjectTransformGroup == null )
return;
int x = mev.getX( );
int y = mev.getY( );
if ( mev.getID( ) == MouseEvent.MOUSE_PRESSED )
{
// Mouse button pressed: record position
previousX = x;
previousY = y;
// Change to a "move" cursor
if ( parentComponent != null )
{
savedCursor = parentComponent.getCursor( );
parentComponent.setCursor(
Cursor.getPredefinedCursor( Cursor.MOVE_CURSOR ) );
}
return;
}
if ( mev.getID( ) == MouseEvent.MOUSE_RELEASED )
{
// Mouse button released: do nothing
// Switch the cursor back
if ( parentComponent != null )
parentComponent.setCursor( savedCursor );
return;
}
//
// Mouse moved while button down: create a translation
//
// Compute the delta in Y from the previous
// position. Use the delta to compute translation
// distances with the mapping:
//
// positive Y mouse delta --> positive Y-axis translation
//
// where positive X mouse movement is to the right, and
// positive Y mouse movement is **down** the screen.
//
int deltaY = y - previousY;
if ( deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA )
{
// Deltas are too huge to be believable. Probably a glitch.
// Don't record the new XY location, or do anything.
return;
}
double zTranslationDistance = deltaY * ZTranslationFactor;
//
// Build transforms
//
translate.set( 0.0, 0.0, zTranslationDistance );
transform1.set( translate );
// Get and save the current transform
subjectTransformGroup.getTransform( currentTransform );
// Translate as needed
currentTransform.mul( transform1, currentTransform );
// Update the transform group
subjectTransformGroup.setTransform( currentTransform );
previousX = x;
previousY = y;
}
/**
* Respond to a button3 event (press, release, or drag).
*
* @param mouseEvent A MouseEvent to respond to.
*/
public void onButton3( MouseEvent mev )
{
if ( subjectTransformGroup == null )
return;
int x = mev.getX( );
int y = mev.getY( );
if ( mev.getID( ) == MouseEvent.MOUSE_PRESSED )
{
// Mouse button pressed: record position
previousX = x;
previousY = y;
// Change to a "move" cursor
if ( parentComponent != null )
{
savedCursor = parentComponent.getCursor( );
parentComponent.setCursor(
Cursor.getPredefinedCursor( Cursor.MOVE_CURSOR ) );
}
return;
}
if ( mev.getID( ) == MouseEvent.MOUSE_RELEASED )
{
// Mouse button released: do nothing
// Switch the cursor back
if ( parentComponent != null )
parentComponent.setCursor( savedCursor );
return;
}
//
// Mouse moved while button down: create a translation
//
// Compute the delta in X and Y from the previous
// position. Use the delta to compute translation
// distances with the mapping:
//
// positive X mouse delta --> positive X-axis translation
// positive Y mouse delta --> negative Y-axis translation
//
// where positive X mouse movement is to the right, and
// positive Y mouse movement is **down** the screen.
//
int deltaX = x - previousX;
int deltaY = y - previousY;
if ( deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA ||
deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA )
{
// Deltas are too huge to be believable. Probably a glitch.
// Don't record the new XY location, or do anything.
return;
}
double xTranslationDistance = deltaX * XTranslationFactor;
double yTranslationDistance = -deltaY * YTranslationFactor;
//
// Build transforms
//
translate.set( xTranslationDistance, yTranslationDistance, 0.0 );
transform1.set( translate );
// Get and save the current transform
subjectTransformGroup.getTransform( currentTransform );
// Translate as needed
currentTransform.mul( transform1, currentTransform );
// Update the transform group
subjectTransformGroup.setTransform( currentTransform );
previousX = x;
previousY = y;
}
/**
* Respond to an elapsed frames event (assuming subclass has set up a
* wakeup criterion for it).
*
* @param time A WakeupOnElapsedFrames criterion to respond to.
*/
public void onElapsedFrames( WakeupOnElapsedFrames timeEvent )
{
// Can't happen
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -