Line data Source code
1 :
2 : /* Copyright (c) 2009-2013, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #include "observer.h"
19 :
20 : #include "config.h"
21 : #include "client.h"
22 : #include "event.h"
23 : #include "eventICommand.h"
24 : #include "server.h"
25 :
26 : #include <eq/fabric/paths.h>
27 : #include <eq/fabric/commands.h>
28 : #include <co/bufferConnection.h>
29 :
30 : #ifdef EQUALIZER_USE_OPENCV
31 : # include "detail/cvTracker.h"
32 : #endif
33 : #ifdef EQUALIZER_USE_VRPN
34 : # include <vrpn_Tracker.h>
35 : # include <co/buffer.h>
36 : #else
37 : class vrpn_Tracker_Remote;
38 : #endif
39 :
40 :
41 : namespace eq
42 : {
43 : namespace detail
44 : {
45 : class CVTracker;
46 :
47 : class Observer
48 : {
49 : public:
50 10 : Observer()
51 : : vrpnTracker( 0 )
52 10 : , cvTracker( 0 )
53 10 : {}
54 :
55 : vrpn_Tracker_Remote *vrpnTracker;
56 : CVTracker* cvTracker;
57 : };
58 : }
59 :
60 : typedef fabric::Observer< Config, Observer > Super;
61 :
62 10 : Observer::Observer( Config* parent )
63 : : Super( parent )
64 10 : , _impl( new detail::Observer )
65 10 : {}
66 :
67 30 : Observer::~Observer()
68 : {
69 10 : delete _impl;
70 20 : }
71 :
72 0 : ServerPtr Observer::getServer()
73 : {
74 0 : Config* config = getConfig();
75 0 : LBASSERT( config );
76 0 : return ( config ? config->getServer() : 0 );
77 : }
78 :
79 : #ifdef EQUALIZER_USE_VRPN
80 : namespace
81 : {
82 : class MotionEvent
83 : {
84 : public:
85 : MotionEvent( const co::Object* object )
86 : : buffer( new co::BufferConnection )
87 : , command( co::Connections( 1, buffer ), fabric::CMD_CONFIG_EVENT,
88 : co::COMMANDTYPE_OBJECT, object->getID(),
89 : object->getInstanceID( ))
90 : {
91 : command << Event::OBSERVER_MOTION;
92 : }
93 :
94 : co::BufferConnectionPtr buffer;
95 : EventOCommand command;
96 : };
97 :
98 : void VRPN_CALLBACK trackerCB( void* userdata, const vrpn_TRACKERCB data )
99 : {
100 : if( data.sensor != 0 )
101 : return; // Only use first sensor
102 :
103 : eq::Matrix4f head( eq::Matrix4f::IDENTITY );
104 : const vmml::quaternion<float> quat( data.quat[0], data.quat[2],
105 : -data.quat[1], data.quat[3] );
106 : quat.get_rotation_matrix( head );
107 : head.set_translation( data.pos[0], data.pos[2], -data.pos[1] );
108 :
109 : Observer *observer = static_cast< Observer* >( userdata );
110 : Config* config = observer->getConfig();
111 :
112 : MotionEvent oEvent( config );
113 : oEvent.command << observer->getID() << head;
114 : oEvent.command.disable();
115 :
116 : ClientPtr client = config->getClient();
117 : co::Buffer buffer;
118 : buffer.swap( oEvent.buffer->getBuffer( ));
119 :
120 : co::ICommand iCommand( client, client, &buffer, false );
121 : EventICommand iEvent( iCommand );
122 : iEvent.get< uint128_t >(); // normally done by Config::handleEvent()
123 : observer->handleEvent( iEvent );
124 : }
125 : }
126 : #endif
127 :
128 8 : bool Observer::configInit()
129 : {
130 : #ifdef EQUALIZER_USE_VRPN
131 : const std::string& vrpnName = getVRPNTracker();
132 : if( !vrpnName.empty( ))
133 : {
134 : _impl->vrpnTracker = new vrpn_Tracker_Remote( vrpnName.c_str( ));
135 : if( _impl->vrpnTracker->register_change_handler(this, trackerCB) != -1 )
136 : return true;
137 :
138 : LBWARN << "VRPN tracker couldn't connect to device " << vrpnName
139 : << std::endl;
140 : delete _impl->vrpnTracker;
141 : _impl->vrpnTracker = 0;
142 : return false;
143 : }
144 : #endif
145 : #ifdef EQUALIZER_USE_OPENCV
146 : int32_t camera = getOpenCVCamera();
147 : if( camera == OFF )
148 : return true;
149 : if( camera == AUTO )
150 : camera = getPath().observerIndex;
151 : else
152 : --camera; // .eqc counts from 1, OpenCV from 0
153 :
154 : _impl->cvTracker = new detail::CVTracker( this, camera );
155 : if( _impl->cvTracker->isGood( ))
156 : return _impl->cvTracker->start();
157 :
158 : delete _impl->cvTracker;
159 : _impl->cvTracker = 0;
160 : return getOpenCVCamera() == AUTO; // not a failure for auto setting
161 : #endif
162 8 : return true;
163 : }
164 :
165 0 : bool Observer::handleEvent( EventICommand& command )
166 : {
167 0 : switch( command.getEventType( ))
168 : {
169 : case Event::OBSERVER_MOTION:
170 0 : return setHeadMatrix( command.read< Matrix4f >( ));
171 : }
172 0 : return false;
173 : }
174 :
175 8 : bool Observer::configExit()
176 : {
177 : #ifdef EQUALIZER_USE_VRPN
178 : if( _impl->vrpnTracker )
179 : {
180 : _impl->vrpnTracker->unregister_change_handler( this, trackerCB );
181 : delete _impl->vrpnTracker;
182 : _impl->vrpnTracker = 0;
183 : }
184 : #endif
185 : #ifdef EQUALIZER_USE_OPENCV
186 : delete _impl->cvTracker;
187 : _impl->cvTracker = 0;
188 : #endif
189 8 : return true;
190 : }
191 :
192 5 : void Observer::frameStart( const uint32_t /*frame*/ )
193 : {
194 : #ifdef EQUALIZER_USE_VRPN
195 : if( _impl->vrpnTracker )
196 : _impl->vrpnTracker->mainloop();
197 : #endif
198 5 : }
199 :
200 : }
201 :
202 : #include "../fabric/observer.ipp"
203 : template class eq::fabric::Observer< eq::Config, eq::Observer >;
204 :
205 : /** @cond IGNORE */
206 : template EQFABRIC_API std::ostream& eq::fabric::operator << ( std::ostream&,
207 36 : const eq::fabric::Observer< eq::Config, eq::Observer >& );
208 : /** @endcond */
|