| 13 | | extern "C" { |
| 14 | | #include <rfb/rfbclient.h> |
| 15 | | } |
| 16 | | |
| 17 | | class VncImage : public osg::Image |
| 18 | | { |
| 19 | | public: |
| 20 | | |
| 21 | | VncImage(); |
| 22 | | |
| 23 | | bool connect(int* argc, char** argv); |
| 24 | | |
| 25 | | void close(); |
| 26 | | |
| 27 | | static rfbBool resizeImage(rfbClient* client); |
| 28 | | |
| 29 | | static void updateImage(rfbClient* client,int x,int y,int w,int h); |
| 30 | | |
| 31 | | protected: |
| 32 | | |
| 33 | | virtual ~VncImage(); |
| 34 | | |
| 35 | | class RfbThread : public osg::Referenced, public OpenThreads::Thread |
| 36 | | { |
| 37 | | public: |
| 38 | | |
| 39 | | RfbThread(rfbClient* client): |
| 40 | | _client(client), |
| 41 | | _done(false) {} |
| 42 | | |
| 43 | | virtual ~RfbThread() |
| 44 | | { |
| 45 | | _done = true; |
| 46 | | cancel(); |
| 47 | | while(isRunning()) |
| 48 | | { |
| 49 | | OpenThreads::Thread::YieldCurrentThread(); |
| 50 | | } |
| 51 | | } |
| 52 | | |
| 53 | | virtual void run() |
| 54 | | { |
| 55 | | do |
| 56 | | { |
| 57 | | int i=WaitForMessage(_client,500); |
| 58 | | if(i<0) |
| 59 | | return; |
| 60 | | if(i) |
| 61 | | if(!HandleRFBServerMessage(_client)) |
| 62 | | return; |
| 63 | | |
| 64 | | } while (!_done && !testCancel()); |
| 65 | | } |
| 66 | | |
| 67 | | rfbClient* _client; |
| 68 | | bool _done; |
| 69 | | |
| 70 | | }; |
| 71 | | |
| 72 | | public: |
| 73 | | |
| 74 | | rfbClient* _client; |
| 75 | | |
| 76 | | osg::ref_ptr<RfbThread> _rfbThread; |
| 77 | | |
| 78 | | }; |
| 79 | | |
| 80 | | VncImage::VncImage() |
| 81 | | { |
| 82 | | // setPixelBufferObject(new osg::PixelBufferObject(this); |
| 83 | | |
| 84 | | } |
| 85 | | |
| 86 | | VncImage::~VncImage() |
| 87 | | { |
| 88 | | close(); |
| 89 | | } |
| 90 | | |
| 91 | | bool VncImage::connect(int* argc, char** argv) |
| 92 | | { |
| 93 | | if (_client) close(); |
| 94 | | |
| 95 | | _client = rfbGetClient(8,3,4); |
| 96 | | _client->canHandleNewFBSize = TRUE; |
| 97 | | _client->MallocFrameBuffer = resizeImage; |
| 98 | | _client->GotFrameBufferUpdate = updateImage; |
| 99 | | _client->HandleKeyboardLedState = 0; |
| 100 | | _client->HandleTextChat = 0; |
| 101 | | |
| 102 | | rfbClientSetClientData(_client, 0, this); |
| 103 | | |
| 104 | | if (rfbInitClient(_client,argc,argv)) |
| 105 | | { |
| 106 | | _rfbThread = new RfbThread(_client); |
| 107 | | _rfbThread->startThread(); |
| 108 | | } |
| 109 | | } |
| 110 | | |
| 111 | | void VncImage::close() |
| 112 | | { |
| 113 | | if (_rfbThread.valid()) |
| 114 | | { |
| 115 | | // stop the client thread |
| 116 | | _rfbThread = 0; |
| 117 | | } |
| 118 | | |
| 119 | | if (_client) |
| 120 | | { |
| 121 | | // close the client |
| 122 | | rfbClientCleanup(_client); |
| 123 | | _client = 0; |
| 124 | | } |
| 125 | | } |
| | 13 | #include <osgDB/ReadFile> |
| 136 | | std::cout<<"resize "<<width<<", "<<height<<", "<<depth<<" image = "<<image<<std::endl; |
| 137 | | |
| 138 | | image->allocateImage(width,height,1,GL_RGBA,GL_UNSIGNED_BYTE); |
| 139 | | |
| 140 | | client->frameBuffer= (uint8_t*)(image->data()); |
| 141 | | |
| 142 | | return TRUE; |
| 143 | | } |
| 144 | | |
| 145 | | void VncImage::updateImage(rfbClient* client,int x,int y,int w,int h) |
| 146 | | { |
| 147 | | osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0)); |
| 148 | | image->dirty(); |
| 149 | | } |
| 150 | | |
| 151 | | |
| 152 | | class RfbEventHandler : public osgGA::GUIEventHandler |
| 153 | | { |
| 154 | | public: |
| 155 | | |
| 156 | | RfbEventHandler(rfbClient* client): |
| 157 | | _client(client) {} |
| 158 | | |
| 159 | | virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv); |
| 160 | | |
| 161 | | rfbKeySym key2rfbKeySym(int key) |
| 162 | | { |
| 163 | | return rfbKeySym(key); |
| 164 | | } |
| 165 | | |
| 166 | | protected: |
| 167 | | |
| 168 | | virtual ~RfbEventHandler() {} |
| 169 | | |
| 170 | | bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const; |
| 171 | | |
| 172 | | rfbClient* _client; |
| 173 | | |
| 174 | | }; |
| 175 | | |
| 176 | | bool RfbEventHandler::mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const |
| 177 | | { |
| 178 | | osgUtil::LineSegmentIntersector::Intersections intersections; |
| 179 | | bool foundIntersection = view==0 ? false : |
| 180 | | (nv==0 ? view->computeIntersections(ea.getX(), ea.getY(), intersections) : |
| 181 | | view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections)); |
| 182 | | |
| 183 | | if (foundIntersection) |
| 184 | | { |
| 185 | | |
| 186 | | osg::Vec2 tc(0.5f,0.5f); |
| 187 | | |
| 188 | | // use the nearest intersection |
| 189 | | const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin()); |
| 190 | | osg::Drawable* drawable = intersection.drawable.get(); |
| 191 | | osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0; |
| 192 | | osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0; |
| 193 | | if (vertices) |
| 194 | | { |
| 195 | | // get the vertex indices. |
| 196 | | const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList; |
| 197 | | const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList; |
| 198 | | |
| 199 | | if (indices.size()==3 && ratios.size()==3) |
| 200 | | { |
| 201 | | unsigned int i1 = indices[0]; |
| 202 | | unsigned int i2 = indices[1]; |
| 203 | | unsigned int i3 = indices[2]; |
| 204 | | |
| 205 | | float r1 = ratios[0]; |
| 206 | | float r2 = ratios[1]; |
| 207 | | float r3 = ratios[2]; |
| 208 | | |
| 209 | | osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0; |
| 210 | | osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords); |
| 211 | | if (texcoords_Vec2Array) |
| 212 | | { |
| 213 | | // we have tex coord array so now we can compute the final tex coord at the point of intersection. |
| 214 | | osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1]; |
| 215 | | osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2]; |
| 216 | | osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3]; |
| 217 | | tc = tc1*r1 + tc2*r2 + tc3*r3; |
| 218 | | } |
| 219 | | } |
| 220 | | |
| 221 | | } |
| 222 | | |
| 223 | | x = int( float(_client->width) * tc.x() ); |
| 224 | | y = int( float(_client->height) * tc.y() ); |
| 225 | | |
| 226 | | return true; |
| 227 | | } |
| 228 | | |
| 229 | | return false; |
| 230 | | } |
| 231 | | |
| 232 | | |
| 233 | | bool RfbEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv) |
| 234 | | { |
| 235 | | switch(ea.getEventType()) |
| 236 | | { |
| 237 | | case(osgGA::GUIEventAdapter::MOVE): |
| 238 | | case(osgGA::GUIEventAdapter::DRAG): |
| 239 | | case(osgGA::GUIEventAdapter::PUSH): |
| 240 | | case(osgGA::GUIEventAdapter::RELEASE): |
| 241 | | { |
| 242 | | osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); |
| 243 | | int x,y; |
| 244 | | if (mousePosition(view, nv, ea, x, y)) |
| 245 | | { |
| 246 | | SendPointerEvent(_client,x,y, ea.getButtonMask()); |
| 247 | | return true; |
| 248 | | } |
| 249 | | break; |
| 250 | | } |
| 251 | | case(osgGA::GUIEventAdapter::KEYDOWN): |
| 252 | | case(osgGA::GUIEventAdapter::KEYUP): |
| 253 | | { |
| 254 | | osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); |
| 255 | | int x,y; |
| 256 | | bool sendKeyEvent = mousePosition(view, nv, ea, x, y); |
| 257 | | |
| 258 | | if (sendKeyEvent) |
| 259 | | { |
| 260 | | SendKeyEvent(_client, |
| 261 | | key2rfbKeySym(ea.getKey()), |
| 262 | | (ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN)?TRUE:FALSE); |
| 263 | | |
| 264 | | return true; |
| 265 | | } |
| 266 | | else |
| 267 | | { |
| 268 | | if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Escape) |
| 269 | | { |
| 270 | | osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa); |
| 271 | | if (viewer) viewer->setDone(true); |
| 272 | | } |
| 273 | | } |
| 274 | | |
| 275 | | } |
| 276 | | |
| 277 | | default: |
| 278 | | return false; |
| 279 | | } |
| 280 | | return false; |
| 281 | | } |
| 282 | | |
| 283 | | int main(int argc,char** argv) |
| 284 | | { |
| 285 | | osg::ref_ptr<VncImage> image = new VncImage; |
| 286 | | |
| 287 | | if (image->connect(&argc,argv)) |
| 288 | | { |
| 289 | | return 1; |
| 290 | | } |
| 291 | | |
| 292 | | osg::ArgumentParser arguments(&argc, argv); |
| 293 | | osgViewer::Viewer viewer; |
| 294 | | |
| 295 | | |
| 296 | | bool xyPlane = false; |
| 297 | | bool flip = true; |
| 298 | | float width = image->s(); |
| 299 | | float height = image->t(); |
| 300 | | |
| 301 | | osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f), |
| 302 | | osg::Vec3(width,0.0f,0.0f), |
| 303 | | xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height), |
| | 21 | osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(origin, widthAxis, heightAxis, |
| 319 | | viewer.setSceneData(geode); |
| | 39 | return geode; |
| | 40 | } |
| | 41 | |
| | 42 | class EscapeHandler : public osgGA::GUIEventHandler |
| | 43 | { |
| | 44 | public: |
| | 45 | |
| | 46 | EscapeHandler() {} |
| | 47 | |
| | 48 | bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) |
| | 49 | { |
| | 50 | if (ea.getHandled()) return false; |
| | 51 | |
| | 52 | switch(ea.getEventType()) |
| | 53 | { |
| | 54 | case(osgGA::GUIEventAdapter::KEYUP): |
| | 55 | { |
| | 56 | if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Escape) |
| | 57 | { |
| | 58 | osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); |
| | 59 | if (view) view->getViewerBase()->setDone(true); |
| | 60 | |
| | 61 | return true; |
| | 62 | } |
| | 63 | } |
| | 64 | |
| | 65 | default: |
| | 66 | return false; |
| | 67 | } |
| | 68 | return false; |
| | 69 | } |
| | 70 | }; |
| | 71 | |
| | 72 | int main(int argc,char** argv) |
| | 73 | { |
| | 74 | |
| | 75 | osg::ArgumentParser arguments(&argc, argv); |
| | 76 | osgViewer::Viewer viewer; |
| | 77 | |
| | 78 | typedef std::list< osg::ref_ptr<osg::Image> > Images; |
| | 79 | Images images; |
| | 80 | |
| | 81 | std::string hostname; |
| | 82 | while (arguments.read("--host",hostname)) |
| | 83 | { |
| | 84 | osg::ref_ptr<osg::Image> image = osgDB::readImageFile(hostname+std::string(".vnc")); |
| | 85 | if (image.valid()) images.push_back(image.get()); |
| | 86 | } |
| | 87 | |
| | 88 | if (images.empty()) |
| | 89 | { |
| | 90 | return 1; |
| | 91 | } |
| | 92 | |
| | 93 | bool xyPlane = false; |
| | 94 | |
| | 95 | osg::Group* group = new osg::Group; |
| | 96 | |
| | 97 | osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f); |
| | 98 | for(Images::iterator itr = images.begin(); |
| | 99 | itr != images.end(); |
| | 100 | ++itr) |
| | 101 | { |
| | 102 | osg::Image* image = itr->get(); |
| | 103 | float width = 1.0; |
| | 104 | float height = float(image->t())/float(image->s()); |
| | 105 | osg::Vec3 widthAxis = osg::Vec3(width,0.0f,0.0f); |
| | 106 | osg::Vec3 heightAxis = xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height); |
| | 107 | group->addChild(createInteractiveQuad(origin, widthAxis, heightAxis, image)); |
| | 108 | |
| | 109 | origin += widthAxis*1.1f; |
| | 110 | } |
| | 111 | |
| | 112 | viewer.setSceneData(group); |