package cz.cuni.jagrlib.testing; import cz.cuni.jagrlib.*; import cz.cuni.jagrlib.iface.Trigger; import cz.cuni.jagrlib.reg.*; /** * Computes 3D-to-2D transformation matrix from interactive mouse/keyboard events. * * @version 0.24 $Rev: 183 $ $Date: 2006-02-08 01:24:54 +0100 (st, 08 II 2006) $ $Author: pepca $ * @since 0.24 * @see InteractiveProjection.java */ public class InteractiveProjection extends DefaultInputListener { //========================================================================== // Data: /** Zoom coefficient for one mouse-wheel "tick" minus 1.0d. */ public static final double WHEEL_ZOOM = 0.03d; /** Actual window width in pixels. */ protected int width = 0; /** Actual window height in pixels. */ protected int height = 0; /** Actual projection matrix. */ protected TrMatrix proj = new TrMatrix( 4, 3 ); protected double rotZ = 0.0d; protected double rotX = 0.0d; /** Actual result zoom factor. */ protected double zoom = 1.0d; /** Zoom factor produces by the mouse-wheel. */ protected double wheelZoom = 1.0d; /** Mouse-move processing is switched on? */ protected boolean live = false; /** Actual translation component. */ protected double[] transl = { 0.0d, 0.0d, 0.0d }; //========================================================================== // Support: /** Assembles the projection matrix and triggers the "redraw" action. */ protected void updateMatrix () { proj.identity( 4, 3 ); proj.rotateAxis3D( 2, rotZ, null ); proj.rotateAxis3D( 0, rotX + 0.5d * Math.PI, null ); proj.scale3D( null, zoom * wheelZoom, null ); proj.translate3D( transl, null ); Trigger t = (Trigger)getInterface( PL_OUTPUT, IFACE+"Trigger" ); if ( t != null ) t.fire( 0 ); } //========================================================================== // Interface InputListener: /** * Change the window shape. * * @param width Horizontal window size in pixels. * @param height Vertical window size in pixels. */ @Override public void setWindowSize ( int width, int height ) { this.width = width; this.height = height; transl[0] = 0.5d * width; transl[1] = 0.5d * height; zoom = Math.min( transl[0], transl[1] ); updateMatrix(); } /** * Mouse button was pressed/released. * * @param when System time in milliseconds. * @param x Horizontal screen position in pixels. * @param y Vertical screen position in pixels. * @param button Button number (0, 1, etc.). * @param press Was it press or release? * @param flags Input system status (key shifts/alts, ..). */ @Override public void mouseButton ( long when, int x, int y, int button, boolean press, int flags ) { if ( button != 1 || press ) return; live = !live; } /** * Mouse pointer was moved. * * @param when System time in milliseconds. * @param x Horizontal screen position in pixels. * @param y Vertical screen position in pixels. * @param flags Input system status (key shifts/alts, ..). */ @Override public void mouseMove ( long when, int x, int y, int flags ) { if ( !live ) return; rotZ = ((double)x / width - 0.5d) * 2.0d * Math.PI; rotX = -((double)y / width - 0.5d) * 2.0d * Math.PI; updateMatrix(); } /** * Mouse wheel was rotated. * * @param when System time in milliseconds. * @param x Horizontal screen position in pixels. * @param y Vertical screen position in pixels. * @param wheel Wheel number (0, 1, etc.). * @param amount Rotation angle (positive number means down - or towards the user). * @param flags Input system status (key shifts/alts, ..). */ @Override public void mouseWheel ( long when, int x, int y, int wheel, int amount, int flags ) { if ( amount == 0 ) return; wheelZoom *= 1.0d + WHEEL_ZOOM * amount; updateMatrix(); } //========================================================================== // Interface Property: public final static String MATRIX = "Matrix"; /** * Sets the given property. * * @param key Key string. * @param value The new value. */ public void set ( String key, Object value ) { if ( key == null || value == null ) return; // MATRIX: if ( key.compareTo(MATRIX) == 0 ) { if ( value != null && value instanceof TrMatrix ) proj = (TrMatrix)value; return; } } /** * Gets the given property. * * @param key Key string. * @return The actual value or null. */ public Object get ( String key ) { if ( key == null ) return null; if ( key.compareTo(MATRIX) == 0 ) return proj; return null; } //========================================================================== // Module registration: /** Object name. */ private final static String NAME = "InteractiveProjection"; /** Object template identifier. */ protected final static String TEMPLATE_NAME = "InputListenerToTrigger"; /** Object description. */ private final static String DESCRIPTION = "Computes projection matrix from interactive mouse events."; /** Object category. */ protected final static String CATEGORY = C_3D + ".projection"; /** * General-purpose registration routine. * Sets all plugs, strings, etc. to the given Template. */ public static int setTemplate ( Template t, int ord ) { if ( t != null && ord <= 0 ) { t.setRegStrings( NAME, TEMPLATE_NAME, CATEGORY, DESCRIPTION ); // Plugs: t.newInputPlug( PL_INPUT, IFACE+"InputListener" ); t.newOptOutputPlug( PL_OUTPUT, IFACE+"Trigger" ); // Property: t.propBegin( MATRIX, TYPE_OBJECT, "Projection matrix", false ); t.propEnd(); } return 1; } /** * Static registration instance for this class. * Automatically initialized in class-loading time. */ public static final RegPiece reg; static { reg = new RegPiece(); setTemplate( reg, 0 ); } }