44 const float wheelFactor = 1.f / 40.f;
54 , _engine(api->getEngine())
55 , _appParams{api->getParametersManager().getApplicationParameters()}
56 , _params(std::move(params))
65 _params.getPropertyMap().merge(prop);
66 _params.markModified();
67 _engine.triggerRender();
81 _handleDeflectEvents();
95 _sendDeflectFrame(_engine);
101 std::vector<char>
data;
119 if (_stream->registerForEvents())
120 _setupSocketListener();
122 CORE_ERROR(
"Deflect failed to register for events!");
124 _params.
setId(_stream->getId());
125 _params.
setHost(_stream->getHost());
143 CORE_INFO(
"Deflect successfully connected to Tide on host " << _stream->getHost());
145 catch (
const std::runtime_error& ex)
147 CORE_ERROR(
"Deflect failed to initialize. " << ex.what());
158 #ifdef USE_NETWORKING
168 void _setupSocketListener()
170 #ifdef USE_NETWORKING
171 assert(_stream->isConnected());
173 auto loop = uvw::Loop::getDefault();
174 _pollHandle = loop->resource<uvw::PollHandle>(_stream->getDescriptor());
176 _pollHandle->on<uvw::PollEvent>([&engine = _engine](
const auto&,
auto&) { engine.triggerRender(); });
178 _pollHandle->start(uvw::PollHandle::Event::READABLE);
180 _stream->setDisconnectedCallback(
189 void _handleDeflectEvents()
193 while (_stream->hasEvent())
195 const deflect::Event&
event = _stream->getEvent();
198 case deflect::Event::EVT_PRESS:
199 _previousPos = _getWindowPos(event, windowSize);
200 _pan = _pinch =
false;
202 case deflect::Event::EVT_MOVE:
203 case deflect::Event::EVT_RELEASE:
205 const auto pos = _getWindowPos(event, windowSize);
206 if (!_pan && !_pinch)
207 cameraManipulator.dragLeft(pos, _previousPos);
209 _pan = _pinch =
false;
212 case deflect::Event::EVT_PAN:
216 const auto pos = _getWindowPos(event, windowSize);
217 cameraManipulator.dragMiddle(pos, _previousPos);
222 case deflect::Event::EVT_PINCH:
226 const auto pos = _getWindowPos(event, windowSize);
227 const auto delta = _getZoomDelta(event, windowSize);
228 cameraManipulator.wheel(pos, delta * wheelFactor);
232 case deflect::Event::EVT_KEY_PRESS:
237 case deflect::Event::EVT_VIEW_SIZE_CHANGED:
244 case deflect::Event::EVT_CLOSE:
256 void _sendSizeHints()
259 if (frameBuffers.empty())
264 auto sizeHints = deflect::SizeHints();
265 sizeHints.maxWidth = std::numeric_limits<unsigned int>::max();
266 sizeHints.maxHeight = std::numeric_limits<unsigned int>::max();
267 sizeHints.minWidth = minSize.x;
268 sizeHints.minHeight = minSize.y;
273 Vector2ui preferredSize = frameBuffers[0]->getSize();
274 for (
auto frameBuffer : frameBuffers)
278 preferredSize = {0, 0};
283 sizeHints.preferredWidth = preferredSize.x;
284 sizeHints.preferredHeight = preferredSize.y;
285 _stream->sendSizeHints(sizeHints);
288 void _sendDeflectFrame(Engine& engine)
290 const bool error = _waitOnFutures();
294 if (!_stream->isConnected())
306 const auto& frameBuffers = engine.getFrameBuffers();
307 for (
size_t i = 0; i < frameBuffers.size(); ++i)
309 auto frameBuffer = frameBuffers[i];
311 if (frameBuffer->getColorBuffer())
313 const deflect::View view =
utils::getView(frameBuffer->getName());
316 if (i <= _lastImages.size())
317 _lastImages.push_back({});
318 auto& image = _lastImages[i];
319 _copyToImage(image, *frameBuffer);
320 _futures.push_back(_sendImage(image, view, channel));
322 frameBuffer->unmap();
324 _futures.push_back(
static_cast<deflect::Stream&
>(*_stream).finishFrame());
327 void _copyToImage(Image& image, FrameBuffer& frameBuffer)
329 const auto& size = frameBuffer.getSize();
330 const size_t bufferSize = size.x * size.y * frameBuffer.getColorDepth();
331 const auto data = frameBuffer.getColorBuffer();
333 image.data.resize(bufferSize);
334 memcpy(image.data.data(),
data, bufferSize);
336 image.format = frameBuffer.getFrameBufferFormat();
339 deflect::Stream::Future _sendImage(
const Image& image,
const deflect::View& view,
const uint8_t channel)
341 const auto format = _getDeflectImageFormat(image.format);
343 deflect::ImageWrapper deflectImage(image.data.data(), image.size.x, image.size.y, format);
345 deflectImage.view = view;
346 deflectImage.channel = channel;
347 deflectImage.compressionQuality = _params.
getQuality();
348 deflectImage.compressionPolicy = _params.
getCompression() ? deflect::COMPRESSION_ON : deflect::COMPRESSION_OFF;
349 deflectImage.rowOrder = _params.
isTopDown() ? deflect::RowOrder::top_down : deflect::RowOrder::bottom_up;
352 return static_cast<deflect::Stream&
>(*_stream).send(deflectImage);
355 deflect::PixelFormat _getDeflectImageFormat(
const FrameBufferFormat format)
const
360 return deflect::BGRA;
364 return deflect::RGBA;
368 Vector2d _getWindowPos(
const deflect::Event& event,
const Vector2ui& windowSize)
const
370 return {
event.mouseX * windowSize.x,
event.mouseY * windowSize.y};
373 double _getZoomDelta(
const deflect::Event& pinchEvent,
const Vector2ui& windowSize)
const
375 const auto dx = pinchEvent.dx * windowSize.x;
376 const auto dy = pinchEvent.dy * windowSize.y;
377 return std::copysign(std::sqrt(dx * dx + dy * dy), dx + dy);
380 bool _waitOnFutures()
383 for (
auto& future : _futures)
394 ApplicationParameters& _appParams;
395 DeflectParameters _params;
399 std::unique_ptr<deflect::Observer> _stream;
400 std::vector<Image> _lastImages;
401 std::vector<deflect::Stream::Future> _futures;
403 #ifdef USE_NETWORKING
404 std::shared_ptr<uvw::PollHandle> _pollHandle;
409 : _params(std::move(params))
415 _impl = std::make_shared<Impl>(
_api, std::move(_params));
core::ExtensionPlugin * brayns_plugin_create(const int argc, const char **argv)
void setWindowSize(const Vector2ui &size)
const Vector2ui getWindowSize() const
unsigned getQuality() const
std::string getHostname() const
bool isResizingEnabled() const
const PropertyMap & getPropertyMap() const
void setHost(const std::string &host)
std::string getId() const
void setId(const std::string &id)
deflect::ChromaSubsampling getChromaSubsampling() const
void setEnabled(const bool enabled)
bool getCompression() const
Impl(PluginAPI *api, DeflectParameters &¶ms)
DeflectPlugin(DeflectParameters &¶ms)
PLATFORM_API const std::vector< FrameBufferPtr > & getFrameBuffers() const
Returns all registered frame buffers that are used during rendering.
virtual PLATFORM_API Vector2ui getMinimumFrameSize() const =0
Returns the minimum frame size in pixels supported by this engine.
void handleKeyboardShortcut(const unsigned char key)
Handles a keyboard shortcut.
virtual ActionInterface * getActionInterface()=0
virtual KeyboardHandler & getKeyboardHandler()=0
virtual AbstractManipulator & getCameraManipulator()=0
bool parse(int argc, const char **argv)
deflect::View getView(const std::string &name)
uint8_t getChannel(const std::string &name)
bool needsReset(const deflect::Observer &stream, const DeflectParameters ¶ms)
glm::vec< 2, double > Vector2d
glm::vec< 2, uint32_t > Vector2ui