4 #include "scenewindow.h" 6 #include "../annotations/scene.h" 7 #include "../core/bagplayer.h" 8 #include "../core/topic.h" 9 #include "../core/workspace.h" 10 #include "../displays/mesh.h" 11 #include "../render/resource.h" 12 #include "../render/shader.h" 13 #include "../render/transformations.h" 14 #include "../render/uniformbuffer.h" 16 SceneWindow::SceneWindow()
22 button->setText(
"Annotate");
23 button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
24 QMenu *menu =
new QMenu(
this);
25 button->setMenu(menu);
26 addToolWidget(button);
27 for (
auto &type : Type::find<SceneAnnotationBase>()->list()) {
28 if (!type->constructable()) {
31 QString label = type->name().c_str();
32 label = label.replace(
"SceneAnnotation",
"");
33 connect(menu->addAction(label), &QAction::triggered,
this,
34 [type, label, button,
this](
bool checked) {
39 auto timeline = ws->document()->timeline();
43 double current_time = ws->player->time();
44 std::shared_ptr<AnnotationTrack> current_track =
45 ws->currentAnnotationTrack().resolve(ws());
47 for (
auto &track_base : timeline->tracks()) {
48 if (
auto track = std::dynamic_pointer_cast<AnnotationTrack>(
50 if (
auto branch = track->branch(ws(),
false)) {
51 for (
auto &span : branch->spans()) {
52 if (span->start() <= current_time &&
53 span->start() + span->duration() >=
55 current_track = track;
67 for (
auto &track_base : timeline->tracks()) {
68 if (
auto track = std::dynamic_pointer_cast<AnnotationTrack>(
70 current_track = track;
76 timeline->tracks().push_back(
77 current_track = std::make_shared<AnnotationTrack>());
79 ws->currentAnnotationTrack() = current_track;
80 std::shared_ptr<AnnotationSpan> current_span;
81 if (
auto branch = current_track->branch(ws(),
false)) {
82 for (
auto &span : branch->spans()) {
83 if (span->start() <= current_time &&
84 span->start() + span->duration() >= current_time) {
90 if (current_span ==
nullptr) {
91 current_span = std::make_shared<AnnotationSpan>();
92 current_span->start() = current_time;
93 current_span->duration() = 0.1;
94 current_track->branch(ws(),
true)
96 .push_back(current_span);
99 current_span->annotations().push_back(annotation);
106 void SceneWindow::updateViewMatrix() {
109 lookatMatrix(viewPosition(), viewTarget(), Eigen::Vector3d::UnitZ());
110 _camera_block.view_matrix = _view_matrix.cast<
float>();
116 _bgcolor = ws->document()->display()->backgroundColor().toLinearVector4f();
119 float far = (100.0 + (viewPosition() - viewTarget()).norm() * 2.0);
120 float near = far * 0.0001f;
121 _projection_matrix = projectionMatrix(1.0, _height * 1.0 / _width, near, far);
122 _camera_block.projection_matrix = _projection_matrix.cast<
float>();
124 _multi_sampling = ws->document()->display()->rendering()->multiSampling();
126 _camera_block.flags = 0;
127 switch (ws->document()->display()->rendering()->sampleShading()) {
129 _camera_block.flags |= CameraBlock::SampleShadingFlag;
132 _camera_block.flags |= CameraBlock::SampleShadingFlag;
133 _camera_block.flags |= CameraBlock::TransparentSampleShadingFlag;
139 renderTarget().update(_width, _height, _multi_sampling);
140 renderTarget().bind();
141 V_GL(glViewport(0, 0, _width, _height));
142 V_GL(glClearColor(_bgcolor.x(), _bgcolor.y(), _bgcolor.z(), _bgcolor.w()));
143 V_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
144 if (!_action_queue.empty()) {
145 std::lock_guard<std::mutex> lock(_action_mutex);
146 for (
auto &a : _action_queue) {
150 _action_queue.clear();
153 context.renderer->render(renderTarget(), _camera_block, *context.render_list);
156 void SceneWindow::composite(
int target) { renderTarget().present(target); }
158 void SceneWindow::pushAction(
160 const std::string &tag) {
161 std::lock_guard<std::mutex> lock(_action_mutex);
162 if (!tag.empty() && _action_tag == tag) {
163 _action_queue.pop_back();
166 _action_queue.push_back(action);
169 void SceneWindow::handleEvent(QEvent *event) {
171 switch (event->type()) {
172 case QEvent::Wheel: {
175 auto *wheel =
static_cast<QWheelEvent *
>(event);
176 double degrees = wheel->angleDelta().y() * (1.0 / 8);
177 double exponent = degrees / 90;
178 double factor = std::pow(0.5, exponent);
179 viewPosition() = (viewPosition() - viewTarget()) * factor + viewTarget();
181 GlobalEvents::instance()->redraw();
184 case QEvent::MouseButtonPress: {
186 auto *mouse =
static_cast<QMouseEvent *
>(event);
189 _mouse_position = mouse->pos();
190 _mouse_buttons = mouse->buttons();
191 GlobalEvents::instance()->redraw();
193 if (mouse->button() == Qt::LeftButton) {
194 _left_dragged =
false;
198 auto pick_result = context.renderer->pick(
199 renderTarget(), _camera_block, *context.render_list, x,
200 (
int)renderTarget()._height - 1 - y);
201 _pick_depth = pick_result.depth;
202 _pick_id = pick_result.id;
205 _picked = ws->document()->display();
206 if (pick_result.id) {
208 ws->document()->display()->recurse(
209 [&](
const std::shared_ptr<Display> &display) {
210 if (display->pick(pick_result.id)) {
211 LOG_DEBUG(
"pick Display");
217 if (ws->player && ws->document()->timeline()) {
218 auto current_time = ws->player->time();
219 for (
auto &track : ws->document()->timeline()->tracks()) {
220 if (
auto annotation_track =
221 std::dynamic_pointer_cast<AnnotationTrack>(track)) {
222 if (
auto branch = annotation_track->branch(ws(),
false)) {
223 for (
auto &span : branch->spans()) {
224 if (span->start() <= current_time &&
225 span->start() + span->duration() >= current_time) {
226 for (
auto &annotation : span->annotations()) {
227 if (
auto scene_annotation = std::dynamic_pointer_cast<
229 if (scene_annotation->pick(pick_result.id)) {
230 LOG_DEBUG(
"pick SceneAnnotationBase");
231 _picked = scene_annotation;
244 GlobalEvents::instance()->redraw();
248 case QEvent::MouseButtonRelease: {
250 auto *mouse =
static_cast<QMouseEvent *
>(event);
251 if (mouse->button() == Qt::LeftButton && !_left_dragged) {
252 auto modifiers = mouse->modifiers();
254 auto picked = _picked.lock();
255 startOnMainThreadAsync([picked, modifiers]() {
257 auto s = ws->selection();
258 LOG_DEBUG(
"modifiers " << modifiers);
259 if ((modifiers & Qt::ShiftModifier) == Qt::ShiftModifier) {
261 }
else if ((modifiers & Qt::ControlModifier) == Qt::ControlModifier) {
266 if (s != ws->selection()) {
273 GlobalEvents::instance()->redraw();
277 case QEvent::MouseMove: {
278 auto *mouse =
static_cast<QMouseEvent *
>(event);
279 if (event->type() == QEvent::MouseMove && mouse->buttons() != 0 &&
280 mouse->buttons() == _mouse_buttons) {
281 if (mouse->buttons() == Qt::LeftButton) {
282 _left_dragged =
true;
284 if (mouse->buttons() == Qt::RightButton) {
287 QPoint d = mouse->pos() - _mouse_position;
288 double meters_per_pixel = (viewTarget() - viewPosition()).norm() /
289 std::sqrt(1.0 * width() * height());
290 double dx = d.x() * meters_per_pixel;
291 double dy = d.y() * meters_per_pixel;
292 Eigen::Vector3d mx = (viewTarget() - viewPosition())
293 .cross(Eigen::Vector3d::UnitZ())
296 Eigen::Vector3d my = (viewTarget() - viewPosition())
297 .cross(Eigen::Vector3d::UnitZ())
298 .cross(viewTarget() - viewPosition())
301 viewTarget() += mx + my;
302 viewPosition() += mx + my;
303 if (event->type() == QEvent::MouseButtonRelease) {
306 GlobalEvents::instance()->redraw();
308 if (mouse->buttons() == Qt::MiddleButton) {
311 QPoint d = mouse->pos() - _mouse_position;
312 double exponent = d.y() * 0.01;
313 double factor = std::pow(0.5, exponent);
315 (viewPosition() - viewTarget()) * factor + viewTarget();
316 if (event->type() == QEvent::MouseButtonRelease) {
319 GlobalEvents::instance()->redraw();
322 _mouse_position = mouse->pos();
326 if (((event->type() == QEvent::MouseButtonPress ||
327 event->type() == QEvent::MouseButtonDblClick) &&
328 (static_cast<QMouseEvent *>(event)->button() == Qt::LeftButton)) ||
329 ((
event->type() == QEvent::MouseMove) &&
330 (static_cast<QMouseEvent *>(event)->buttons() & Qt::LeftButton)) ||
331 ((
event->type() == QEvent::MouseButtonRelease) &&
332 (static_cast<QMouseEvent *>(event)->button() == Qt::LeftButton))) {
333 auto *mouse =
static_cast<QMouseEvent *
>(event);
334 int event_x = mouse->x();
335 int event_y = mouse->y();
336 int event_type =
event->type();
339 [event_type, event_x, event_y,
343 if (event_type == QEvent::MouseButtonPress) {
345 _interaction.id = _pick_id;
347 _interaction.current.view_matrix = _view_matrix;
348 _interaction.current.projection_matrix = _projection_matrix;
349 _interaction.current.x = event_x;
350 _interaction.current.y = event_y;
351 _interaction.current.center = viewPosition();
353 _interaction.current.x * 2.0 / renderWidth() - 1.0,
354 1.0 - _interaction.current.y * 2.0 / renderHeight(),
355 _pick_depth * 2 - 1, 1.0);
357 (_camera_block.projection_matrix * _camera_block.view_matrix)
361 _interaction.current.direction =
362 (q.head(3) / q.w() - _interaction.current.center);
363 _interaction.current.point =
364 _interaction.current.center + _interaction.current.direction;
366 if (event_type == QEvent::MouseButtonPress ||
367 event_type == QEvent::MouseButtonDblClick) {
368 _interaction.begin = _interaction.current;
369 _interaction.previous = _interaction.current;
371 _interaction.pressed = (event_type == QEvent::MouseButtonPress ||
372 event_type == QEvent::MouseButtonDblClick);
373 _interaction.finished = (event_type == QEvent::MouseButtonRelease);
374 bool interactive =
false;
375 if (
auto picked = _picked.lock()) {
376 if (
auto p = std::dynamic_pointer_cast<Display>(picked)) {
377 LOG_DEBUG(
"Display::interact");
378 interactive = p->interact(_interaction);
381 std::dynamic_pointer_cast<SceneAnnotationBase>(picked)) {
382 LOG_DEBUG(
"SceneAnnotationBase::interact");
383 interactive = p->interact(_interaction);
385 if (_interaction.finished) {
390 interact(_interaction);
392 if (_interaction.finished) {
393 startOnMainThreadAsync([]() {
LockScope()->modified(); });
395 _interaction.previous = _interaction.current;
396 GlobalEvents::instance()->redraw();
398 (event_type == QEvent::MouseMove) ?
"move" :
"");
399 GlobalEvents::instance()->redraw();
404 void SceneWindow::interact(
const Interaction &interaction) {
406 QPoint d(interaction.current.x - interaction.previous.x,
407 interaction.current.y - interaction.previous.y);
408 double degrees_per_pixel = 0.25;
409 double f = degrees_per_pixel * M_PI / 180.0;
410 double dx = d.x() * f;
411 double dy = d.y() * f;
412 viewPosition() -= viewTarget();
414 Eigen::AngleAxisd(-dx, Eigen::Vector3d::UnitZ()) * viewPosition();
415 double pitch = std::max(
417 std::min(M_PI * 0.499, std::asin(viewPosition().normalized().z()) + dy));
418 double distance = std::max(0.01, viewPosition().norm());
419 viewPosition() = ((viewPosition().array() * Eigen::Vector3d(1, 1, 0).array())
423 Eigen::Vector3d(0, 0, std::sin(pitch))) *
425 viewPosition() += viewTarget();
428 void SceneWindow::paintHUD(QPainter *painter) {
429 if (LoaderThread::instance()->count() > 0) {
430 static auto font = []() {
432 font.setPixelSize(32);
435 static auto text = []() {
436 QStaticText text(
"Loading...");
437 text.setPerformanceHint(QStaticText::AggressiveCaching);
438 text.prepare(QTransform(), font);
443 painter->fillRect(_width - padding_x * 2 - text.size().width(), 0,
444 padding_x * 2 + text.size().width(),
445 padding_y * 2 + text.size().height(),
446 QBrush(QColor(0, 0, 0, 150)));
447 painter->setPen(QPen(QBrush(Qt::white), 0));
448 painter->drawStaticText(_width - padding_x - text.size().width(), padding_y,