view native/OpenHaptics/XYPad/XYScene.cpp @ 1:46671fc7d649 tip

fixed "window" message bug and brought the message outside the haptic device monitor
author Fiore Martin <f.martin@qmul.ac.uk>
date Fri, 13 Mar 2015 13:02:16 +0000
parents 011caca7515a
children
line wrap: on
line source
/*
XYPad - a haptic xy-pad that uses the jHapticGUI library

Copyright (C) 2015  Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "XYScene.h"

#include <HL/hl.h>
#include <HDU/hduError.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include <iostream>

jhapticgui::XYScene::XYScene(void(*messageCallback) (const Message & m)) : HapticScene(messageCallback) {}

jhapticgui::XYScene::~XYScene() {}

bool jhapticgui::XYScene::initHaptics(void){
	/* init haptic device */
	HHD hHD = hdInitDevice(HD_DEFAULT_DEVICE);
	if (HD_DEVICE_ERROR(hdGetError())) {
		/* if unsuccessful return false */
		return false;
	}

	/* create haptic context */
	HHLRC hHLRC = hlCreateContext(hHD);
	hlMakeCurrent(hHLRC);

	/* Reserve an id for the shape */
	shapeID = hlGenShapes(1);


	/* initialize the haptic space */
	hlMatrixMode(HL_TOUCHWORKSPACE);
	hlLoadIdentity();
	hlOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

	/* install event callbacks for touch and motion */
	hlAddEventCallback(HL_EVENT_TOUCH, HL_OBJECT_ANY, HL_CLIENT_THREAD, checkContact, this);
	hlAddEventCallback(HL_EVENT_UNTOUCH, HL_OBJECT_ANY, HL_CLIENT_THREAD, checkContact, this);
	hlAddEventCallback(HL_EVENT_MOTION, HL_OBJECT_ANY, HL_CLIENT_THREAD, checkMotion, this);

	/* initialization successful */
	return true;
}

void jhapticgui::XYScene::initGL(void){
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

	glDepthFunc(GL_LEQUAL);
	glEnable(GL_DEPTH_TEST);
}


unsigned int jhapticgui::XYScene::processMessage(const Message & m){
	/* there is only one type of message coming from the java * 
	 * but the check is performed nevertheless for clarity    */
	if (!strcmp(m.command, "change")) {

		/* the command selects the shape to display here all is done   *
		 * is just a variable update. The variable new value will be   *
		 * read in the  next cycle of drawScene                        */
		if (!strcmp(m.args, "circle")){
			shape = Shape::CIRCLE;
		}
		else  if(!strcmp(m.args, "square")){
			shape = Shape::SQUARE;
		}
	}

	/* message updates not used, just return any value */
	return 0;
}

void jhapticgui::XYScene::beginFrame(void){
	hlBeginFrame();
}

void jhapticgui::XYScene::endFrame(void){
	hlEndFrame();
}

void jhapticgui::XYScene::drawCursor(void){
	/* no cursor drawn */
}

void jhapticgui::XYScene::drawScene(unsigned int messageUpdate, unsigned int callbacksUpdate){

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f(1.0, 200.0/255.0, 0.0);

	hlBeginShape(HL_SHAPE_DEPTH_BUFFER, shapeID);

	/* use shape variable to determine which shape to draw */
	if (shape == Shape::SQUARE){
		glBegin(GL_POLYGON);
		glVertex3f(-RADIUS, -RADIUS, 0.0);
		glVertex3f(RADIUS, -RADIUS, 0.0);
		glVertex3f(RADIUS, RADIUS, 0.0);
		glVertex3f(-RADIUS, RADIUS, 0.0);
		glEnd();
	}
	else { // CIRCLE 
		glutSolidSphere(RADIUS, 64, 64);
	}
	
	hlEndShape();
}

unsigned int jhapticgui::XYScene::checkCallbacks(void){
	/* openhaptics call to check all the events */
	hlCheckEvents();
	/* no callback update used, return any value */
	return 0;
}

/* contact callback  */
void jhapticgui::XYScene::checkContact(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata){
	XYScene *pThis = static_cast<XYScene*>(userdata);

	/* update a status variable and send a message to the java thread */
	if (event == HL_EVENT_TOUCH){
		pThis->isTouching = true;
		pThis->send(Message("touch", "yes", object));
	}
	else{
		pThis->isTouching = false;
		pThis->send(Message("touch", "no", object));
	}
}

/* motion callback */
void jhapticgui::XYScene::checkMotion(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata){
	/* pointer to this scene */
	XYScene *pThis = static_cast<XYScene*>(userdata);

	/* get the proxy position */
	HLdouble proxyPosition[3];
	hlGetDoublev(HL_DEVICE_POSITION, proxyPosition);

	/* only send position data if the haptic object is being touched */
	if (pThis->isTouching){
		/* the proxy position ranges from -RADIUS to +RADIUS   *
		 * so the formula to get a normalized position (0 to 1)*
		 * is: ( proxyPos - (-RADIUS) / (RADIUS) - (-RADIUS) ),*
		 * let RADIUS be 0.5, the above formula is reduced to  *
		 * proxyPos + RADIUS                                   */
		double x = proxyPosition[0] + RADIUS;
		double y = proxyPosition[1] + RADIUS;

		/* send position message */
		char msgArgs[Message::MAX_ARGS_LEN];
		sprintf_s(msgArgs, "%f %f", x, y);
		pThis->send(Message("position", msgArgs, object));
	}
}


const double jhapticgui::XYScene::RADIUS = 0.5;