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/windowmanager/intern/wm_draw.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/windowmanager/intern/wm_draw.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_draw.c | 82 |
1 files changed, 70 insertions, 12 deletions
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 9ccff2a3e3d..a0e8374a46a 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -67,6 +67,7 @@ #include "wm_draw.h" #include "wm_window.h" #include "wm_event_system.h" +#include "wm_surface.h" #ifdef WITH_OPENSUBDIV # include "BKE_subsurf.h" @@ -186,7 +187,10 @@ static void wm_area_mark_invalid_backbuf(ScrArea *sa) } } -static void wm_region_test_gizmo_do_draw(ARegion *region, bool tag_redraw) +static void wm_region_test_gizmo_do_draw(bContext *C, + ScrArea *sa, + ARegion *region, + bool tag_redraw) { if (region->gizmo_map == NULL) { return; @@ -195,10 +199,26 @@ static void wm_region_test_gizmo_do_draw(ARegion *region, bool tag_redraw) wmGizmoMap *gzmap = region->gizmo_map; for (wmGizmoGroup *gzgroup = WM_gizmomap_group_list(gzmap)->first; gzgroup; gzgroup = gzgroup->next) { + if (tag_redraw && (gzgroup->type->flag & WM_GIZMOGROUPTYPE_VR_REDRAWS)) { + ScrArea *ctx_sa = CTX_wm_area(C); + ARegion *ctx_ar = CTX_wm_region(C); + + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, region); + + if (WM_gizmo_group_type_poll(C, gzgroup->type)) { + ED_region_tag_redraw_editor_overlays(region); + } + + /* Reset. */ + CTX_wm_area_set(C, ctx_sa); + CTX_wm_region_set(C, ctx_ar); + } + for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) { if (gz->do_draw) { if (tag_redraw) { - ED_region_tag_redraw_no_rebuild(region); + ED_region_tag_redraw_editor_overlays(region); } gz->do_draw = false; } @@ -237,6 +257,19 @@ static void wm_region_test_render_do_draw(const Scene *scene, } } +#ifdef WITH_XR_OPENXR +static void wm_region_test_xr_do_draw(const wmWindowManager *wm, + const ScrArea *area, + ARegion *region) +{ + if ((area->spacetype == SPACE_VIEW3D) && (region->regiontype == RGN_TYPE_WINDOW)) { + if (ED_view3d_is_region_xr_mirror_active(wm, area->spacedata.first, region)) { + ED_region_tag_redraw_no_rebuild(region); + } + } +} +#endif + static bool wm_region_use_viewport_by_type(short space_type, short region_type) { return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE) && region_type == RGN_TYPE_WINDOW); @@ -836,11 +869,26 @@ static void wm_draw_window(bContext *C, wmWindow *win) screen->do_draw = false; } +/** + * Draw offscreen contexts not bound to a specific window. + */ +static void wm_draw_surface(bContext *C, wmSurface *surface) +{ + wm_window_clear_drawable(CTX_wm_manager(C)); + wm_surface_make_drawable(surface); + + surface->draw(C); + + /* Avoid interference with window drawable */ + wm_surface_clear_drawable(); +} + /****************** main update call **********************/ /* quick test to prevent changing window drawable */ -static bool wm_draw_update_test_window(Main *bmain, wmWindow *win) +static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win) { + const wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true); @@ -861,8 +909,11 @@ static bool wm_draw_update_test_window(Main *bmain, wmWindow *win) ED_screen_areas_iter(win, screen, sa) { for (region = sa->regionbase.first; region; region = region->next) { - wm_region_test_gizmo_do_draw(region, true); + wm_region_test_gizmo_do_draw(C, sa, region, true); wm_region_test_render_do_draw(scene, depsgraph, sa, region); +#ifdef WITH_XR_OPENXR + wm_region_test_xr_do_draw(wm, sa, region); +#endif if (region->visible && region->do_draw) { do_draw = true; @@ -890,19 +941,23 @@ static bool wm_draw_update_test_window(Main *bmain, wmWindow *win) return true; } +#ifndef WITH_XR_OPENXR + UNUSED_VARS(wm); +#endif + return false; } /* Clear drawing flags, after drawing is complete so any draw flags set during * drawing don't cause any additional redraws. */ -static void wm_draw_update_clear_window(wmWindow *win) +static void wm_draw_update_clear_window(bContext *C, wmWindow *win) { bScreen *screen = WM_window_get_active_screen(win); ED_screen_areas_iter(win, screen, sa) { for (ARegion *region = sa->regionbase.first; region; region = region->next) { - wm_region_test_gizmo_do_draw(region, false); + wm_region_test_gizmo_do_draw(C, sa, region, false); } } @@ -944,10 +999,10 @@ void wm_draw_update(bContext *C) } #endif - if (wm_draw_update_test_window(bmain, win)) { - bScreen *screen = WM_window_get_active_screen(win); + CTX_wm_window_set(C, win); - CTX_wm_window_set(C, win); + if (wm_draw_update_test_window(bmain, C, win)) { + bScreen *screen = WM_window_get_active_screen(win); /* sets context window+screen */ wm_window_make_drawable(wm, win); @@ -956,13 +1011,16 @@ void wm_draw_update(bContext *C) ED_screen_ensure_updated(wm, win, screen); wm_draw_window(C, win); - wm_draw_update_clear_window(win); + wm_draw_update_clear_window(C, win); wm_window_swap_buffers(win); - - CTX_wm_window_set(C, NULL); } } + + CTX_wm_window_set(C, NULL); + + /* Draw non-windows (surfaces) */ + wm_surfaces_iter(C, wm_draw_surface); } void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(region)) |