annotate 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
rev   line source
f@0 1 /*
f@0 2 XYPad - a haptic xy-pad that uses the jHapticGUI library
f@0 3
f@0 4 Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19 #include "XYScene.h"
f@0 20
f@0 21 #include <HL/hl.h>
f@0 22 #include <HDU/hduError.h>
f@0 23
f@0 24 #include <GL/gl.h>
f@0 25 #include <GL/glu.h>
f@0 26 #include <GL/glut.h>
f@0 27
f@0 28 #include <iostream>
f@0 29
f@0 30 jhapticgui::XYScene::XYScene(void(*messageCallback) (const Message & m)) : HapticScene(messageCallback) {}
f@0 31
f@0 32 jhapticgui::XYScene::~XYScene() {}
f@0 33
f@0 34 bool jhapticgui::XYScene::initHaptics(void){
f@0 35 /* init haptic device */
f@0 36 HHD hHD = hdInitDevice(HD_DEFAULT_DEVICE);
f@0 37 if (HD_DEVICE_ERROR(hdGetError())) {
f@0 38 /* if unsuccessful return false */
f@0 39 return false;
f@0 40 }
f@0 41
f@0 42 /* create haptic context */
f@0 43 HHLRC hHLRC = hlCreateContext(hHD);
f@0 44 hlMakeCurrent(hHLRC);
f@0 45
f@0 46 /* Reserve an id for the shape */
f@0 47 shapeID = hlGenShapes(1);
f@0 48
f@0 49
f@0 50 /* initialize the haptic space */
f@0 51 hlMatrixMode(HL_TOUCHWORKSPACE);
f@0 52 hlLoadIdentity();
f@0 53 hlOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
f@0 54
f@0 55 /* install event callbacks for touch and motion */
f@0 56 hlAddEventCallback(HL_EVENT_TOUCH, HL_OBJECT_ANY, HL_CLIENT_THREAD, checkContact, this);
f@0 57 hlAddEventCallback(HL_EVENT_UNTOUCH, HL_OBJECT_ANY, HL_CLIENT_THREAD, checkContact, this);
f@0 58 hlAddEventCallback(HL_EVENT_MOTION, HL_OBJECT_ANY, HL_CLIENT_THREAD, checkMotion, this);
f@0 59
f@0 60 /* initialization successful */
f@0 61 return true;
f@0 62 }
f@0 63
f@0 64 void jhapticgui::XYScene::initGL(void){
f@0 65 glClearColor(0.0, 0.0, 0.0, 0.0);
f@0 66 glMatrixMode(GL_PROJECTION);
f@0 67 glLoadIdentity();
f@0 68 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
f@0 69
f@0 70 glDepthFunc(GL_LEQUAL);
f@0 71 glEnable(GL_DEPTH_TEST);
f@0 72 }
f@0 73
f@0 74
f@0 75 unsigned int jhapticgui::XYScene::processMessage(const Message & m){
f@0 76 /* there is only one type of message coming from the java *
f@0 77 * but the check is performed nevertheless for clarity */
f@0 78 if (!strcmp(m.command, "change")) {
f@0 79
f@0 80 /* the command selects the shape to display here all is done *
f@0 81 * is just a variable update. The variable new value will be *
f@0 82 * read in the next cycle of drawScene */
f@0 83 if (!strcmp(m.args, "circle")){
f@0 84 shape = Shape::CIRCLE;
f@0 85 }
f@0 86 else if(!strcmp(m.args, "square")){
f@0 87 shape = Shape::SQUARE;
f@0 88 }
f@0 89 }
f@0 90
f@0 91 /* message updates not used, just return any value */
f@0 92 return 0;
f@0 93 }
f@0 94
f@0 95 void jhapticgui::XYScene::beginFrame(void){
f@0 96 hlBeginFrame();
f@0 97 }
f@0 98
f@0 99 void jhapticgui::XYScene::endFrame(void){
f@0 100 hlEndFrame();
f@0 101 }
f@0 102
f@0 103 void jhapticgui::XYScene::drawCursor(void){
f@0 104 /* no cursor drawn */
f@0 105 }
f@0 106
f@0 107 void jhapticgui::XYScene::drawScene(unsigned int messageUpdate, unsigned int callbacksUpdate){
f@0 108
f@0 109 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
f@0 110 glColor3f(1.0, 200.0/255.0, 0.0);
f@0 111
f@0 112 hlBeginShape(HL_SHAPE_DEPTH_BUFFER, shapeID);
f@0 113
f@0 114 /* use shape variable to determine which shape to draw */
f@0 115 if (shape == Shape::SQUARE){
f@0 116 glBegin(GL_POLYGON);
f@0 117 glVertex3f(-RADIUS, -RADIUS, 0.0);
f@0 118 glVertex3f(RADIUS, -RADIUS, 0.0);
f@0 119 glVertex3f(RADIUS, RADIUS, 0.0);
f@0 120 glVertex3f(-RADIUS, RADIUS, 0.0);
f@0 121 glEnd();
f@0 122 }
f@0 123 else { // CIRCLE
f@0 124 glutSolidSphere(RADIUS, 64, 64);
f@0 125 }
f@0 126
f@0 127 hlEndShape();
f@0 128 }
f@0 129
f@0 130 unsigned int jhapticgui::XYScene::checkCallbacks(void){
f@0 131 /* openhaptics call to check all the events */
f@0 132 hlCheckEvents();
f@0 133 /* no callback update used, return any value */
f@0 134 return 0;
f@0 135 }
f@0 136
f@0 137 /* contact callback */
f@0 138 void jhapticgui::XYScene::checkContact(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata){
f@0 139 XYScene *pThis = static_cast<XYScene*>(userdata);
f@0 140
f@0 141 /* update a status variable and send a message to the java thread */
f@0 142 if (event == HL_EVENT_TOUCH){
f@0 143 pThis->isTouching = true;
f@0 144 pThis->send(Message("touch", "yes", object));
f@0 145 }
f@0 146 else{
f@0 147 pThis->isTouching = false;
f@0 148 pThis->send(Message("touch", "no", object));
f@0 149 }
f@0 150 }
f@0 151
f@0 152 /* motion callback */
f@0 153 void jhapticgui::XYScene::checkMotion(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata){
f@0 154 /* pointer to this scene */
f@0 155 XYScene *pThis = static_cast<XYScene*>(userdata);
f@0 156
f@0 157 /* get the proxy position */
f@0 158 HLdouble proxyPosition[3];
f@0 159 hlGetDoublev(HL_DEVICE_POSITION, proxyPosition);
f@0 160
f@0 161 /* only send position data if the haptic object is being touched */
f@0 162 if (pThis->isTouching){
f@0 163 /* the proxy position ranges from -RADIUS to +RADIUS *
f@0 164 * so the formula to get a normalized position (0 to 1)*
f@0 165 * is: ( proxyPos - (-RADIUS) / (RADIUS) - (-RADIUS) ),*
f@0 166 * let RADIUS be 0.5, the above formula is reduced to *
f@0 167 * proxyPos + RADIUS */
f@0 168 double x = proxyPosition[0] + RADIUS;
f@0 169 double y = proxyPosition[1] + RADIUS;
f@0 170
f@0 171 /* send position message */
f@0 172 char msgArgs[Message::MAX_ARGS_LEN];
f@0 173 sprintf_s(msgArgs, "%f %f", x, y);
f@0 174 pThis->send(Message("position", msgArgs, object));
f@0 175 }
f@0 176 }
f@0 177
f@0 178
f@0 179 const double jhapticgui::XYScene::RADIUS = 0.5;