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