package org.geogebra.desktop.geogebra3D.input3D.intelRealSense;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import org.geogebra.common.geogebra3D.euclidian3D.EuclidianView3D;
import org.geogebra.common.geogebra3D.input3D.Input3D;
import org.geogebra.common.kernel.Matrix.Coords;
import org.geogebra.common.main.App;
import org.geogebra.common.main.settings.EuclidianSettings3D;
import org.geogebra.common.util.debug.Log;
import org.geogebra.desktop.geogebra3D.input3D.Input3DFactory.Input3DException;
import org.geogebra.desktop.geogebra3D.input3D.Input3DFactory.Input3DExceptionType;
/**
* controller with specific methods from realsense input system
*
* @author mathieu
*
*/
public class InputIntelRealsense3D extends Input3D {
private Socket socket;
private double[] mousePosition;
private double[] mouseOrientation;
private boolean isRightPressed, isLeftPressed;
/**
* Check if realsense camera can be inited (check registry)
*
* @throws Input3DException
* if no camera installed
*/
public static void init() throws Input3DException {
try {
Socket.queryRegistry();
} catch (Input3DException e) {
throw e;
} catch (Throwable e) {
Log.error(e.getMessage());
throw new Input3DException(Input3DExceptionType.UNKNOWN,
e.getMessage());
}
}
/**
* constructor
*
*
* @throws Exception
*/
public InputIntelRealsense3D(final App app)
throws Input3DException {
// 3D mouse position
mousePosition = new double[3];
// 3D mouse orientation
mouseOrientation = new double[4];
// screen dimensions
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
screenHalfWidth = gd.getDisplayMode().getWidth()/2;
//screenHalfHeight = gd.getDisplayMode().getHeight()/2;
//App.debug("screen:"+screenWidth+"x"+screenHeight);
//App.error("height/2="+gd.getDisplayMode().getHeight()/2);
outOfField = OutOfField.YES;
socket = new Socket(app);
}
@Override
public boolean update() {
boolean updateOccured = false;
// update from last message
if (socket.gotMessage){
// mouse position
// double factor = screenHalfWidth;
double factor = panelWidth / 2;
mousePosition[0] = socket.handX * factor;
mousePosition[1] = socket.handY * factor;
mousePosition[2] = socket.handZ * factor;
// mouse position
mouseOrientation[0] = socket.handOrientationX;
mouseOrientation[1] = socket.handOrientationY;
mouseOrientation[2] = socket.handOrientationZ;
mouseOrientation[3] = socket.handOrientationW;
// right button
isRightPressed = socket.rightButton;
// left button
isLeftPressed = socket.leftButton;
updateOccured = true;
}
// request next message
socket.getData();
return updateOccured;
}
@Override
public double[] getInputPosition(){
return mousePosition;
}
@Override
public double[] getInputOrientation(){
return mouseOrientation;
}
@Override
public boolean isRightPressed(){
return isRightPressed;
}
@Override
public boolean isLeftPressed(){
return isLeftPressed;
}
@Override
public boolean isThirdButtonPressed() {
return false;
}
@Override
public boolean isButtonPressed(){
return isRightPressed() || isLeftPressed();
}
@Override
public double[] getGlassesPosition(int i){
return null; // not implemented yet
}
@Override
public double getEyeSeparation(){
return 0; // not implemented yet
}
@Override
public boolean useInputDepthForHitting(){
return false;
}
@Override
public boolean useMouseRobot(){
return false;
}
@Override
public DeviceType getDeviceType(){
return DeviceType.HAND;
}
private OutOfField outOfField;
@Override
public boolean hasMouse(EuclidianView3D view3D, Coords mouse3DPosition){
OutOfField oof = socket.getOutOfField(); // this is camera field of view
if (oof == OutOfField.NO) {
// check if mouse is out and if we should keep same out of field
switch (outOfField) {
case RIGHT:
if (mouse3DPosition.getX() < view3D.getRenderer().getRight()) {
outOfField = OutOfField.NO;
}
break;
case LEFT:
if (mouse3DPosition.getX() > view3D.getRenderer().getLeft()) {
outOfField = OutOfField.NO;
}
break;
case TOP:
if (mouse3DPosition.getY() < view3D.getRenderer().getTop()) {
outOfField = OutOfField.NO;
}
break;
case BOTTOM:
if (mouse3DPosition.getY() > view3D.getRenderer().getBottom()) {
outOfField = OutOfField.NO;
}
break;
case FAR:
if (mouse3DPosition.getZ() < view3D.getRenderer().getFar()) {
outOfField = OutOfField.NO;
}
break;
case NEAR:
if (mouse3DPosition.getZ() > view3D.getRenderer().getNear()) {
outOfField = OutOfField.NO;
}
break;
case NEVER:
break;
case NO:
break;
case YES:
break;
default:
break;
}
// now check if we are indeed in the 3D view field
if (mouse3DPosition.getX() > view3D.getRenderer().getRight()) {
outOfField = OutOfField.RIGHT;
} else if (mouse3DPosition.getX() < view3D.getRenderer().getLeft()) {
outOfField = OutOfField.LEFT;
} else if (mouse3DPosition.getY() > view3D.getRenderer().getTop()) {
outOfField = OutOfField.TOP;
} else if (mouse3DPosition.getY() < view3D.getRenderer()
.getBottom()) {
outOfField = OutOfField.BOTTOM;
} else if (mouse3DPosition.getZ() > view3D.getRenderer().getFar()) {
outOfField = OutOfField.FAR;
} else if (mouse3DPosition.getZ() < view3D.getRenderer().getNear()) {
outOfField = OutOfField.NEAR;
}
} else {
// set out of field from socket
outOfField = oof;
}
// App.debug(((int) mouse3DPosition.getZ()) + ","
// + view3D.getRenderer().getNear() + "--"
// + view3D.getRenderer().getFar() + " , "
// + view3D.getScreenZOffset());
// App.debug(oof + "," + outOfField);
return socket.hasTrackedHand();
}
@Override
public boolean hasMouse(EuclidianView3D view3D) {
return socket.hasTrackedHand();
}
@Override
public boolean currentlyUseMouse2D(){
return !socket.hasTrackedHand();
}
private boolean hasCompletedGrabbingDelay = false;
@Override
public void setHasCompletedGrabbingDelay(boolean flag){
hasCompletedGrabbingDelay = flag;
}
@Override
public boolean hasCompletedGrabbingDelay(){
return hasCompletedGrabbingDelay;
}
@Override
public void setPositionXYOnPanel(double[] absolutePos, Coords panelPos,
double screenHalfWidth, double screenHalfHeight, int panelPositionX, int panelPositionY,
int panelDimW, int panelDimH) {
panelPos.setX(absolutePos[0]);// + screenHalfWidth - panelPosition.x - panelDimension.width / 2);
panelPos.setY(absolutePos[1]);// - screenHalfHeight + panelPosition.y + panelDimension.height / 2);
}
@Override
public boolean useScreenZOffset(){
return false;
}
@Override
public boolean isStereoBuffered() {
return false;
}
@Override
public boolean useInterlacedPolarization(){
return false;
}
@Override
public boolean useCompletingDelay(){
return true;
}
@Override
public boolean hasMouseDirection() {
return false;
}
@Override
public double[] getInputDirection() {
return null;
}
@Override
public boolean useQuaternionsForRotate() {
return false;
}
@Override
public boolean wantsStereo() {
return false;
}
@Override
public double getDefaultRotationOz() {
return EuclidianView3D.ANGLE_ROT_OZ;
}
@Override
public double getDefaultRotationXOY() {
return EuclidianView3D.ANGLE_ROT_XOY;
}
@Override
public boolean shouldStoreStereoToXML() {
return true;
}
@Override
public boolean needsGrayBackground() {
return false;
}
@Override
public boolean useHeadTracking() {
return false;
}
@Override
public boolean useHandGrabbing() {
return true;
}
@Override
public OutOfField getOutOfField() {
return outOfField;
}
@Override
public void exit() {
// socket.exit();
}
@Override
public void setPositionOnScreen() {
// nothing to do
}
@Override
public void setPositionOffScreen() {
// nothing to do
}
@Override
public boolean isZSpace() {
return false;
}
@Override
public void setSpecificSettings(EuclidianSettings3D settings) {
// nothing to do
}
}