Line data Source code
1 :
2 : /* Copyright (c) 2009-2016, 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 "eventICommand.h"
23 : #include "server.h"
24 :
25 : #include <eq/fabric/event.h>
26 : #include <eq/fabric/paths.h>
27 : #include <eq/fabric/commands.h>
28 : #include <co/bufferConnection.h>
29 : #include <vmmlib/quaternion.hpp>
30 :
31 : #ifdef EQUALIZER_USE_OPENCV
32 : # include "detail/cvTracker.h"
33 : #endif
34 : #ifdef EQUALIZER_USE_VRPN
35 : # include <vrpn_Tracker.h>
36 : # include <co/buffer.h>
37 : #else
38 : class vrpn_Tracker_Remote;
39 : #endif
40 :
41 :
42 : namespace eq
43 : {
44 : namespace detail
45 : {
46 : class CVTracker;
47 :
48 : class Observer
49 : {
50 : public:
51 2 : Observer()
52 : : vrpnTracker( 0 )
53 2 : , cvTracker( 0 )
54 2 : {}
55 :
56 : vrpn_Tracker_Remote *vrpnTracker;
57 : CVTracker* cvTracker;
58 : };
59 : }
60 :
61 : typedef fabric::Observer< Config, Observer > Super;
62 :
63 2 : Observer::Observer( Config* parent )
64 : : Super( parent )
65 2 : , _impl( new detail::Observer )
66 2 : {}
67 :
68 6 : Observer::~Observer()
69 : {
70 2 : delete _impl;
71 4 : }
72 :
73 0 : ServerPtr Observer::getServer()
74 : {
75 0 : Config* config = getConfig();
76 0 : LBASSERT( config );
77 0 : return ( config ? config->getServer() : 0 );
78 : }
79 :
80 : #ifdef EQUALIZER_USE_VRPN
81 : namespace
82 : {
83 0 : class MotionEvent
84 : {
85 : public:
86 0 : MotionEvent( const co::Object* object )
87 0 : : buffer( new co::BufferConnection )
88 : , command( co::Connections( 1, buffer ), fabric::CMD_CONFIG_EVENT,
89 0 : co::COMMANDTYPE_OBJECT, object->getID(),
90 0 : object->getInstanceID( ))
91 : {
92 0 : command << Event::OBSERVER_MOTION;
93 0 : }
94 :
95 : co::BufferConnectionPtr buffer;
96 : EventOCommand command;
97 : };
98 :
99 0 : void VRPN_CALLBACK trackerCB( void* userdata, const vrpn_TRACKERCB data )
100 : {
101 0 : if( data.sensor != 0 )
102 0 : return; // Only use first sensor
103 :
104 0 : const Matrix4f head( Quaternionf( data.quat[0], data.quat[1],
105 0 : data.quat[2], data.quat[3] ),
106 0 : Vector3f( data.pos[0], data.pos[1], data.pos[2] ));
107 0 : Observer *observer = static_cast< Observer* >( userdata );
108 0 : Config* config = observer->getConfig();
109 :
110 : // Directly dispatch the event: We're called from Config::startFrame and
111 : // need to process now without sending the event so that the change is
112 : // committed and takes effect for this frame.
113 0 : MotionEvent oEvent( config );
114 0 : oEvent.command << observer->getID() << head;
115 0 : oEvent.command.disable();
116 :
117 0 : ClientPtr client = config->getClient();
118 0 : co::Buffer buffer;
119 0 : buffer.swap( oEvent.buffer->getBuffer( ));
120 :
121 0 : co::ICommand iCommand( client, client, &buffer, false );
122 0 : EventICommand iEvent( iCommand );
123 0 : config->handleEvent( iEvent ); // config dispatch so app can update state
124 : }
125 : }
126 : #endif
127 :
128 1 : bool Observer::configInit()
129 : {
130 : #ifdef EQUALIZER_USE_VRPN
131 1 : const std::string& vrpnName = getVRPNTracker();
132 1 : if( !vrpnName.empty( ))
133 : {
134 0 : _impl->vrpnTracker = new vrpn_Tracker_Remote( vrpnName.c_str( ));
135 0 : if( _impl->vrpnTracker->register_change_handler(this, trackerCB) != -1 )
136 0 : return true;
137 :
138 0 : LBWARN << "VRPN tracker couldn't connect to device " << vrpnName
139 0 : << std::endl;
140 0 : delete _impl->vrpnTracker;
141 0 : _impl->vrpnTracker = 0;
142 0 : 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 1 : 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 0 : bool Observer::configExit()
176 : {
177 : #ifdef EQUALIZER_USE_VRPN
178 0 : if( _impl->vrpnTracker )
179 : {
180 0 : _impl->vrpnTracker->unregister_change_handler( this, trackerCB );
181 0 : delete _impl->vrpnTracker;
182 0 : _impl->vrpnTracker = 0;
183 : }
184 : #endif
185 : #ifdef EQUALIZER_USE_OPENCV
186 : delete _impl->cvTracker;
187 : _impl->cvTracker = 0;
188 : #endif
189 0 : return true;
190 : }
191 :
192 0 : void Observer::frameStart( const uint32_t /*frame*/ )
193 : {
194 : #ifdef EQUALIZER_USE_VRPN
195 0 : if( _impl->vrpnTracker )
196 0 : _impl->vrpnTracker->mainloop();
197 : #endif
198 0 : }
199 :
200 : }
201 :
202 : #include <eq/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 42 : const eq::fabric::Observer< eq::Config, eq::Observer >& );
208 : /** @endcond */
|