@@ -62,8 +62,21 @@ Canvas3D::Canvas3D() : i_model_loading(0), stop_model_load_thread(false)
62
62
});
63
63
64
64
set_can_focus (true );
65
+ animators.push_back (&azimuth_animator);
66
+ animators.push_back (&elevation_animator);
67
+ animators.push_back (&zoom_animator);
68
+ animators.push_back (&cx_animator);
69
+ animators.push_back (&cy_animator);
65
70
}
66
71
72
+ void Canvas3D::set_msd_params (const MSD::Params ¶ms)
73
+ {
74
+ for (auto anim : animators) {
75
+ anim->set_params (params);
76
+ }
77
+ }
78
+
79
+
67
80
glm::vec2 Canvas3D::get_center_shift (const glm::vec2 &shift) const
68
81
{
69
82
return glm::rotate (glm::mat2 (1 , 0 , 0 , sin (glm::radians (cam_elevation))) * shift * 0 .1218f * cam_distance / 105 .f ,
@@ -83,7 +96,8 @@ void Canvas3D::on_size_allocate(Gtk::Allocation &alloc)
83
96
height = alloc.get_height ();
84
97
needs_resize = true ;
85
98
if (needs_view_all) {
86
- view_all ();
99
+ Canvas3DBase::view_all (); // don't use animation
100
+ queue_draw ();
87
101
needs_view_all = false ;
88
102
}
89
103
@@ -192,36 +206,13 @@ void Canvas3D::rotate_gesture_update_cb(GdkEventSequence *seq)
192
206
auto delta = gesture_rotate->get_angle_delta ();
193
207
if (cam_elevation < 0 )
194
208
delta *= -1 ;
195
- cam_azimuth = gesture_rotate_cam_azimuth_orig + glm::degrees (delta);
196
- inc_cam_azimuth (0 );
209
+ set_cam_azimuth (gesture_rotate_cam_azimuth_orig + glm::degrees (delta));
197
210
double cx, cy;
198
211
gesture_rotate->get_bounding_box_center (cx, cy);
199
212
auto dy = cy - gesture_rotate_pos_orig.y ;
200
213
set_cam_elevation (gesture_rotate_cam_elevation_orig + (dy / height) * 180 );
201
214
}
202
215
203
- int Canvas3D::zoom_animate_step (GdkFrameClock *frame_clock)
204
- {
205
- const auto r = zoom_animator.step (gdk_frame_clock_get_frame_time (frame_clock) / 1e6 );
206
-
207
- auto s = zoom_animator.get_s ();
208
-
209
- set_cam_distance (zoom_animation_cam_dist_orig * pow (1.5 , s));
210
-
211
- if (!r) // should stop
212
- return G_SOURCE_REMOVE;
213
- else
214
- return G_SOURCE_CONTINUE;
215
- }
216
-
217
- int Canvas3D::zoom_tick_cb (GtkWidget *cwidget, GdkFrameClock *frame_clock, gpointer user_data)
218
- {
219
- Gtk::Widget *widget = Glib::wrap (cwidget);
220
- auto canvas = dynamic_cast <Canvas3D *>(widget);
221
- return canvas->zoom_animate_step (frame_clock);
222
- }
223
-
224
-
225
216
bool Canvas3D::on_scroll_event (GdkEventScroll *scroll_event)
226
217
{
227
218
auto *dev = gdk_event_get_source_device ((GdkEvent *)scroll_event);
@@ -265,6 +256,20 @@ void Canvas3D::pan_rotate(GdkEventScroll *scroll_event)
265
256
set_cam_azimuth (get_cam_azimuth () - delta.x * 9 );
266
257
set_cam_elevation (get_cam_elevation () - delta.y * 9 );
267
258
}
259
+
260
+
261
+ static const float zoom_base = 1.5 ;
262
+
263
+ static float cam_dist_to_anim (float d)
264
+ {
265
+ return log (d) / log (zoom_base);
266
+ }
267
+
268
+ static float cam_dist_from_anim (float d)
269
+ {
270
+ return pow (zoom_base, d);
271
+ }
272
+
268
273
void Canvas3D::pan_zoom (GdkEventScroll *scroll_event)
269
274
{
270
275
float inc = 0 ;
@@ -286,27 +291,127 @@ void Canvas3D::pan_zoom(GdkEventScroll *scroll_event)
286
291
if (smooth_zoom) {
287
292
if (inc == 0 )
288
293
return ;
289
- if (!zoom_animator.is_running ()) {
290
- zoom_animator.start ();
291
- zoom_animation_cam_dist_orig = cam_distance;
292
- gtk_widget_add_tick_callback (GTK_WIDGET (gobj ()), &zoom_tick_cb, nullptr , nullptr );
293
- }
294
+ start_anim ();
294
295
zoom_animator.target += inc;
295
296
}
296
297
else {
297
- set_cam_distance (cam_distance * pow (1.5 , inc));
298
+ set_cam_distance (cam_distance * pow (zoom_base, inc));
299
+ }
300
+ }
301
+
302
+ int Canvas3D::animate_step (GdkFrameClock *frame_clock)
303
+ {
304
+ bool stop = true ;
305
+ for (auto anim : animators) {
306
+ if (anim->step (gdk_frame_clock_get_frame_time (frame_clock) / 1e6 ))
307
+ stop = false ;
308
+ }
309
+
310
+ set_cam_azimuth (azimuth_animator.get_s ());
311
+ set_cam_elevation (elevation_animator.get_s ());
312
+ set_cam_distance (cam_dist_from_anim (zoom_animator.get_s ()));
313
+ set_center ({cx_animator.get_s (), cy_animator.get_s ()});
314
+
315
+ if (stop)
316
+ return G_SOURCE_REMOVE;
317
+ else
318
+ return G_SOURCE_CONTINUE;
319
+ }
320
+
321
+ int Canvas3D::anim_tick_cb (GtkWidget *cwidget, GdkFrameClock *frame_clock, gpointer user_data)
322
+ {
323
+ Gtk::Widget *widget = Glib::wrap (cwidget);
324
+ auto canvas = dynamic_cast <Canvas3D *>(widget);
325
+ return canvas->animate_step (frame_clock);
326
+ }
327
+
328
+
329
+ void Canvas3D::start_anim ()
330
+ {
331
+ const bool was_stopped = !std::any_of (animators.begin (), animators.end (), [](auto x) { return x->is_running (); });
332
+
333
+ if (!azimuth_animator.is_running ())
334
+ azimuth_animator.start (cam_azimuth);
335
+
336
+ if (!elevation_animator.is_running ())
337
+ elevation_animator.start (cam_elevation);
338
+
339
+ if (!zoom_animator.is_running ())
340
+ zoom_animator.start (cam_dist_to_anim (cam_distance));
341
+
342
+ if (!cx_animator.is_running ())
343
+ cx_animator.start (center.x );
344
+
345
+ if (!cy_animator.is_running ())
346
+ cy_animator.start (center.y );
347
+
348
+ if (was_stopped)
349
+ gtk_widget_add_tick_callback (GTK_WIDGET (gobj ()), &Canvas3D::anim_tick_cb, nullptr , nullptr );
350
+ }
351
+
352
+ void Canvas3D::animate_to_azimuth_elevation_abs (float az, float el)
353
+ {
354
+ if (!smooth_zoom) {
355
+ set_cam_azimuth (az);
356
+ set_cam_elevation (el);
357
+ return ;
298
358
}
359
+ start_anim ();
360
+
361
+ azimuth_animator.target = az;
362
+ elevation_animator.target = el;
363
+ }
364
+
365
+ void Canvas3D::animate_to_azimuth_elevation_rel (float az, float el)
366
+ {
367
+ if (!smooth_zoom) {
368
+ set_cam_azimuth (get_cam_azimuth () + az);
369
+ set_cam_elevation (get_cam_elevation () + el);
370
+ return ;
371
+ }
372
+ start_anim ();
373
+
374
+ azimuth_animator.target += az;
375
+ elevation_animator.target += el;
299
376
}
300
377
301
- void Canvas3D::inc_cam_azimuth ( float v )
378
+ void Canvas3D::animate_zoom_step ( int inc )
302
379
{
303
- set_cam_azimuth (get_cam_azimuth () + v);
380
+ if (!smooth_zoom) {
381
+ set_cam_distance (get_cam_distance () * pow (zoom_base, inc));
382
+ return ;
383
+ }
384
+ start_anim ();
385
+
386
+ zoom_animator.target += inc;
387
+ }
388
+
389
+ void Canvas3D::animate_center_rel (const glm::vec2 &d)
390
+ {
391
+ if (!smooth_zoom) {
392
+ set_center (get_center () + d);
393
+ return ;
394
+ }
395
+ start_anim ();
396
+ cx_animator.target += d.x ;
397
+ cy_animator.target += d.y ;
304
398
}
305
399
306
400
void Canvas3D::view_all ()
307
401
{
308
- Canvas3DBase::view_all ();
309
- queue_draw ();
402
+ if (!smooth_zoom) {
403
+ Canvas3DBase::view_all ();
404
+ queue_draw ();
405
+ return ;
406
+ }
407
+ if (const auto p = get_view_all_params ()) {
408
+ start_anim ();
409
+ azimuth_animator.target = p->cam_azimuth ;
410
+ elevation_animator.target = p->cam_elevation ;
411
+ zoom_animator.target = cam_dist_to_anim (p->cam_distance );
412
+ cx_animator.target = p->cx ;
413
+ cy_animator.target = p->cy ;
414
+ }
310
415
}
311
416
312
417
void Canvas3D::request_push ()
0 commit comments