package vgp.tutor.eventCamera; import java.awt.Color; import jv.geom.PgElementSet; import jv.number.PuDouble; import jv.object.PsObject; import jv.project.PvDisplayIf; import jv.project.PvCameraIf; import jv.project.PvCameraEvent; import jv.project.PvCameraListenerIf; import jv.project.PvLightIf; import jv.project.PjProject; import jv.project.PvViewerIf; import jv.vecmath.PdVector; import jv.vecmath.PuVectorGeom; /** * Demo project shows how to handle camera events issued from * a JavaView display. In this example the events are used to * steer the camera in a second window. *
* The camera events from one window are used to steer the
* camera in the other window such that a stereo effect is produced.
* Note, the viewing direction of the left camera is slightly rotated
* around the up-vector of the camera by about 6 degrees.
*
* @see jv.project.PvCameraEvent
* @see jv.project.PvCameraListenerIf
* @see jv.project.PvDisplayIf
* @author Konrad Polthier
* @version 05.11.06, 2.10 revised (kp) Appearance of surface adjusted.
* 14.12.03, 2.00 revised (kp) Full revision.
* 25.07.00, 1.00 created (kp)
*/
public class PjEventCamera extends PjProject implements PvCameraListenerIf {
/** Cross eye stereo projection. */
public final static int STEREO_CROSS = 0;
/** Parallel eye stereo projection. */
public final static int STEREO_PARALLEL = 1;
/** Red green painting of stereo projection. */
public final static int STEREO_REDGREEN = 2;
/** Torus geometry added to both displays. */
protected PgElementSet m_geom;
/** Left display which is steered. */
protected PvDisplayIf m_dispRight;
/** Right display which issues camera events. */
protected PvDisplayIf m_dispLeft;
/** Type of stereo projection, see {@link #STEREO_CROSS STEREO_CROSS} and similar. */
protected int m_stereoType;
/** Angle between left and right camera. */
protected PuDouble m_parallax;
/** Currently selected display. */
protected PvDisplayIf m_currDisp;
public PjEventCamera() {
super("Camera Events");
m_geom = new PgElementSet(3);
m_parallax = new PuDouble("Parallax", this);
if (getClass() == PjEventCamera.class)
init();
}
public void init() {
super.init();
m_geom.setName("Torus");
m_geom.computeTorus(10, 10, 2., 1.);
m_geom.setGlobalVertexSize(4.);
m_geom.setGlobalEdgeSize(2.);
m_geom.showVertices(true);
m_geom.showElements(false);
m_geom.makeVertexColorsFromZHue();
m_geom.showVertexColors(false);
m_geom.showEdgeColors(true);
m_geom.showEdgeColorFromElements(false);
// Mark a vertex to help focusing the eyes.
PdVector v = m_geom.getVertex(74);
if (v != null)
v.setTag(PsObject.IS_SELECTED);
m_stereoType = STEREO_PARALLEL;
m_parallax.setDefBounds(0., 30., 0.5, 2.);
m_parallax.setDefValue(6.);
m_parallax.init();
m_currDisp = m_dispRight;
}
public void start() {
// Add geometry to default window, ie. the right window.
addGeometry(m_geom);
selectGeometry(m_geom);
getLeftDisplay().addGeometry(m_geom);
getRightDisplay().addGeometry(m_geom);
super.start();
}
public void reset() {
init();
if (!m_dispRight.containsGeometry(m_geom))
m_dispRight.addGeometry(m_geom);
if (!m_dispLeft.containsGeometry(m_geom))
m_dispLeft.addGeometry(m_geom);
m_geom.update(m_geom);
update(this);
updateDisplay(m_currDisp);
}
public boolean update(Object event) {
if (event == m_geom) {
return true;
} else if (event == m_parallax) {
updateDisplay(m_currDisp);
return true;
}
return super.update(event);
}
public PvDisplayIf getRightDisplay() {
if (m_dispRight != null)
return m_dispRight;
// Get viewer and ask for another display
PvViewerIf viewer = getViewer();
// Create right window and add a clone of the torus geometry.
m_dispRight = viewer.newDisplay("Right Display", false);
m_dispRight.setBackgroundColor(Color.white);
m_dispRight.showDepthcue(true);
m_dispRight.showEdgeAura(false);
m_dispRight.setLightingModel(PvLightIf.MODEL_SURFACE);
m_dispRight.addCameraListener(this);
return m_dispRight;
}
public PvDisplayIf getLeftDisplay() {
if (m_dispLeft != null)
return m_dispLeft;
// Get viewer and ask for another display
PvViewerIf viewer = getViewer();
// Create left window and add a clone of the torus geometry.
m_dispLeft = viewer.newDisplay("Left Display", false);
m_dispLeft.setBackgroundColor(Color.white);
m_dispLeft.showDepthcue(true);
m_dispLeft.showEdgeAura(false);
m_dispLeft.setLightingModel(PvLightIf.MODEL_SURFACE);
m_dispLeft.addCameraListener(this);
return m_dispLeft;
}
/**
* Get type of stereo projection.
* @return stereo projection type, see {@link #STEREO_CROSS STEREO_CROSS} and similar.
*/
public int getStereoType() { return m_stereoType; }
/**
* Set type of stereo projection.
* @param type stereo projection type, see {@link #STEREO_CROSS STEREO_CROSS} and similar.
*/
public void setStereoType(int type) { m_stereoType = type; }
/**
* Get camera events resulting from picking the mouse.
* Use information about camera in one display to
* adjust the camera in the other window. But previously
* rotate the camera position around the line given by
* interest+t*upVector by -6 degrees.
*/
public void pickCamera(PvCameraEvent pos) {
if (m_bUpdating)
return;
// Do nothing if not both display have been created yet
if (m_dispLeft==null || m_dispRight==null)
return;
// Find out which camera has issued the event, and then steer the other.
PvDisplayIf dispSrc = pos.getSource();
updateDisplay(dispSrc);
}
protected void updateDisplay(PvDisplayIf dispSrc) {
if (dispSrc == null)
return;
m_currDisp = dispSrc;
PvCameraIf camSrc = dispSrc.getCamera();
PdVector interest = camSrc.getInterest();
PdVector upVector = camSrc.getUpVector();
PdVector position = camSrc.getPosition();
double scale = camSrc.getScale();
PvDisplayIf dispSteer = null;
PvCameraIf camSteer = null;
double angle = m_parallax.getValue()*Math.PI/180;
double flag = ((m_stereoType==STEREO_CROSS)?-1:1);
if (dispSrc == m_dispRight) {
camSteer = m_dispLeft.getCamera();
dispSteer = m_dispLeft;
angle = -flag*angle;
} else {
camSteer = m_dispRight.getCamera();
dispSteer = m_dispRight;
angle = flag*angle;
}
PdVector pRot = (PdVector)position.clone();
PuVectorGeom.rotatePointAroundLine(pRot, position, interest, upVector, angle);
camSteer.setScale(scale);
camSteer.setFullPosition(interest, pRot, upVector);
// Update the camera in the steered display
// but block this current method to avoid an infinite loop
// since the steered camera will also issue a camera event.
m_bUpdating = true;
dispSteer.update(camSteer);
m_bUpdating = false;
}
boolean m_bUpdating = false;
/**
* Get camera events resulting from dragging the mouse.
* This method just calls the method pickCamera which does all the work.
*/
public void dragCamera(PvCameraEvent pos) {
pickCamera(pos);
}
}