diff options
author | Julian Eisel <julian@blender.org> | 2020-03-17 22:20:55 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2020-03-17 23:42:44 +0300 |
commit | dc2df8307f41888bab722f75fa9e73adecf86b72 (patch) | |
tree | f83c54f43e27a07e9cb9fed306d79b08864f29f2 /source/blender/editors/space_view3d/view3d_edit.c | |
parent | 406bfd43040a5526702b51f88f1491cb61aecedb (diff) |
VR: Initial Virtual Reality support - Milestone 1, Scene Inspection
NOTE: While most of the milestone 1 goals are there, a few smaller features and
improvements are still to be done.
Big picture of this milestone: Initial, OpenXR-based virtual reality support
for users and foundation for advanced use cases.
Maniphest Task: https://developer.blender.org/T71347
The tasks contains more information about this milestone.
To be clear: This is not a feature rich VR implementation, it's focused on the
initial scene inspection use case. We intentionally focused on that, further
features like controller support are part of the next milestone.
- How to use?
Instructions on how to use this are here:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/How_to_Test
These will be updated and moved to a more official place (likely the manual) soon.
Currently Windows Mixed Reality and Oculus devices are usable. Valve/HTC
headsets don't support the OpenXR standard yet and hence, do not work with this
implementation.
---------------
This is the C-side implementation of the features added for initial VR
support as per milestone 1. A "VR Scene Inspection" Add-on will be
committed separately, to expose the VR functionality in the UI. It also
adds some further features for milestone 1, namely a landmarking system
(stored view locations in the VR space)
Main additions/features:
* Support for rendering viewports to an HMD, with good performance.
* Option to sync the VR view perspective with a fully interactive,
regular 3D View (VR-Mirror).
* Option to disable positional tracking. Keeps the current position (calculated
based on the VR eye center pose) when enabled while a VR session is running.
* Some regular viewport settings for the VR view
* RNA/Python-API to query and set VR session state information.
* WM-XR: Layer tying Ghost-XR to the Blender specific APIs/data
* wmSurface API: drawable, non-window container (manages Ghost-OpenGL and GPU
context)
* DNA/RNA for management of VR session settings
* `--debug-xr` and `--debug-xr-time` commandline options
* Utility batch & config file for using the Oculus runtime on Windows.
* Most VR data is runtime only. The exception is user settings which are saved
to files (`XrSessionSettings`).
* VR support can be disabled through the `WITH_XR_OPENXR` compiler flag.
For architecture and code documentation, see
https://wiki.blender.org/wiki/Source/Interface/XR.
---------------
A few thank you's:
* A huge shoutout to Ray Molenkamp for his help during the project - it would
have not been that successful without him!
* Sebastian Koenig and Simeon Conzendorf for testing and feedback!
* The reviewers, especially Brecht Van Lommel!
* Dalai Felinto for pushing and managing me to get this done ;)
* The OpenXR working group for providing an open standard. I think we're the
first bigger application to adopt OpenXR. Congratulations to them and
ourselves :)
This project started as a Google Summer of Code 2019 project - "Core Support of
Virtual Reality Headsets through OpenXR" (see
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/).
Some further information, including ideas for further improvements can be found
in the final GSoC report:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/Final_Report
Differential Revisions: D6193, D7098
Reviewed by: Brecht Van Lommel, Jeroen Bakker
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_edit.c')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_edit.c | 130 |
1 files changed, 77 insertions, 53 deletions
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index a7136cc580c..68d5765e43d 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -85,6 +85,52 @@ enum { HAS_ROTATE = (1 << 0), }; +/* test for unlocked camera view in quad view */ +static bool view3d_camera_user_poll(bContext *C) +{ + View3D *v3d; + ARegion *region; + + if (ED_view3d_context_user_region(C, &v3d, ®ion)) { + RegionView3D *rv3d = region->regiondata; + if ((rv3d->persp == RV3D_CAMOB) && !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM)) { + return 1; + } + } + + return 0; +} + +static bool view3d_lock_poll(bContext *C) +{ + View3D *v3d = CTX_wm_view3d(C); + if (v3d) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (rv3d) { + return ED_view3d_offset_lock_check(v3d, rv3d); + } + } + return false; +} + +static bool view3d_pan_poll(bContext *C) +{ + if (ED_operator_region_view3d_active(C)) { + const RegionView3D *rv3d = CTX_wm_region_view3d(C); + return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION); + } + return false; +} + +static bool view3d_zoom_or_dolly_poll(bContext *C) +{ + if (ED_operator_region_view3d_active(C)) { + const RegionView3D *rv3d = CTX_wm_region_view3d(C); + return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY); + } + return false; +} + /* -------------------------------------------------------------------- */ /** \name Generic View Operator Properties * \{ */ @@ -935,7 +981,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) vod = op->customdata; /* poll should check but in some cases fails, see poll func for details */ - if (vod->rv3d->viewlock & RV3D_LOCKED) { + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) { viewops_data_free(C, op); return OPERATOR_PASS_THROUGH; } @@ -983,34 +1029,6 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) } } -/* test for unlocked camera view in quad view */ -static bool view3d_camera_user_poll(bContext *C) -{ - View3D *v3d; - ARegion *region; - - if (ED_view3d_context_user_region(C, &v3d, ®ion)) { - RegionView3D *rv3d = region->regiondata; - if (rv3d->persp == RV3D_CAMOB) { - return 1; - } - } - - return 0; -} - -static bool view3d_lock_poll(bContext *C) -{ - View3D *v3d = CTX_wm_view3d(C); - if (v3d) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (rv3d) { - return ED_view3d_offset_lock_check(v3d, rv3d); - } - } - return false; -} - static void viewrotate_cancel(bContext *C, wmOperator *op) { viewops_data_free(C, op); @@ -1051,7 +1069,7 @@ static bool ndof_has_translate(const wmNDOFMotionData *ndof, static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d) { - return !is_zero_v3(ndof->rvec) && ((rv3d->viewlock & RV3D_LOCKED) == 0); + return !is_zero_v3(ndof->rvec) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0); } /** @@ -1159,7 +1177,7 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, /* move center of view opposite of hand motion (this is camera mode, not object mode) */ sub_v3_v3(rv3d->ofs, pan_vec); - if (rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(sa, region); } } @@ -1176,7 +1194,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, float view_inv[4]; - BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0); + BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0); ED_view3d_persp_ensure(vod->depsgraph, v3d, region); @@ -1400,7 +1418,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) const bool has_rotation = ndof_has_rotate(ndof, rv3d); /* if we can't rotate, fallback to translate (locked axis views) */ const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) && - (rv3d->viewlock & RV3D_LOCKED); + (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION); const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; if (has_translate || has_zoom) { @@ -1732,7 +1750,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) add_v3_v3(vod->rv3d->ofs, dvec); - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->region); } } @@ -1807,12 +1825,17 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* makes op->customdata */ viewops_data_alloc(C, op); + vod = op->customdata; + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_LOCATION) { + viewops_data_free(C, op); + return OPERATOR_PASS_THROUGH; + } + viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); - vod = op->customdata; ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region); @@ -2165,7 +2188,7 @@ static void viewzoom_apply_3d(ViewOpsData *vod, /* these limits were in old code too */ CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]); - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->region); } @@ -2318,7 +2341,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op) } } - if (rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(sa, region); } @@ -2416,7 +2439,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->invoke = viewzoom_invoke; ot->exec = viewzoom_exec; ot->modal = viewzoom_modal; - ot->poll = ED_operator_region_view3d_active; + ot->poll = view3d_zoom_or_dolly_poll; ot->cancel = viewzoom_cancel; /* flags */ @@ -2514,7 +2537,7 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_ view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac); } - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->region); } @@ -2612,7 +2635,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op) view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f); - if (rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(sa, region); } @@ -2641,7 +2664,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event) vod = op->customdata; /* poll should check but in some cases fails, see poll func for details */ - if (vod->rv3d->viewlock & RV3D_LOCKED) { + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) { viewops_data_free(C, op); return OPERATOR_PASS_THROUGH; } @@ -3121,7 +3144,7 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot) /* api callbacks */ ot->exec = viewselected_exec; - ot->poll = ED_operator_region_view3d_active; + ot->poll = view3d_zoom_or_dolly_poll; /* flags */ ot->flag = 0; @@ -3265,7 +3288,7 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) /* api callbacks */ ot->exec = viewcenter_cursor_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = view3d_pan_poll; /* flags */ ot->flag = 0; @@ -3317,7 +3340,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot) /* api callbacks */ ot->invoke = viewcenter_pick_invoke; - ot->poll = ED_operator_view3d_active; + ot->poll = view3d_pan_poll; /* flags */ ot->flag = 0; @@ -3701,7 +3724,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) .dist = &new_dist, }); - if (rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(CTX_wm_area(C), region); } @@ -3721,7 +3744,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot) ot->modal = WM_gesture_box_modal; ot->cancel = WM_gesture_box_cancel; - ot->poll = ED_operator_region_view3d_active; + ot->poll = view3d_zoom_or_dolly_poll; /* flags */ ot->flag = 0; @@ -3834,7 +3857,7 @@ static void axis_set_view(bContext *C, rv3d->view_axis_roll = view_axis_roll; } - if (rv3d->viewlock & RV3D_LOCKED) { + if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) { ED_region_tag_redraw(region); return; } @@ -4058,7 +4081,7 @@ static int view_camera_exec(bContext *C, wmOperator *op) ED_view3d_smooth_view_force_finish(C, v3d, region); - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) { /* lastview - */ ViewLayer *view_layer = CTX_data_view_layer(C); @@ -4207,7 +4230,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) RV3D_VIEW_USER; orbitdir = RNA_enum_get(op->ptr, "type"); - if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) { + if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) && (view_opposite == RV3D_VIEW_USER)) { /* no NULL check is needed, poll checks */ ED_view3d_context_user_region(C, &v3d, ®ion); rv3d = region->regiondata; @@ -4215,7 +4238,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) ED_view3d_smooth_view_force_finish(C, v3d, region); - if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) { + if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0 || (view_opposite != RV3D_VIEW_USER)) { if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { int smooth_viewtx = WM_operator_smooth_viewtx_get(op); float quat_mul[4]; @@ -4352,7 +4375,7 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y)) vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs); } - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->region); } @@ -4621,7 +4644,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot) /* api callbacks */ ot->invoke = viewpan_invoke; - ot->poll = ED_operator_region_view3d_active; + ot->poll = view3d_pan_poll; /* flags */ ot->flag = 0; @@ -4647,7 +4670,8 @@ static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) ED_view3d_context_user_region(C, &v3d_dummy, ®ion); rv3d = region->regiondata; - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + /* Could add a separate lock flag for locking persp. */ + if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) { if (rv3d->persp != RV3D_ORTHO) { rv3d->persp = RV3D_ORTHO; } |