mirror of
https://projects.blender.org/blender/blender.git
synced 2025-01-22 07:22:12 -05:00
squashed XR, Support Mirror Blender UI to XR
This commit is contained in:
parent
1628cfee8d
commit
b67c7eab58
22 changed files with 1447 additions and 72 deletions
|
@ -84,6 +84,8 @@ _modules = [
|
|||
|
||||
# XXX, keep last so panels show after all other tool options.
|
||||
"properties_workspace",
|
||||
# XXX This depends on spaces
|
||||
"properties_viewport_vr_mirror",
|
||||
]
|
||||
|
||||
import bpy
|
||||
|
|
40
scripts/startup/bl_ui/properties_viewport_vr_mirror.py
Normal file
40
scripts/startup/bl_ui/properties_viewport_vr_mirror.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
|
||||
class VIEW3D_PT_vr_session_blender_ui_mirror(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = 'VR'
|
||||
bl_label = 'Blender UI Mirror'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
session_settings = context.window_manager.xr_session_settings
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(session_settings, "show_blender_ui_mirror")
|
||||
col.prop(session_settings, "show_xr_controllers")
|
||||
col.prop(session_settings, "use_mirror_ui_xray")
|
||||
col.prop(session_settings, "hide_mirror_ui_on_mouse_over_v3d")
|
||||
col.prop(session_settings, "viewer_offset")
|
||||
col.prop(session_settings, "viewer_angle_offset")
|
||||
col.prop(session_settings, "mirrored_ui_rads_span")
|
||||
col.prop(session_settings, "mirrored_ui_offset")
|
||||
col.prop(session_settings, "mirrored_ui_scale_y")
|
||||
col.prop(session_settings, "mirrored_ui_distance_factor")
|
||||
col.prop(session_settings, "cursor_raycast_distance0")
|
||||
col.prop(session_settings, "cursor_raycast_distance1")
|
||||
col.prop(session_settings, "cursor_raycast_distance2")
|
||||
|
||||
classes = [
|
||||
VIEW3D_PT_vr_session_blender_ui_mirror
|
||||
]
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
|
@ -277,6 +277,13 @@ void CTX_data_type_set(struct bContextDataResult *result, short type);
|
|||
short CTX_data_type_get(struct bContextDataResult *result);
|
||||
|
||||
bool CTX_data_equals(const char *member, const char *str);
|
||||
// GG: If is_empty_string(member), then callers should CTX_data_dir_set(result, dir) where dir
|
||||
// is an array of strings w/ a null sentinel as the last element. These strings are the names of
|
||||
// members/vars that the caller knows about and can set. Why this was never commented/documented
|
||||
// within the code I dont know. (see: https://wiki.blender.org/wiki/Source/Architecture/Context
|
||||
// under callbacks).. And why we've chosen to design a singular function (image_context(..))
|
||||
// that returns two different results for different uses (do you have this member? / fill this
|
||||
// member) is beyond me.
|
||||
bool CTX_data_dir(const char *member);
|
||||
|
||||
#define CTX_DATA_BEGIN(C, Type, instance, member) \
|
||||
|
@ -285,7 +292,8 @@ bool CTX_data_dir(const char *member);
|
|||
CollectionPointerLink *ctx_link; \
|
||||
CTX_data_##member(C, &ctx_data_list); \
|
||||
for (ctx_link = (CollectionPointerLink *)ctx_data_list.first; ctx_link; \
|
||||
ctx_link = ctx_link->next) { \
|
||||
ctx_link = ctx_link->next) \
|
||||
{ \
|
||||
Type instance = (Type)ctx_link->ptr.data;
|
||||
|
||||
#define CTX_DATA_END \
|
||||
|
|
|
@ -3812,6 +3812,23 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "XrSessionSettings", "float", "mirrored_ui_scale_y")) {
|
||||
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
|
||||
wm->xr.session_settings.flag |= XR_SESSION_USE_UI_MIRROR_XRAY | XR_SESSION_SHOW_CONTROLLERS |
|
||||
XR_SESSION_SHOW_BLENDER_UI_MIRROR;
|
||||
// Commented code left as reminder that the default hiding is off.
|
||||
// wm->xr.session_settings.flag &= ~XR_SESSION_HIDE_UI_MIRROR_ON_MOUSE_OVER_V3D;
|
||||
zero_v3(wm->xr.session_settings.viewer_offset);
|
||||
wm->xr.session_settings.viewer_angle_offset = 0;
|
||||
wm->xr.session_settings.mirrored_ui_rads_span = 1.57f;
|
||||
zero_v2(wm->xr.session_settings.mirrored_ui_offset);
|
||||
wm->xr.session_settings.mirrored_ui_scale_y = 1;
|
||||
wm->xr.session_settings.mirrored_ui_distance_factor = 10.0f;
|
||||
wm->xr.session_settings.cursor_raycast_distance0 = -1;
|
||||
wm->xr.session_settings.cursor_raycast_distance1 = 1;
|
||||
wm->xr.session_settings.cursor_raycast_distance2 = 6;
|
||||
}
|
||||
}
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "short", "ikflag_location")) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->type != OB_ARMATURE || ob->pose == nullptr) {
|
||||
|
|
|
@ -100,7 +100,8 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
|||
bool draw_background,
|
||||
bool do_color_management,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUViewport *viewport);
|
||||
struct GPUViewport *viewport,
|
||||
const struct bContext *evil_C);
|
||||
void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
|
||||
struct ARegion *region,
|
||||
struct GPUViewport *viewport,
|
||||
|
|
|
@ -1465,7 +1465,7 @@ void DRW_draw_callbacks_post_scene(void)
|
|||
|
||||
const bool do_annotations = drw_draw_show_annotation();
|
||||
|
||||
if (DST.draw_ctx.evil_C) {
|
||||
if (DST.draw_ctx.evil_C && (v3d->flag & V3D_XR_SESSION_SURFACE) == 0) {
|
||||
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
|
||||
|
||||
DRW_state_reset();
|
||||
|
@ -1490,33 +1490,37 @@ void DRW_draw_callbacks_post_scene(void)
|
|||
/* Apply state for callbacks. */
|
||||
GPU_apply_state();
|
||||
|
||||
// GG: TODO: ... sadly this very call (operator helper guides) is what causes the visual
|
||||
// distortion while in XR. I suppose the proper way
|
||||
// is for the operators to add their callbacks to the v3D region surface? Then the problematic
|
||||
// operators just plain won't draw? Or just choose to be more aware of when they're causing an
|
||||
// issue and make better choices?
|
||||
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW);
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* XR callbacks (controllers, custom draw functions) for session mirror. */
|
||||
if ((v3d->flag & V3D_XR_SESSION_MIRROR) != 0) {
|
||||
if ((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) {
|
||||
ARegionType *art = WM_xr_surface_controller_region_type_get();
|
||||
// if ((v3d->flag & V3D_XR_SESSION_MIRROR) != 0) {
|
||||
if ((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) {
|
||||
ARegionType *art = WM_xr_surface_controller_region_type_get();
|
||||
if (art) {
|
||||
ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW);
|
||||
}
|
||||
}
|
||||
if ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0) {
|
||||
SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D);
|
||||
if (st) {
|
||||
ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_XR);
|
||||
if (art) {
|
||||
ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW);
|
||||
}
|
||||
}
|
||||
if ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0) {
|
||||
SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D);
|
||||
if (st) {
|
||||
ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_XR);
|
||||
if (art) {
|
||||
ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Callback can be nasty and do whatever they want with the state.
|
||||
* Don't trust them! */
|
||||
DRW_state_reset();
|
||||
|
||||
/* Needed so gizmo isn't occluded. */
|
||||
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
|
||||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
|
@ -1561,6 +1565,9 @@ void DRW_draw_callbacks_post_scene(void)
|
|||
}
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
// GG: This is where Blender explicitly draws XR controllers, or more relveant atm,
|
||||
// where blender allows custom drawing during an XR session. this is where I can (properly)
|
||||
// insert the BLender UI quad draw.
|
||||
if ((v3d->flag & V3D_XR_SESSION_SURFACE) != 0) {
|
||||
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
|
||||
|
||||
|
@ -1597,6 +1604,13 @@ void DRW_draw_callbacks_post_scene(void)
|
|||
DRW_state_reset();
|
||||
}
|
||||
|
||||
// disabled since its causing visual distortions?
|
||||
// GPU_depth_test(GPU_DEPTH_NONE);
|
||||
// // 3D cursor drawing,
|
||||
// // ideally, we do this before the controllers are drawn but for some reason doing so leads
|
||||
// // to the controllers not being draw at all
|
||||
// DRW_draw_region_info();
|
||||
|
||||
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
||||
}
|
||||
#endif
|
||||
|
@ -1773,7 +1787,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
|
|||
|
||||
DRW_stats_reset();
|
||||
|
||||
DRW_draw_callbacks_post_scene();
|
||||
DRW_draw_callbacks_post_scene(); // maybe gizmos and all dont render in XR because the
|
||||
// callbacks aren't attacheds to it?
|
||||
|
||||
if (WM_draw_region_get_bound_viewport(region)) {
|
||||
/* Don't unbind the frame-buffer yet in this case and let
|
||||
|
@ -1812,7 +1827,8 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
|||
const bool draw_background,
|
||||
const bool do_color_management,
|
||||
GPUOffScreen *ofs,
|
||||
GPUViewport *viewport)
|
||||
GPUViewport *viewport,
|
||||
const bContext *evil_C)
|
||||
{
|
||||
const bool is_xr_surface = ((v3d->flag & V3D_XR_SESSION_SURFACE) != 0);
|
||||
|
||||
|
@ -1834,7 +1850,12 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
|||
drw_state_prepare_clean_for_draw(&DST);
|
||||
DST.options.is_image_render = is_image_render;
|
||||
DST.options.draw_background = draw_background;
|
||||
DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, render_viewport, NULL);
|
||||
// GG: I thikn the callbacks dont get called because NULL is sent for the context?
|
||||
// ..well the above one alsos sends NULL, so thats probably not it. Though the CB
|
||||
// beign called do dep on evil_c being non null. Actually i think that's exactly it.
|
||||
// This call stack just doesn't do callbacks for w/e reason? yet its the only way to
|
||||
// draw to an offscreen buffer....
|
||||
DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, render_viewport, evil_C);
|
||||
|
||||
if (draw_background) {
|
||||
/* HACK(@fclem): In this case we need to make sure the final alpha is 1.
|
||||
|
|
|
@ -40,7 +40,8 @@ void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
|
|||
bool do_color_management,
|
||||
bool restore_rv3d_mats,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUViewport *viewport);
|
||||
struct GPUViewport *viewport,
|
||||
const struct bContext *evil_C);
|
||||
/**
|
||||
* Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen). Similar too
|
||||
* #ED_view_draw_offscreen_imbuf_simple, but takes view/projection matrices as arguments.
|
||||
|
@ -64,7 +65,8 @@ void ED_view3d_draw_offscreen_simple(struct Depsgraph *depsgraph,
|
|||
const char *viewname,
|
||||
bool do_color_management,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUViewport *viewport);
|
||||
struct GPUViewport *viewport,
|
||||
struct bContext *evil_C);
|
||||
|
||||
/**
|
||||
* Utility func for ED_view3d_draw_offscreen
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_studiolight.h"
|
||||
#include "BKE_unit.h"
|
||||
|
||||
|
@ -78,6 +79,7 @@
|
|||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
#include "wm_draw.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
|
@ -1656,7 +1658,8 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
|
|||
const bool do_color_management,
|
||||
const bool restore_rv3d_mats,
|
||||
GPUOffScreen *ofs,
|
||||
GPUViewport *viewport)
|
||||
GPUViewport *viewport,
|
||||
const bContext *evil_C)
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
RenderEngineType *engine_type = ED_view3d_engine_type(scene, drawtype);
|
||||
|
@ -1732,7 +1735,8 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
|
|||
draw_background,
|
||||
do_color_management,
|
||||
ofs,
|
||||
viewport);
|
||||
viewport,
|
||||
evil_C);
|
||||
DRW_cache_free_old_subdiv();
|
||||
GPU_matrix_pop_projection();
|
||||
GPU_matrix_pop();
|
||||
|
@ -1775,7 +1779,8 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||
const char *viewname,
|
||||
const bool do_color_management,
|
||||
GPUOffScreen *ofs,
|
||||
GPUViewport *viewport)
|
||||
GPUViewport *viewport,
|
||||
bContext *evil_C)
|
||||
{
|
||||
View3D v3d = blender::dna::shallow_zero_initialize();
|
||||
ARegion ar = {nullptr};
|
||||
|
@ -1784,7 +1789,74 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||
v3d.regionbase.first = v3d.regionbase.last = &ar;
|
||||
ar.regiondata = &rv3d;
|
||||
ar.regiontype = RGN_TYPE_WINDOW;
|
||||
// GG: callbacks are attached to ARegion.type so this needs to be assigned properly.
|
||||
// GG: TODO: a nonNull evil_C works and the deired callbacks will occur (pre/post view for ex:
|
||||
// mesh loopcut) however, I've disbled it for now since it creates distortion in the xr session
|
||||
// drawing and I dont know why, nor do I have the energy to look into why. A: it seems the
|
||||
// postview callbacks themselves cause the distortion, so
|
||||
// .. the only way for this to work and be practical (no distrtions) then it wo9uld have to be a
|
||||
// GPU state that's being changed by a callback, but i doubt it since we reset() things I think?
|
||||
// Thus the solution is for callbacks themselves to not casuse the distortion which isn't
|
||||
// practical w/o them explicitly knowing whether they're drawing to an XR surface. And thats too
|
||||
// much work atm so i'm leaving the callback drawing disabled.
|
||||
evil_C = nullptr;
|
||||
if (evil_C) {
|
||||
ar.type = BKE_regiontype_from_id(BKE_spacetype_from_id(SPACE_VIEW3D), RGN_TYPE_WINDOW);
|
||||
|
||||
wmWindowManager *wm = CTX_wm_manager(evil_C);
|
||||
wmWindow *win = static_cast<wmWindow *>(wm->windows.first);
|
||||
|
||||
ARegion *v3d_region_under_mouse = nullptr;
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
ScrArea *v3d_area = nullptr;
|
||||
ED_screen_areas_iter (win, screen, area) {
|
||||
if (area->spacetype != SPACE_VIEW3D) {
|
||||
continue;
|
||||
}
|
||||
// v3d = area->spacedata.first;
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (!region->visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (region->overlap) {
|
||||
continue;
|
||||
}
|
||||
if (region->draw_buffer->viewport == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (region->regiontype != RGN_TYPE_WINDOW) {
|
||||
continue;
|
||||
}
|
||||
|
||||
v3d_region_under_mouse = region;
|
||||
v3d_area = area;
|
||||
}
|
||||
}
|
||||
|
||||
// after this, its just tedious stuff that also needs to be set otherwise an error is thrown
|
||||
// but otherwise isn't specifically needed for callbacks to be called.
|
||||
// needed for view3d_draw_border().. GG: TODO: still erroring though..
|
||||
// v3d.spacetype = SPACE_VIEW3D;
|
||||
// send in any old existing v3d area so callbacks occur. Our offscreen buffer is active so it
|
||||
// will draw to our buffer anyways. Who cares what dta its reading from.
|
||||
// IT works!
|
||||
CTX_wm_area_set(evil_C, v3d_area); // static_cast<ScrArea *>(&v3d));
|
||||
// View3D *v3d_ret = CTX_wm_view3d(evil_C); // 48dcbfcc70
|
||||
// BLI_assert(v3d_ret != nullptr);
|
||||
}
|
||||
/*
|
||||
* note: seach for CTX_wm_area_set() for proper useage: One file sets it like this:
|
||||
*
|
||||
CTX_wm_manager_set(C, static_cast<wmWindowManager *>(bmain->wm.first));
|
||||
CTX_wm_screen_set(C, bfd->curscreen);
|
||||
CTX_data_scene_set(C, bfd->curscene);
|
||||
CTX_wm_area_set(C, nullptr);
|
||||
CTX_wm_region_set(C, nullptr);
|
||||
CTX_wm_menu_set(C, nullptr);
|
||||
|
||||
SO maybe I do too?
|
||||
*/
|
||||
View3DShading *source_shading_settings = &scene->display.shading;
|
||||
if (draw_flags & V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS && shading_override != nullptr) {
|
||||
source_shading_settings = shading_override;
|
||||
|
@ -1822,15 +1894,15 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||
v3d.flag2 |= V3D_XR_SHOW_CUSTOM_OVERLAYS;
|
||||
}
|
||||
/* Disable other overlays (set all available _HIDE_ flags). */
|
||||
v3d.overlay.flag |= V3D_OVERLAY_HIDE_CURSOR | V3D_OVERLAY_HIDE_TEXT |
|
||||
V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
|
||||
// v3d.overlay.flag |= V3D_OVERLAY_HIDE_CURSOR | V3D_OVERLAY_HIDE_TEXT |
|
||||
// V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
|
||||
if ((draw_flags & V3D_OFSDRAW_SHOW_OBJECT_EXTRAS) == 0) {
|
||||
v3d.overlay.flag |= V3D_OVERLAY_HIDE_OBJECT_XTRAS;
|
||||
}
|
||||
if ((object_type_exclude_viewport_override & (1 << OB_ARMATURE)) != 0) {
|
||||
v3d.overlay.flag |= V3D_OVERLAY_HIDE_BONES;
|
||||
}
|
||||
v3d.flag |= V3D_HIDE_HELPLINES;
|
||||
// v3d.flag |= V3D_HIDE_HELPLINES;
|
||||
}
|
||||
|
||||
if (is_xr_surface) {
|
||||
|
@ -1861,7 +1933,8 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||
do_color_management,
|
||||
true,
|
||||
ofs,
|
||||
viewport);
|
||||
viewport,
|
||||
evil_C);
|
||||
}
|
||||
|
||||
ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
||||
|
@ -1989,6 +2062,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
|||
do_color_management,
|
||||
restore_rv3d_mats,
|
||||
ofs,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
if (ibuf->rect_float) {
|
||||
|
|
|
@ -522,6 +522,9 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
|
|||
|
||||
void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
|
||||
{
|
||||
// GG: TODO: LOOK: the windows are drawn w/ colorspace stuff going on!, I should be able to just
|
||||
// disable it? Unless the pre-draw itself is also done w/ colorspacing stuff then its a bit more
|
||||
// invovled..
|
||||
GPU_viewport_draw_to_screen_ex(viewport, view, rect, true, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -1383,6 +1383,14 @@ static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat
|
|||
(s3d->flag & S3D_INTERLACE_SWAP) != 0);
|
||||
break;
|
||||
case S3D_DISPLAY_SIDEBYSIDE:
|
||||
// GG: This func shows that both L/R img buffers already have the scene drawn.
|
||||
// Since these funcs are just properly interlacing/placing the pixel data within the
|
||||
// buffers.
|
||||
//... which means that the Blender UI probnably isn't part of these buffers and they're
|
||||
// just the view3D w/o the overlays. meaning that We must copy the UI elsewhere. This
|
||||
// also means that the BlenderUI part will not have the view3D drawn so hopefully, itll
|
||||
// be trivial to set the view3D non-overlay elements as alpha cutout. Probbaly as simple
|
||||
// as a GL_CLEARBuffEr_COlor(trnasparent) bfore rendering overlays.
|
||||
imb_stereo3d_read_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0);
|
||||
break;
|
||||
case S3D_DISPLAY_TOPBOTTOM:
|
||||
|
|
|
@ -111,15 +111,20 @@ typedef struct ReportTimerInfo {
|
|||
float widthfac;
|
||||
} ReportTimerInfo;
|
||||
|
||||
//#ifdef WITH_XR_OPENXR
|
||||
// #ifdef WITH_XR_OPENXR
|
||||
typedef struct wmXrData {
|
||||
/** Runtime information for managing Blender specific behaviors. */
|
||||
struct wmXrRuntimeData *runtime;
|
||||
/** Permanent session settings (draw mode, feature toggles, etc). Stored in files and accessible
|
||||
* even before the session runs. */
|
||||
XrSessionSettings session_settings;
|
||||
ListBase full_blender_ui_screens; /* #LinkData of GPUOffScreen, not saved to file. */
|
||||
short window_positions_xy[64];
|
||||
int mouse_positions_per_window_xy[64];
|
||||
int mouse_position_global_xy[2];
|
||||
struct bContext *evil_C;
|
||||
} wmXrData;
|
||||
//#endif
|
||||
// #endif
|
||||
|
||||
/* reports need to be before wmWindowManager */
|
||||
|
||||
|
@ -199,9 +204,9 @@ typedef struct wmWindowManager {
|
|||
|
||||
struct wmMsgBus *message_bus;
|
||||
|
||||
//#ifdef WITH_XR_OPENXR
|
||||
// #ifdef WITH_XR_OPENXR
|
||||
wmXrData xr;
|
||||
//#endif
|
||||
// #endif
|
||||
} wmWindowManager;
|
||||
|
||||
/** #wmWindowManager.initialized */
|
||||
|
|
|
@ -37,6 +37,18 @@ typedef struct XrSessionSettings {
|
|||
|
||||
int flag;
|
||||
|
||||
float mirrored_ui_offset[2];
|
||||
// float mirrored_ui_scale;
|
||||
float mirrored_ui_scale_y;
|
||||
float mirrored_ui_distance_factor;
|
||||
float cursor_raycast_distance0;
|
||||
float cursor_raycast_distance1;
|
||||
float cursor_raycast_distance2;
|
||||
float viewer_offset[3];
|
||||
float viewer_angle_offset;
|
||||
float mirrored_ui_rads_span;
|
||||
// float _pad3;
|
||||
|
||||
/** Object type settings to apply to VR view (unlike shading, not shared with window 3D-View). */
|
||||
int object_type_exclude_viewport;
|
||||
int object_type_exclude_select;
|
||||
|
@ -45,6 +57,10 @@ typedef struct XrSessionSettings {
|
|||
typedef enum eXrSessionFlag {
|
||||
XR_SESSION_USE_POSITION_TRACKING = (1 << 0),
|
||||
XR_SESSION_USE_ABSOLUTE_TRACKING = (1 << 1),
|
||||
XR_SESSION_USE_UI_MIRROR_XRAY = (1 << 2),
|
||||
XR_SESSION_HIDE_UI_MIRROR_ON_MOUSE_OVER_V3D = (1 << 3),
|
||||
XR_SESSION_SHOW_CONTROLLERS = (1 << 4),
|
||||
XR_SESSION_SHOW_BLENDER_UI_MIRROR = (1 << 5),
|
||||
} eXrSessionFlag;
|
||||
|
||||
typedef enum eXRSessionBasePoseType {
|
||||
|
|
|
@ -699,7 +699,7 @@ static int rna_XrSessionSettings_icon_from_show_object_viewport_get(PointerRNA *
|
|||
const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr);
|
||||
return rna_object_type_visibility_icon_get_common(
|
||||
xr->session_settings.object_type_exclude_viewport,
|
||||
# if 0
|
||||
# if 1
|
||||
/* For the future when selection in VR is reliably supported. */
|
||||
&xr->session_settings.object_type_exclude_select
|
||||
# else
|
||||
|
@ -2035,6 +2035,106 @@ static void rna_def_xr_session_settings(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Clip End", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
{
|
||||
prop = RNA_def_property(srna, "viewer_offset", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_default(prop, 0);
|
||||
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -10, 10, 0.01f, 2);
|
||||
RNA_def_property_ui_text(prop, "Viewer Offset", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "viewer_angle_offset", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_default(prop, 0);
|
||||
RNA_def_property_range(prop, -6.28f, 6.28f);
|
||||
RNA_def_property_ui_range(prop, -6.28f, 6.28f, 1, 0);
|
||||
RNA_def_property_ui_text(prop, "Angle Offset", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "mirrored_ui_rads_span", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_default(prop, 1.57f);
|
||||
RNA_def_property_range(prop, 0, 6.28f);
|
||||
RNA_def_property_ui_range(prop, 0, 6.28f, 1, 0);
|
||||
RNA_def_property_ui_text(prop, "Angle Span", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "mirrored_ui_offset", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_default(prop, 0);
|
||||
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 10, 0);
|
||||
RNA_def_property_ui_text(prop, "UI Offset", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
// prop = RNA_def_property(srna, "mirrored_ui_scale", PROP_FLOAT, PROP_DISTANCE);
|
||||
// RNA_def_property_float_default(prop, 1);
|
||||
// RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||
// RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 0.1f, 3);
|
||||
// RNA_def_property_ui_text(prop, "UI Scale", "VR viewport far clipping distance");
|
||||
// RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "mirrored_ui_scale_y", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_default(prop, 1);
|
||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 0.1f, 3);
|
||||
RNA_def_property_ui_text(prop, "UI YScale", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "mirrored_ui_distance_factor", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_default(prop, 1);
|
||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 0.1f, 3);
|
||||
RNA_def_property_ui_text(prop, "UI Distance Factor", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "cursor_raycast_distance0", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_default(prop, -1.0f);
|
||||
RNA_def_property_range(prop, -1.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -1.0f, 20.0f, 0.001f, 3);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Cursor RayCast p0 Distance", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "cursor_raycast_distance1", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_default(prop, 1);
|
||||
RNA_def_property_range(prop, -1.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -1.0f, 20.0f, 0.001f, 3);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Cursor RayCast p1 Distance", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "cursor_raycast_distance2", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_default(prop, 6);
|
||||
RNA_def_property_range(prop, -1.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -1.0f, 20.0f, 0.001f, 3);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Cursor RayCast p2 Distance", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_mirror_ui_xray", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", XR_SESSION_USE_UI_MIRROR_XRAY);
|
||||
RNA_def_property_ui_text(prop, "Mirrored UI: Do XRay", "");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "hide_mirror_ui_on_mouse_over_v3d", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", XR_SESSION_HIDE_UI_MIRROR_ON_MOUSE_OVER_V3D);
|
||||
RNA_def_property_boolean_default(prop, false);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Mouse Over V3D: Hide Mirror UI",
|
||||
"Best used w/ prefs set to disabled region overlapping");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_xr_controllers", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", XR_SESSION_SHOW_CONTROLLERS);
|
||||
RNA_def_property_boolean_default(prop, true);
|
||||
RNA_def_property_ui_text(prop, "Show Controllers", "");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_blender_ui_mirror", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", XR_SESSION_SHOW_BLENDER_UI_MIRROR);
|
||||
RNA_def_property_boolean_default(prop, true);
|
||||
RNA_def_property_ui_text(prop, "Show Blender UI Mirror", "");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
}
|
||||
|
||||
prop = RNA_def_property(srna, "use_positional_tracking", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop,
|
||||
"rna_XrSessionSettings_use_positional_tracking_get",
|
||||
|
@ -2180,15 +2280,15 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
parm = RNA_def_string(
|
||||
func, "user_path", NULL, XR_MAX_USER_PATH_LENGTH, "User Path", "OpenXR user path");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_float_array(
|
||||
func,
|
||||
parm = RNA_def_float_array(func,
|
||||
"state",
|
||||
2,
|
||||
NULL,
|
||||
-FLT_MAX,
|
||||
FLT_MAX,
|
||||
"Action State",
|
||||
"Current state of the VR action. Second float value is only set for 2D vector type actions",
|
||||
"Current state of the VR action. Second float value is only set "
|
||||
"for 2D vector type actions",
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT);
|
||||
|
|
|
@ -411,7 +411,8 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar
|
|||
do_color_management,
|
||||
true,
|
||||
self->ofs,
|
||||
self->viewport);
|
||||
self->viewport,
|
||||
NULL);
|
||||
|
||||
GPU_offscreen_unbind(self->ofs, true);
|
||||
|
||||
|
|
|
@ -211,6 +211,11 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
wm->message_bus = NULL;
|
||||
|
||||
wm->xr.runtime = NULL;
|
||||
// GG: what if it has data in it? Or is this more of a nulling out refs that dont exist anymore?
|
||||
// or maybe Blender checks which data has been orphaned and will not save orphaned data? it
|
||||
// exists on first load of saved data, but not on reload after savingagain?
|
||||
wm->xr.full_blender_ui_screens.first = NULL;
|
||||
wm->xr.full_blender_ui_screens.last = NULL;
|
||||
|
||||
BLI_listbase_clear(&wm->jobs);
|
||||
BLI_listbase_clear(&wm->drags);
|
||||
|
|
|
@ -750,6 +750,7 @@ static void wm_draw_region_unbind(ARegion *region)
|
|||
|
||||
static void wm_draw_region_blit(ARegion *region, int view)
|
||||
{
|
||||
// int original_view = view;
|
||||
if (!region->draw_buffer) {
|
||||
return;
|
||||
}
|
||||
|
@ -765,10 +766,27 @@ static void wm_draw_region_blit(ARegion *region, int view)
|
|||
}
|
||||
}
|
||||
|
||||
// GG: so they blit w/ awareness of whether its stereo or not.
|
||||
// GG: This is sthe call that draws the viewports scenes (not the overlays).
|
||||
// So.. i just need to make this completely transparent instead.
|
||||
// Since this is a blit, that means all the UI was already rendered earlier. This is just
|
||||
// properly blitting to the L/R buffers, I think. And, that means all other code draws the
|
||||
// rest of the UI, which is done in GPU_offscreen_draw_to_screen() and caller for overlays.
|
||||
if (region->draw_buffer->viewport) {
|
||||
|
||||
// if (original_view == 1) {
|
||||
// original_view += 1;
|
||||
// }
|
||||
GPU_viewport_draw_to_screen(region->draw_buffer->viewport, view, ®ion->winrct);
|
||||
}
|
||||
else {
|
||||
// GG: not sure why this draws for view==0, but not for view==1? Maybe the 1st time its drawn
|
||||
// repeated? and the 2nd is just redundant?
|
||||
// but.. then when the 2nd view only draws, then everything is bal
|
||||
/*if (original_view == 1)
|
||||
return;*/
|
||||
// GG:*USEFUL* That means that the thing of interest is region->draw_buffer->offscreen which
|
||||
// has the UI of interest.
|
||||
GPU_offscreen_draw_to_screen(
|
||||
region->draw_buffer->offscreen, region->winrct.xmin, region->winrct.ymin);
|
||||
}
|
||||
|
@ -1013,7 +1031,10 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
|
|||
}
|
||||
}
|
||||
|
||||
static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
|
||||
static void wm_draw_window_onscreen(bContext *C,
|
||||
wmWindow *win,
|
||||
int view,
|
||||
const bool do_view3D_cutout)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
|
@ -1021,7 +1042,8 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
|
|||
GPU_debug_group_begin("Window Redraw");
|
||||
|
||||
/* Draw into the window frame-buffer, in full window coordinates. */
|
||||
wmWindowViewport(win);
|
||||
wmWindowViewport(
|
||||
win); // GG: for upscaling, this prob should use upscale res instead of window res.
|
||||
|
||||
/* We draw on all pixels of the windows so we don't need to clear them before.
|
||||
* Actually this is only a problem when resizing the window.
|
||||
|
@ -1030,17 +1052,28 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
|
|||
GPU_clear_color(0, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
if (do_view3D_cutout)
|
||||
GPU_clear_color(0, 0, 0, 0);
|
||||
|
||||
/* Blit non-overlapping area regions. */
|
||||
// GG: This is nonoverlays, so its the File menu, view3D, timeline ,etc.
|
||||
// Overlays are the T/N panels, timeline playback cursor, etc. view3D nav is drawn here too.
|
||||
ED_screen_areas_iter (win, screen, area) {
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (!region->visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (region->overlap == false) {
|
||||
/* Blit from off-screen buffer. */
|
||||
wm_draw_region_blit(region, view);
|
||||
if (region->overlap) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (do_view3D_cutout && region->draw_buffer->viewport) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Blit from off-screen buffer. */
|
||||
wm_draw_region_blit(region, view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1156,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
|
|||
GPU_debug_group_end();
|
||||
}
|
||||
|
||||
static void wm_draw_window(bContext *C, wmWindow *win)
|
||||
static void wm_draw_window(bContext *C, wmWindow *win, GPUOffScreen *mirrored_screen)
|
||||
{
|
||||
GPU_context_begin_frame(win->gpuctx);
|
||||
|
||||
|
@ -1135,25 +1168,48 @@ static void wm_draw_window(bContext *C, wmWindow *win)
|
|||
|
||||
/* Draw area regions into their own frame-buffer. This way we can redraw
|
||||
* the areas that need it, and blit the rest from existing frame-buffers. */
|
||||
// GG: I think this is where we drawn Blender UI? then the L/R stero imagaes are just blitted
|
||||
// ontop of the view3D?
|
||||
// GG: I think that this draws all elements, probably except view3D. These elements are then
|
||||
// blitted
|
||||
// to each L/R side. So the UI is drawn once, cached, blitted per L/R.
|
||||
// So I think this is the
|
||||
wm_draw_window_offscreen(C, win, stereo);
|
||||
|
||||
// GG: TODO: if mirrored_screen is not NULL, then draw to that along with drawing to the normal
|
||||
// backbuffer.
|
||||
// So basically, draw to the mirroeed scren then copy mirror to buffer.
|
||||
|
||||
/* Now we draw into the window frame-buffer, in full window coordinates. */
|
||||
if (!stereo) {
|
||||
/* Regular mono drawing. */
|
||||
wm_draw_window_onscreen(C, win, -1);
|
||||
// GG: *USEFUL* This is the call of interest. It blits all the buffers for the entire UI. To
|
||||
// prevent the view3D from drawing, we just
|
||||
// avoid calling wm_draw_region_blit():GPU_viewport_draw_to_screen within this function.
|
||||
// FOr VR sessions, we just set the backbuffer to a render texture (or blit to one) then draw
|
||||
// the texture in scene space for the session.
|
||||
|
||||
wm_draw_window_onscreen(C, win, -1, false);
|
||||
|
||||
// TODO: Clear view3D to trnasparent and dont draw the sceen at all.
|
||||
if (mirrored_screen != NULL) {
|
||||
GPU_offscreen_bind(mirrored_screen, false);
|
||||
wm_draw_window_onscreen(C, win, -1, true);
|
||||
GPU_offscreen_unbind(mirrored_screen, false);
|
||||
}
|
||||
}
|
||||
else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
|
||||
/* For page-flip we simply draw to both back buffers. */
|
||||
GPU_backbuffer_bind(GPU_BACKBUFFER_RIGHT);
|
||||
wm_draw_window_onscreen(C, win, 1);
|
||||
wm_draw_window_onscreen(C, win, 1, false);
|
||||
|
||||
GPU_backbuffer_bind(GPU_BACKBUFFER_LEFT);
|
||||
wm_draw_window_onscreen(C, win, 0);
|
||||
wm_draw_window_onscreen(C, win, 0, false);
|
||||
}
|
||||
else if (ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) {
|
||||
/* For anaglyph and interlace, we draw individual regions with
|
||||
* stereo frame-buffers using different shaders. */
|
||||
wm_draw_window_onscreen(C, win, -1);
|
||||
wm_draw_window_onscreen(C, win, -1, false);
|
||||
}
|
||||
else {
|
||||
/* For side-by-side and top-bottom, we need to render each view to an
|
||||
|
@ -1171,7 +1227,7 @@ static void wm_draw_window(bContext *C, wmWindow *win)
|
|||
for (int view = 0; view < 2; view++) {
|
||||
/* Draw view into offscreen buffer. */
|
||||
GPU_offscreen_bind(offscreen, false);
|
||||
wm_draw_window_onscreen(C, win, view);
|
||||
wm_draw_window_onscreen(C, win, view, false);
|
||||
GPU_offscreen_unbind(offscreen, false);
|
||||
|
||||
/* Draw offscreen buffer to screen. */
|
||||
|
@ -1179,6 +1235,9 @@ static void wm_draw_window(bContext *C, wmWindow *win)
|
|||
|
||||
wmWindowViewport(win);
|
||||
if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) {
|
||||
// GG: Per iter, this draws half of the entire blender UI, which I think is
|
||||
// a single buffer i think by this point?- as in all the UI is already in the
|
||||
// texture, we're just properly placing it on screen...
|
||||
wm_stereo3d_draw_sidebyside(win, view);
|
||||
}
|
||||
else {
|
||||
|
@ -1192,7 +1251,7 @@ static void wm_draw_window(bContext *C, wmWindow *win)
|
|||
}
|
||||
else {
|
||||
/* Still draw something in case of allocation failure. */
|
||||
wm_draw_window_onscreen(C, win, 0);
|
||||
wm_draw_window_onscreen(C, win, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1320,7 +1379,7 @@ uint *WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_siz
|
|||
const uint rect_len = r_size[0] * r_size[1];
|
||||
uint *rect = MEM_mallocN(sizeof(*rect) * rect_len, __func__);
|
||||
GPU_offscreen_bind(offscreen, false);
|
||||
wm_draw_window_onscreen(C, win, -1);
|
||||
wm_draw_window_onscreen(C, win, -1, false);
|
||||
GPU_offscreen_unbind(offscreen, false);
|
||||
GPU_offscreen_read_color(offscreen, GPU_DATA_UBYTE, rect);
|
||||
GPU_offscreen_free(offscreen);
|
||||
|
@ -1350,7 +1409,7 @@ bool WM_window_pixels_read_sample_from_offscreen(bContext *C,
|
|||
|
||||
float rect_pixel[4];
|
||||
GPU_offscreen_bind(offscreen, false);
|
||||
wm_draw_window_onscreen(C, win, -1);
|
||||
wm_draw_window_onscreen(C, win, -1, false);
|
||||
GPU_offscreen_unbind(offscreen, false);
|
||||
GPU_offscreen_read_color_region(offscreen, GPU_DATA_FLOAT, pos[0], pos[1], 1, 1, rect_pixel);
|
||||
GPU_offscreen_free(offscreen);
|
||||
|
@ -1495,7 +1554,12 @@ void wm_draw_update(bContext *C)
|
|||
|
||||
BKE_image_free_unused_gpu_textures();
|
||||
|
||||
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
||||
const bool xr_session_exists = WM_xr_session_exists(&wm->xr);
|
||||
// if(xr_session_exists){
|
||||
// BLI_assert(BLI_listbase_count(wm->xr->runtime->))
|
||||
// }
|
||||
int wn_index;
|
||||
LISTBASE_FOREACH_INDEX (wmWindow *, win, &wm->windows, wn_index) {
|
||||
#ifdef WIN32
|
||||
GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
|
||||
|
||||
|
@ -1519,7 +1583,16 @@ void wm_draw_update(bContext *C)
|
|||
/* notifiers for screen redraw */
|
||||
ED_screen_ensure_updated(C, wm, win, screen);
|
||||
|
||||
wm_draw_window(C, win);
|
||||
GPUOffScreen *xr_mirror_BUI_to_hmd_screen = NULL;
|
||||
const bool draw_to_blender_ui_mirror = (wm->xr.session_settings.flag &
|
||||
XR_SESSION_SHOW_BLENDER_UI_MIRROR) != 0;
|
||||
if (xr_session_exists && draw_to_blender_ui_mirror) {
|
||||
// BLI_assert(wn_index < BLI_)
|
||||
LinkData *ld = BLI_findlink(&wm->xr.full_blender_ui_screens, wn_index);
|
||||
if (ld != NULL)
|
||||
xr_mirror_BUI_to_hmd_screen = ld->data;
|
||||
}
|
||||
wm_draw_window(C, win, xr_mirror_BUI_to_hmd_screen);
|
||||
wm_draw_update_clear_window(C, win);
|
||||
|
||||
wm_window_swap_buffers(win);
|
||||
|
|
|
@ -73,10 +73,10 @@ void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
|
|||
immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
||||
immAttr2f(texcoord, halfx, halfy);
|
||||
immVertex2f(pos, soffx, 0.0f);
|
||||
immVertex2f(pos, soffx, 0);
|
||||
|
||||
immAttr2f(texcoord, 1.0f + halfx, halfy);
|
||||
immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f);
|
||||
immVertex2f(pos, soffx + (sizex * 0.5f), 0);
|
||||
|
||||
immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy);
|
||||
immVertex2f(pos, soffx + (sizex * 0.5f), sizey);
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
#include "GPU_framebuffer.h"
|
||||
#include "GPU_platform.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -101,6 +103,29 @@ bool wm_xr_init(wmWindowManager *wm)
|
|||
if (!wm->xr.runtime) {
|
||||
wm->xr.runtime = wm_xr_runtime_data_create();
|
||||
wm->xr.runtime->context = context;
|
||||
|
||||
// GG: TODO: .. what happens if user deletes a window while in XR session?
|
||||
// so maybe just have a max buffer of offscreens? Otherwise have to sync w/ window
|
||||
// creation/deletion.
|
||||
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
||||
const int width = WM_window_pixels_x(win);
|
||||
const int height = WM_window_pixels_y(win);
|
||||
|
||||
// GG: TODO: I need to use the XR per-eye resolution, not window resolution. Maybe thats
|
||||
// why the UI is blurry? But then, would blender UI drawing implementation.. just work?
|
||||
// There's probably hardcoded areas that query/use the window pixel size...
|
||||
// Though.. maybe im wrong.. because an image quad scnee object w/ blender UI on it appears
|
||||
// fine and not low res/blurry at all..-it is just as blurry when viewed at ~30degrees away
|
||||
// from forward?- so curving the UI is a big help.
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(
|
||||
width, height, false, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, NULL);
|
||||
|
||||
// Dont skip so that indices align with wm->windows, so wm_draw_window() can draw to proper
|
||||
// window offscreen buffer if (offscreen == NULL)
|
||||
// continue;
|
||||
|
||||
BLI_addtail(&wm->xr.full_blender_ui_screens, BLI_genericNodeN(offscreen));
|
||||
}
|
||||
}
|
||||
}
|
||||
BLI_assert(wm->xr.runtime && wm->xr.runtime->context);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "ED_view3d_offscreen.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_Types.h"
|
||||
#include "GPU_batch_presets.h"
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_matrix.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
|
||||
#include "wm_surface.h"
|
||||
#include "wm_xr_intern.h"
|
||||
typedef struct GHOST_XrPose;
|
||||
|
||||
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4])
|
||||
{
|
||||
|
@ -93,7 +95,14 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data,
|
|||
/* Apply base pose and navigation. */
|
||||
wm_xr_pose_scale_to_imat(&draw_data->base_pose, draw_data->base_scale, base_inv);
|
||||
wm_xr_pose_scale_to_imat(&session_state->nav_pose_prev, session_state->nav_scale_prev, nav_inv);
|
||||
mul_m4_m4m4(m, eye_inv, base_inv);
|
||||
|
||||
float viewer_offset[4][4];
|
||||
unit_m4(viewer_offset);
|
||||
rotate_m4(viewer_offset, 'Y', -session_settings->viewer_angle_offset);
|
||||
copy_v3_v3(viewer_offset[3], session_settings->viewer_offset);
|
||||
|
||||
mul_m4_m4m4(m, eye_inv, viewer_offset);
|
||||
mul_m4_m4_post(m, base_inv);
|
||||
mul_m4_m4m4(r_viewmat, m, nav_inv);
|
||||
|
||||
perspective_m4_fov(r_projmat,
|
||||
|
@ -133,6 +142,9 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
|
|||
wmXrSessionState *session_state = &xr_data->runtime->session_state;
|
||||
XrSessionSettings *settings = &xr_data->session_settings;
|
||||
|
||||
// GG: using 0: shows everything: helper lines (knife cut op), wireframes bones, xform gizmos,
|
||||
// etc
|
||||
// const int display_flags = ~0;
|
||||
const int display_flags = V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS | settings->draw_flags;
|
||||
|
||||
float viewmat[4][4], winmat[4][4];
|
||||
|
@ -155,7 +167,14 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
|
|||
/* Some systems have drawing glitches without this. */
|
||||
GPU_clear_depth(1.0f);
|
||||
|
||||
/* Draws the view into the surface_data->viewport's frame-buffers. */
|
||||
// GG: I feel like maybe drawing the BBlender UI can just happen around here and be optional?
|
||||
/* Draws the view into the surface_data->viewport's frame-buffers. Though, perhaps we dont have
|
||||
* access to window data?*/
|
||||
// GG: maybe we need to set CTX_wm_region_set() to use our fake v3d? maybe thats why tools aren't
|
||||
// being drawn in XR? (see editmesh_loopcut.c/search for REGION_DRAW_POST_VIEW They just attach a
|
||||
// cb to the active region. Since we don't see it, then maybe the region isn't being set? or,
|
||||
// maybe its as simple as this offscreen not calling callbacks)
|
||||
|
||||
ED_view3d_draw_offscreen_simple(draw_data->depsgraph,
|
||||
draw_data->scene,
|
||||
&settings->shading,
|
||||
|
@ -175,7 +194,8 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
|
|||
NULL,
|
||||
false,
|
||||
vp->offscreen,
|
||||
vp->viewport);
|
||||
vp->viewport,
|
||||
xr_data->evil_C);
|
||||
|
||||
/* The draw-manager uses both GPUOffscreen and GPUViewport to manage frame and texture buffers. A
|
||||
* call to GPU_viewport_draw_to_screen() is still needed to get the final result from the
|
||||
|
@ -230,6 +250,7 @@ static void wm_xr_controller_model_draw(const XrSessionSettings *settings,
|
|||
GHOST_XrContextHandle xr_context,
|
||||
wmXrSessionState *state)
|
||||
{
|
||||
|
||||
GHOST_XrControllerModelData model_data;
|
||||
|
||||
float color[4];
|
||||
|
@ -334,9 +355,15 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
|
|||
madd_v3_v3v3fl(ray, mat[3], mat[2], -scale);
|
||||
|
||||
immAttrSkip(col);
|
||||
immVertex3fv(pos, mat[3]);
|
||||
// immVertex3fv(pos, mat[3]);
|
||||
// immVertex3f(pos, mat[3][0] + 1, mat[3][1], mat[3][2]);
|
||||
immAttr4ubv(col, color);
|
||||
immVertex3fv(pos, ray);
|
||||
|
||||
// immAttrSkip(col);
|
||||
// immVertex3f(pos, mat[3][0] + 1, mat[3][1], mat[3][2]);
|
||||
// immAttr4ubv(col, color);
|
||||
// immVertex3f(pos, ray[0] + 1, ray[1], ray[2]);
|
||||
}
|
||||
|
||||
immEnd();
|
||||
|
@ -357,7 +384,7 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
|
|||
const float(*mat)[4] = controller->aim_mat;
|
||||
madd_v3_v3v3fl(x_axis, mat[3], mat[0], scale);
|
||||
madd_v3_v3v3fl(y_axis, mat[3], mat[1], scale);
|
||||
madd_v3_v3v3fl(z_axis, mat[3], mat[2], scale);
|
||||
madd_v3_v3v3fl(z_axis, mat[3], mat[2], scale * 5);
|
||||
|
||||
immAttrSkip(col);
|
||||
immVertex3fv(pos, mat[3]);
|
||||
|
@ -385,9 +412,639 @@ void wm_xr_draw_controllers(const bContext *UNUSED(C), ARegion *UNUSED(region),
|
|||
{
|
||||
wmXrData *xr = customdata;
|
||||
const XrSessionSettings *settings = &xr->session_settings;
|
||||
|
||||
if ((settings->flag & XR_SESSION_SHOW_CONTROLLERS) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GHOST_XrContextHandle xr_context = xr->runtime->context;
|
||||
wmXrSessionState *state = &xr->runtime->session_state;
|
||||
|
||||
wm_xr_controller_model_draw(settings, xr_context, state);
|
||||
wm_xr_controller_aim_draw(settings, state);
|
||||
}
|
||||
|
||||
// GG: draw blender UI, need to have access to all regions
|
||||
void draw_mirror_blender_ui_to_xr(const bContext *UNUSED(C),
|
||||
ARegion *UNUSED(region),
|
||||
void *customdata)
|
||||
{
|
||||
wmXrData *xr = customdata;
|
||||
const XrSessionSettings *settings = &xr->session_settings;
|
||||
|
||||
if ((settings->flag & XR_SESSION_SHOW_BLENDER_UI_MIRROR) == 0) {
|
||||
return;
|
||||
}
|
||||
// GG: TIP: Setting UI Resolution in prefs to 1.5+ makes the mirrored UI extrmely readable, along
|
||||
// w/ setting text rendering to full and using AA. You can also plain make the window itself
|
||||
// larger and span across multiple monitors before starting the XR session (not as effective
|
||||
// though).
|
||||
|
||||
// GG: TIP: Placing raycast origin aligned with nose or lower isn't jarring, probably least
|
||||
// jarring
|
||||
// of all possible placements (probably because we've learned to ignore our nose). Next least
|
||||
// jarring is to palce the raycast on our shoulder but then rotating objects is slightly off,
|
||||
// enough to notice but not enough to make it unusable. Best place is under the nose.
|
||||
|
||||
// GG: TIP: TO get more wokring space, just use a single window thats wide and extends mupltiple
|
||||
// monitors. Its better than using multiple window since cursor capture is slow when moving
|
||||
// between
|
||||
// windows.
|
||||
// GG: TODO: use camera origin + forward projected onto quad sphere as the ui origin (suhc that
|
||||
// its
|
||||
// where the center of the screenspace v3D is in viewspace.
|
||||
// (base_pose.location + base_pose.forawrd * radius)
|
||||
// This also makes it the scale origin so that changing scale in the ui props doesn't affect
|
||||
// the v3D center point in vr space, which is what the user calibrates their UI pos/scale/rads
|
||||
// to.
|
||||
|
||||
// GG: TODO: default ui offset should be centered on raycast origin. Currently its higher up than
|
||||
// expected by 0.5 * ui_height
|
||||
GPUVertFormat *format;
|
||||
uint texcoord;
|
||||
uint pos;
|
||||
uint col;
|
||||
|
||||
float ui_width = 1920;
|
||||
float ui_height = 1080;
|
||||
if (!BLI_listbase_is_empty(&xr->full_blender_ui_screens)) {
|
||||
GPUOffScreen *any_screen = ((LinkData *)xr->full_blender_ui_screens.first)->data;
|
||||
if (any_screen) {
|
||||
ui_width = GPU_offscreen_width(any_screen);
|
||||
// / 4.0f; // xr->ui_res_scaling_factor;
|
||||
ui_height = GPU_offscreen_height(any_screen);
|
||||
// / 4.0f; // xr->ui_res_scaling_factor;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: really should alpha clip v3D pixels instead of just doing alpha blend. (maybe try
|
||||
// colormask?)
|
||||
// since non-clip still writes to depth buffer.
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
||||
/**
|
||||
* OK, so I think that the entire blenderUI should
|
||||
* just be fully rendered on XR again instead of just
|
||||
* being blitted. This allows python users to draw
|
||||
* overlays specifically for the XR device for non
|
||||
* view3D's, or do things specifically when seen through XR.
|
||||
* ...Q:... if XR is already only drawn for XR view3D,
|
||||
* then shouldnt some caller high up be able to draw
|
||||
* to the same space and even have access to the entire
|
||||
* blender UI?
|
||||
*/
|
||||
|
||||
float base_pose_mat[4][4];
|
||||
GHOST_XrPose *base_pose = &xr->runtime->session_state.prev_base_pose;
|
||||
wm_xr_pose_to_mat(base_pose, base_pose_mat);
|
||||
float resx = 2.0f;
|
||||
const float resy_per_x = (ui_height / ui_width);
|
||||
float resy = resy_per_x * resx;
|
||||
float halfresx = resx * 0.5f;
|
||||
float halfresy = resy * 0.5f;
|
||||
// GG: window iter from L1534
|
||||
// GG: TODO: really, only need one window, the main one that user is using.
|
||||
|
||||
// float fmouse_xyz[3] = {xr->runtime->mouse_xy[0], xr->runtime->mouse_xy[1], ui_distance};
|
||||
// // Normalize mouse coords to UI resolution.
|
||||
// fmouse_xyz[0] /= ui_width;
|
||||
// fmouse_xyz[1] /= ui_height;
|
||||
// fmouse_xyz[0] *= resx;
|
||||
// fmouse_xyz[1] *= resy;
|
||||
// fmouse_xyz[0] -= halfresx;
|
||||
// fmouse_xyz[1] -= halfresy;
|
||||
// float fmouse_xyz_screenspace[3];
|
||||
// copy_v3_v3(fmouse_xyz_screenspace, fmouse_xyz);
|
||||
// mul_m4_v3(base_pose_mat, fmouse_xyz);
|
||||
// float fmouse_mat[4][4];
|
||||
// unit_m4(fmouse_mat);
|
||||
// copy_v3_v3(fmouse_mat[3], fmouse_xyz);
|
||||
// copy_m3_m3(fmouse_mat, base_pose_mat);
|
||||
// mul_m4_m4m4(fmouse_mat, base_pose_mat, fmouse_mat);
|
||||
|
||||
// unit_m4(fmouse_mat);
|
||||
// float color[4] = {0, 0, 1, 1};
|
||||
// GPUBatch *sphere = GPU_batch_preset_sphere(0);
|
||||
// GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
// GPU_batch_uniform_4fv(sphere, "color", color);
|
||||
|
||||
// GPU_matrix_push();
|
||||
// GPU_matrix_set(base_pose_mat);
|
||||
////GPU_matrix_set(fmouse_mat);
|
||||
// GPU_matrix_scale_1f(0.1f);
|
||||
// GPU_batch_draw(sphere);
|
||||
// GPU_matrix_pop();
|
||||
|
||||
bool is_mouse_over_v3d = (xr->runtime->flags & XR_RUNTIME_IS_MOUSE_OVER_V3D) != 0;
|
||||
|
||||
if (is_mouse_over_v3d) {
|
||||
format = immVertexFormat();
|
||||
pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR);
|
||||
float viewport[4];
|
||||
GPU_viewport_size_get_f(viewport);
|
||||
immUniform2fv("viewportSize", &viewport[2]);
|
||||
|
||||
// immUniform1f("lineWidth", 1); // 3.0f * U.pixelsize);//thinner is easier on eyes
|
||||
immUniform1f("lineWidth", 10.0f * U.pixelsize); // thinner is easier on eyes
|
||||
|
||||
// GG:TODO: replace with drawing blender UI to a quad (then eventually sphere quad)
|
||||
// currently just ensuring XR arbitrary drawing.
|
||||
|
||||
immBeginAtMost(GPU_PRIM_LINE_STRIP, 16);
|
||||
|
||||
// consider starting ray at mouse? or atleast screen? (since mouse may not match w/ ray)
|
||||
immAttr3f(col, 0, 0, 1);
|
||||
float raycast_startpoint[3];
|
||||
copy_v3_v3(raycast_startpoint, xr->runtime->v3d_ray_dir);
|
||||
// starting depth of drawn ray, dont want it to be too closer to user's eyes
|
||||
mul_v3_fl(raycast_startpoint, xr->session_settings.cursor_raycast_distance0);
|
||||
add_v3_v3(raycast_startpoint, xr->runtime->v3d_origin);
|
||||
immVertex3fv(pos, raycast_startpoint);
|
||||
|
||||
immAttr3f(col, 0, 1, 0);
|
||||
float raycast_endpoint[3];
|
||||
copy_v3_v3(raycast_endpoint, xr->runtime->v3d_ray_dir);
|
||||
mul_v3_fl(raycast_endpoint, xr->session_settings.cursor_raycast_distance1);
|
||||
add_v3_v3(raycast_endpoint, xr->runtime->v3d_origin);
|
||||
immVertex3fv(pos, raycast_endpoint);
|
||||
|
||||
immAttr3f(col, 1, 0, 0);
|
||||
copy_v3_v3(raycast_endpoint, xr->runtime->v3d_ray_dir);
|
||||
mul_v3_fl(raycast_endpoint, xr->session_settings.cursor_raycast_distance2);
|
||||
add_v3_v3(raycast_endpoint, xr->runtime->v3d_origin);
|
||||
immVertex3fv(pos, raycast_endpoint);
|
||||
|
||||
immEnd();
|
||||
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
float viewspace_from_worldspace[4][4];
|
||||
float worldspace_from_viewspace[4][4];
|
||||
copy_m4_m4(worldspace_from_viewspace, base_pose_mat);
|
||||
invert_m4_m4(viewspace_from_worldspace, worldspace_from_viewspace);
|
||||
|
||||
float rads_per_viewspace_unit = 1;
|
||||
float total_rads_per_ui_width = xr->session_settings.mirrored_ui_rads_span;
|
||||
const float rads_per_pixel = total_rads_per_ui_width / ui_width;
|
||||
float viewspace_ui_height = 0;
|
||||
float window_origin_viewspace[3] = {0, 0, 0};
|
||||
{
|
||||
mul_m4_v3(xr->runtime->worldspace_from_windowspace, window_origin_viewspace);
|
||||
mul_m4_v3(viewspace_from_worldspace, window_origin_viewspace);
|
||||
}
|
||||
{
|
||||
float viewspace_unit_per_rad_vec[3] = {1.0 / rads_per_pixel, 0, 0};
|
||||
mul_m4_v3(xr->runtime->worldspace_from_windowspace, viewspace_unit_per_rad_vec);
|
||||
mul_m4_v3(viewspace_from_worldspace, viewspace_unit_per_rad_vec);
|
||||
sub_v3_v3(viewspace_unit_per_rad_vec, window_origin_viewspace);
|
||||
rads_per_viewspace_unit = 1.0 / len_v3(viewspace_unit_per_rad_vec);
|
||||
|
||||
float window_top_left_viewspace[3] = {0, ui_height, 0};
|
||||
mul_m4_v3(xr->runtime->worldspace_from_windowspace, window_top_left_viewspace);
|
||||
mul_m4_v3(viewspace_from_worldspace, window_top_left_viewspace);
|
||||
sub_v3_v3(window_top_left_viewspace, window_origin_viewspace);
|
||||
viewspace_ui_height = len_v3(window_top_left_viewspace);
|
||||
}
|
||||
|
||||
float center_viewspace[3] = {ui_width / 2.0f, ui_height / 2.0f, 0};
|
||||
mul_m4_v3(xr->runtime->worldspace_from_windowspace, center_viewspace);
|
||||
// curve the UI so its easier to read (for now its at an arbitrary distance)
|
||||
mul_m4_v3(viewspace_from_worldspace, center_viewspace);
|
||||
float radius = len_v3(center_viewspace) * 2.0f *
|
||||
xr->session_settings.mirrored_ui_distance_factor;
|
||||
float ui_width_arclength = total_rads_per_ui_width * radius;
|
||||
|
||||
float pre_ui_width = ui_width;
|
||||
float pre_ui_height = ui_height;
|
||||
|
||||
int windex;
|
||||
|
||||
bool hide_ui_on_mouse_over_v3d = (xr->session_settings.flag &
|
||||
XR_SESSION_HIDE_UI_MIRROR_ON_MOUSE_OVER_V3D) != 0;
|
||||
|
||||
float mirror_ui_camera_center_viewspace[3] = {0, 0, radius};
|
||||
if (!hide_ui_on_mouse_over_v3d || !is_mouse_over_v3d) {
|
||||
LISTBASE_FOREACH_INDEX (LinkData *, ld, &xr->full_blender_ui_screens, windex) {
|
||||
GPUOffScreen *offscreen = ld->data;
|
||||
if (offscreen == NULL)
|
||||
continue;
|
||||
ui_width = GPU_offscreen_width(offscreen);
|
||||
ui_height = GPU_offscreen_height(offscreen);
|
||||
short window_pos_x = 0;
|
||||
short window_pos_y = 0;
|
||||
if (windex < 32) {
|
||||
window_pos_x = xr->window_positions_xy[windex * 2 + 0];
|
||||
window_pos_y = xr->window_positions_xy[windex * 2 + 1];
|
||||
}
|
||||
|
||||
/* Setup offscreen color texture for drawing. */
|
||||
GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
|
||||
|
||||
GPU_texture_bind(texture, 0);
|
||||
/* No mipmaps or filtering. */
|
||||
// GPU_texture_mipmap_mode(texture, false, false);
|
||||
GPU_texture_mipmap_mode(texture, true, true);
|
||||
// wmWindowViewport(win); // not necessary?
|
||||
|
||||
// float vp_mat[4][4];
|
||||
// GPU_matrix_model_view_projection_get();
|
||||
// immUniformMatrix4fv("ModelViewProjectionMatrix",);
|
||||
// GPU_matrix_push()
|
||||
|
||||
// float vert_positions[3 * 4] = {
|
||||
// -halfresx,
|
||||
// -halfresy,
|
||||
// ui_distance,
|
||||
// //
|
||||
// halfresx,
|
||||
// -halfresy,
|
||||
// ui_distance,
|
||||
// //
|
||||
// halfresx,
|
||||
// halfresy,
|
||||
// ui_distance,
|
||||
// //
|
||||
// -halfresx,
|
||||
// halfresy,
|
||||
// ui_distance,
|
||||
// };
|
||||
|
||||
// window space vert positoins (basically pixel coords)
|
||||
int total_verts = 4;
|
||||
// float vert_positions[3 * 4] = {
|
||||
// 0,
|
||||
// 0,
|
||||
// 0,
|
||||
// //
|
||||
// ui_width,
|
||||
// 0,
|
||||
// 0,
|
||||
// //
|
||||
// ui_width,
|
||||
// ui_height,
|
||||
// 0,
|
||||
// //
|
||||
// 0,
|
||||
// ui_height,
|
||||
// 0,
|
||||
// };
|
||||
// float vert_texcoords[2 * 4] = {0,
|
||||
// 0,
|
||||
// //
|
||||
// 1,
|
||||
// 0,
|
||||
// //
|
||||
// 1,
|
||||
// 1,
|
||||
// //
|
||||
// 0,
|
||||
// 1};
|
||||
|
||||
#define vertices_per_width 32
|
||||
total_verts = (vertices_per_width + 0) * (vertices_per_width + 0);
|
||||
float vert_positions[3 * (vertices_per_width + 0) * (vertices_per_width + 0)];
|
||||
float vert_texcoords[2 * (vertices_per_width + 0) * (vertices_per_width + 0)];
|
||||
for (int y = 0; y < vertices_per_width; y++) {
|
||||
for (int x = 0; x < vertices_per_width; x++) {
|
||||
int vert_index = (x + y * vertices_per_width);
|
||||
float mu_x = ((float)x / (vertices_per_width - 1));
|
||||
float mu_y = ((float)y / (vertices_per_width - 1));
|
||||
vert_positions[vert_index * 3 + 0] = mu_x * ui_width;
|
||||
vert_positions[vert_index * 3 + 1] = mu_y * ui_height;
|
||||
vert_positions[vert_index * 3 + 2] = 0;
|
||||
// float z = fabsf((mu_x - 0.5f) * 2.0f * ui_width);
|
||||
// vert_positions[vert_index * 3 + 2] = .2 * z * z;
|
||||
/*
|
||||
z = fabs((mu_x - 0.5f) * 2.0f * ui_width);
|
||||
vert_positions[vert_index * 3 + 2] = .001f * z * z;*/
|
||||
/* z = mu_x;
|
||||
vert_positions[vert_index * 3 + 2] = 5 * ui_width * -sin(z * 3.14);
|
||||
vert_positions[vert_index * 3 + 0] = -.4 * ui_width * sin((mu_x + 0.5) * 3.14) +
|
||||
.5 * ui_width;*/
|
||||
// vert_positions[vert_index * 3 + 2] = mu_x * 10;
|
||||
|
||||
// float base_length = 500;
|
||||
// float center_xz[2] = {(0.5f * ui_width), 10*base_length};
|
||||
// float vec[2] = {vert_positions[vert_index * 3 + 0], vert_positions[vert_index * 3 +
|
||||
// 2]}; sub_v2_v2(vec, center_xz); normalize_v2_length(vec, base_length); add_v2_v2(vec,
|
||||
// center_xz); vert_positions[vert_index * 3 + 0] = vec[0]; vert_positions[vert_index * 3
|
||||
// + 2] = vec[1];
|
||||
/*
|
||||
float center[3] = {0.5f * ui_width, 0.5f * ui_height, -1000};
|
||||
sub_v3_v3(&vert_positions[vert_index * 3], center);
|
||||
normalize_v3_length(&vert_positions[vert_index * 3], 1000);
|
||||
add_v3_v3(&vert_positions[vert_index * 3], center);*/
|
||||
|
||||
vert_texcoords[vert_index * 2 + 0] = mu_x;
|
||||
vert_texcoords[vert_index * 2 + 1] = mu_y;
|
||||
}
|
||||
}
|
||||
|
||||
#define tri_buffer_len (2 * 3 * (vertices_per_width + -1) * (vertices_per_width + -1))
|
||||
int tri_index_buffer[tri_buffer_len];
|
||||
for (int y = 0; y < vertices_per_width - 1; y++) {
|
||||
for (int x = 0; x < vertices_per_width - 1; x++) {
|
||||
int vert_index = (x + y * vertices_per_width);
|
||||
int tri_index = (x + y * (vertices_per_width - 1));
|
||||
tri_index_buffer[tri_index * 6 + 0] = vert_index;
|
||||
tri_index_buffer[tri_index * 6 + 1] = ((x + 0) + (y + 1) * vertices_per_width);
|
||||
tri_index_buffer[tri_index * 6 + 2] = ((x + 1) + (y + 1) * vertices_per_width);
|
||||
|
||||
tri_index_buffer[tri_index * 6 + 3] = vert_index;
|
||||
tri_index_buffer[tri_index * 6 + 4] = ((x + 1) + (y + 1) * vertices_per_width);
|
||||
tri_index_buffer[tri_index * 6 + 5] = ((x + 1) + (y + 0) * vertices_per_width);
|
||||
}
|
||||
}
|
||||
|
||||
// int soffx = 0;
|
||||
// const int sizex = WM_window_pixels_x(win);
|
||||
// const int sizey = WM_window_pixels_y(win);
|
||||
|
||||
// /* wmOrtho for the screen has this same offset */
|
||||
// const float halfx = GLA_PIXEL_OFS / sizex;
|
||||
// const float halfy = GLA_PIXEL_OFS / sizex;
|
||||
|
||||
/* Texture is already bound to GL_TEXTURE0 unit. */
|
||||
// DONE: so the rads origin (vert pos X) and the screen space to viewpsace origin need to
|
||||
// match
|
||||
// w/ camera forward as zero.
|
||||
float vert_pos_viewspace[3];
|
||||
for (int i = 0; i < total_verts; i++) {
|
||||
float *vert_position = &vert_positions[i * 3];
|
||||
// vert_position[1] = (vert_position[1] / ui_height);
|
||||
// GG: TODO: scale from center of view3D instead of bottom left corner since the user
|
||||
// sets up their mirror UI offsets based on the raycast range/area. Currently the scaling
|
||||
// moves the entire UI/v3d area so it no longer matches with the raycast effective
|
||||
// range/area thus the user will have to re-offset everything again.
|
||||
// mul_v3_fl(vert_position, xr->session_settings.mirrored_ui_scale);
|
||||
// angle span and ui_scale counter eachother, so need yscale for really wide windows to see
|
||||
// better
|
||||
vert_position[1] *= xr->session_settings.mirrored_ui_scale_y;
|
||||
|
||||
add_v2_v2(vert_position, xr->session_settings.mirrored_ui_offset);
|
||||
// better Y default. than zero
|
||||
vert_position[1] -= ui_height * 0.5 * xr->session_settings.mirrored_ui_scale_y;
|
||||
vert_position[0] += window_pos_x;
|
||||
vert_position[1] += window_pos_y;
|
||||
|
||||
mul_m4_v3(xr->runtime->worldspace_from_windowspace, vert_position);
|
||||
|
||||
mul_m4_v3(viewspace_from_worldspace, vert_position);
|
||||
|
||||
float offset_from_origin_viewspace[3];
|
||||
copy_v3_v3(offset_from_origin_viewspace, vert_position);
|
||||
sub_v3_v3(offset_from_origin_viewspace, window_origin_viewspace);
|
||||
|
||||
// I'm assuming that the UI is planar, which it is, and that viewspace up is aligned with
|
||||
// UI up, which I think is true.
|
||||
vert_position[1] = (offset_from_origin_viewspace[1] / viewspace_ui_height) *
|
||||
(ui_width_arclength * resy_per_x);
|
||||
|
||||
sub_v3_v3(vert_position, mirror_ui_camera_center_viewspace);
|
||||
|
||||
float radsxz = -vert_position[0] * rads_per_viewspace_unit;
|
||||
radsxz += 3.14;
|
||||
float xz_rotation_forward[3] = {sinf(radsxz), 0, cosf(radsxz)};
|
||||
vert_position[0] = xz_rotation_forward[0] * radius;
|
||||
vert_position[2] = xz_rotation_forward[2] * radius;
|
||||
|
||||
// float viewspace_up[3] = {0, 1, 0};
|
||||
// float secondary_rotation_axis[3];
|
||||
// cross_v3_v3v3(secondary_rotation_axis, viewspace_up, xz_rotation_forward);
|
||||
//
|
||||
// float radsyz = -vert_position[1] * rads_per_viewspace_unit;
|
||||
|
||||
////radsyz += 3.14;
|
||||
// rotate_v3_v3v3fl(vert_position, xz_rotation_forward, secondary_rotation_axis, radsyz);
|
||||
// normalize_v3_length(vert_position, radius);
|
||||
|
||||
mul_m4_v3(worldspace_from_viewspace, vert_position);
|
||||
}
|
||||
//// curve the UI so its easier to read (for now its at an arbitrary distance)
|
||||
// mul_m4_v3(viewspace_from_worldspace, &vert_positions[i * 3]);
|
||||
//// float v2[2] = {vert_positions[i * 3 + 0], vert_positions[i * 3 + 2]};
|
||||
// normalize_v3_length(&vert_positions[i * 3], radius);
|
||||
// mul_m4_v3(worldspace_from_viewspace, &vert_positions[i * 3]);
|
||||
format = immVertexFormat();
|
||||
texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
// draw UI Xrayed through objects. (a bit annoying for animating, but nice in general..?)
|
||||
if ((xr->session_settings.flag & XR_SESSION_USE_UI_MIRROR_XRAY) != 0) {
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR);
|
||||
float gray = 0.75f;
|
||||
immUniformColor4f(0, gray, 0, 0.5f);
|
||||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
GPU_depth_mask(false);
|
||||
immBegin(GPU_PRIM_TRIS, tri_buffer_len);
|
||||
|
||||
// for (int i = 0; i < total_verts; i++) {
|
||||
// immAttr2fv(texcoord, &vert_texcoords[i * 2]);
|
||||
// immVertex3fv(pos, &vert_positions[i * 3]);
|
||||
// }
|
||||
|
||||
for (int i = 0; i < tri_buffer_len; i++) {
|
||||
int vertex_index = tri_index_buffer[i];
|
||||
immAttr2fv(texcoord, &vert_texcoords[vertex_index * 2]);
|
||||
immVertex3fv(pos, &vert_positions[vertex_index * 3]);
|
||||
}
|
||||
|
||||
immEnd();
|
||||
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE);
|
||||
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
||||
GPU_depth_mask(true);
|
||||
immBegin(GPU_PRIM_TRIS, tri_buffer_len);
|
||||
// immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// immAttr2fv(texcoord, &vert_texcoords[i * 2]);
|
||||
// immVertex3fv(pos, &vert_positions[i * 3]);
|
||||
// }
|
||||
|
||||
for (int i = 0; i < tri_buffer_len; i++) {
|
||||
int vertex_index = tri_index_buffer[i];
|
||||
immAttr2fv(texcoord, &vert_texcoords[vertex_index * 2]);
|
||||
immVertex3fv(pos, &vert_positions[vertex_index * 3]);
|
||||
}
|
||||
immEnd();
|
||||
immUnbindProgram();
|
||||
|
||||
GPU_texture_unbind(texture);
|
||||
#undef vertices_per_width
|
||||
#undef tri_buffer_len
|
||||
}
|
||||
}
|
||||
ui_width = pre_ui_width;
|
||||
ui_height = pre_ui_height;
|
||||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
GPU_depth_mask(false);
|
||||
|
||||
format = immVertexFormat();
|
||||
pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
|
||||
|
||||
// GG:TODO: replace with drawing blender UI to a quad (then eventually sphere quad)
|
||||
// currently just ensuring XR arbitrary drawing.
|
||||
immBeginAtMost(GPU_PRIM_TRI_FAN, 4);
|
||||
// float size = 0.005f;
|
||||
float size = 6;
|
||||
float mverts[3 * 4] = {
|
||||
-size,
|
||||
-size,
|
||||
0, // size * .5f,
|
||||
//
|
||||
size,
|
||||
-size,
|
||||
0, // size * .5f,
|
||||
//
|
||||
size,
|
||||
size,
|
||||
0, // size * .5f,
|
||||
//
|
||||
-size,
|
||||
size,
|
||||
0, // size * .5f,
|
||||
};
|
||||
float windowspace_from_mouse[4][4];
|
||||
unit_m4(windowspace_from_mouse);
|
||||
|
||||
// windowspace_from_mouse[3][0] = xr->runtime->mouse_xy[0];
|
||||
// windowspace_from_mouse[3][1] = xr->runtime->mouse_xy[1];
|
||||
windowspace_from_mouse[3][0] = xr->mouse_position_global_xy[0];
|
||||
windowspace_from_mouse[3][1] = xr->mouse_position_global_xy[1];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// mul_m4_v3(fmouse_mat, &mverts[i * 3]);
|
||||
float *vert_position = &mverts[i * 3];
|
||||
|
||||
mul_m4_v3(windowspace_from_mouse, &mverts[i * 3]);
|
||||
// GG: TODO: scale from center of view3D instead of bottom left corner since the user
|
||||
// sets up their mirror UI offsets based on the raycast range/area. Currently the scaling
|
||||
// moves the entire UI/v3d area so it no longer matches with the raycast effective range/area
|
||||
// thus the user will have to re-offset everything again.
|
||||
// mul_v3_fl(vert_position, xr->session_settings.mirrored_ui_scale);
|
||||
// angle span and ui_scale counter eachother, so need yscale for really wide windows to see
|
||||
// better
|
||||
vert_position[1] *= xr->session_settings.mirrored_ui_scale_y;
|
||||
add_v2_v2(vert_position, xr->session_settings.mirrored_ui_offset);
|
||||
// better Y default. than zero
|
||||
vert_position[1] -= ui_height * 0.5 * xr->session_settings.mirrored_ui_scale_y;
|
||||
|
||||
mul_m4_v3(xr->runtime->worldspace_from_windowspace, &mverts[i * 3]);
|
||||
|
||||
mul_m4_v3(viewspace_from_worldspace, vert_position);
|
||||
|
||||
float offset_from_origin_viewspace[3];
|
||||
copy_v3_v3(offset_from_origin_viewspace, vert_position);
|
||||
sub_v3_v3(offset_from_origin_viewspace, window_origin_viewspace);
|
||||
|
||||
// I'm assuming that the UI is planar, which it is, and that viewspace up is aligned with UI
|
||||
// up, which I think is true.
|
||||
vert_position[1] = (offset_from_origin_viewspace[1] / viewspace_ui_height) *
|
||||
(ui_width_arclength * resy_per_x);
|
||||
|
||||
sub_v3_v3(vert_position, mirror_ui_camera_center_viewspace);
|
||||
|
||||
float radsxz = -vert_position[0] * rads_per_viewspace_unit;
|
||||
float width_arclength = radsxz * radius;
|
||||
radsxz += 3.14;
|
||||
float xz_rotation_forward[3] = {sinf(radsxz), 0, cosf(radsxz)};
|
||||
vert_position[0] = xz_rotation_forward[0] * radius * 0.999f;
|
||||
vert_position[2] = xz_rotation_forward[2] * radius * 0.999f; // NOTE: only use 0.99f on final
|
||||
// vert_position[1] = (vert_position[1] / ui_width) * (width_arclength * resy_per_x);
|
||||
//
|
||||
|
||||
//
|
||||
// float viewspace_up[3] = {0, 1, 0};
|
||||
// float secondary_rotation_axis[3];
|
||||
// cross_v3_v3v3(secondary_rotation_axis, viewspace_up, xz_rotation_forward);
|
||||
|
||||
// float radsyz = -vert_position[1] * rads_per_viewspace_unit;
|
||||
|
||||
//// radsyz += 3.14;
|
||||
// rotate_v3_v3v3fl(vert_position, xz_rotation_forward, secondary_rotation_axis, radsyz);
|
||||
// normalize_v3_length(vert_position, radius * 0.99f);
|
||||
|
||||
mul_m4_v3(worldspace_from_viewspace, vert_position);
|
||||
}
|
||||
// top left
|
||||
immAttr4f(col, 1, 1, 1, 0.5f);
|
||||
immVertex3fv(pos, &mverts[0]);
|
||||
|
||||
// top right
|
||||
immAttr4f(col, 1, 1, 1, 0.5f);
|
||||
immVertex3fv(pos, &mverts[3]);
|
||||
|
||||
// bottom left
|
||||
immAttr4f(col, 1, 1, 1, 0.5f);
|
||||
immVertex3fv(pos, &mverts[6]);
|
||||
|
||||
// bottom right
|
||||
immAttr4f(col, 1, 1, 1, 0.5f);
|
||||
immVertex3fv(pos, &mverts[9]);
|
||||
|
||||
immEnd();
|
||||
|
||||
const int floats_per_vert = 3;
|
||||
const int verts_per_line = 2;
|
||||
const int total_lines = 3;
|
||||
float line_lengths = 0.1;
|
||||
const int total_verts = 6;
|
||||
float scene_cursor_verts[3 * 2 * 3] = {
|
||||
// X-axis
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
//
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
// Y-axis
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
//
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
// Z-axis
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
//
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
};
|
||||
|
||||
float *scene_cursor_location = xr->runtime->cursor_location_worldspace;
|
||||
|
||||
for (int i = 0; i < total_verts; i++) {
|
||||
float *vert_position = &scene_cursor_verts[i * 3];
|
||||
mul_v3_fl(vert_position, line_lengths);
|
||||
add_v3_v3(vert_position, scene_cursor_location);
|
||||
}
|
||||
|
||||
immBegin(GPU_PRIM_LINES, total_verts);
|
||||
|
||||
for (int i = 0; i < total_verts; i++) {
|
||||
float *vert_position = &scene_cursor_verts[i * 3];
|
||||
immAttr4f(col, 1, 1, 0, 0.5f);
|
||||
immVertex3fv(pos, vert_position);
|
||||
}
|
||||
immEnd();
|
||||
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
}
|
||||
|
|
|
@ -78,8 +78,29 @@ typedef struct wmXrRuntimeData {
|
|||
ListBase actionmaps; /* #XrActionMap */
|
||||
short actactionmap;
|
||||
short selactionmap;
|
||||
|
||||
int flags;
|
||||
int _pad;
|
||||
|
||||
int mouse_xy[2];
|
||||
float v3d_origin[3];
|
||||
float v3d_ray_dir[3];
|
||||
float worldspace_from_windowspace[4][4];
|
||||
float viewspace_from_worldspace[4][4];
|
||||
float worldspace_from_viewspace[4][4];
|
||||
float cursor_location_worldspace[3];
|
||||
float _pad1;
|
||||
// float ui_res_scaling_factor;
|
||||
// ideal palce for this, but this etnire struct is intern..
|
||||
// // GG: Might need to store some kind of handle/ref to window so that
|
||||
// // wm_draw_window() can draw to the proper offscreen buffer?
|
||||
// ListBase full_blender_ui_screens; /* #LinkData of GPUOffScreen */
|
||||
} wmXrRuntimeData;
|
||||
|
||||
enum wmXrRuntimeDataFlags {
|
||||
XR_RUNTIME_IS_MOUSE_OVER_V3D = (1 << 0),
|
||||
};
|
||||
|
||||
typedef struct wmXrViewportPair {
|
||||
struct wmXrViewportPair *next, *prev;
|
||||
struct GPUOffScreen *offscreen;
|
||||
|
@ -94,6 +115,7 @@ typedef struct {
|
|||
struct ARegionType *controller_art;
|
||||
/** Controller draw callback handle. */
|
||||
void *controller_draw_handle;
|
||||
void *draw_mirror_blender_ui_to_xr;
|
||||
} wmXrSurfaceData;
|
||||
|
||||
typedef struct wmXrDrawData {
|
||||
|
@ -234,3 +256,10 @@ void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_ima
|
|||
*/
|
||||
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata);
|
||||
void wm_xr_draw_controllers(const struct bContext *C, struct ARegion *region, void *customdata);
|
||||
void draw_mirror_blender_ui_to_xr(const struct bContext *C,
|
||||
struct ARegion *region,
|
||||
void *customdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -128,7 +128,6 @@ static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
v3d->runtime.flag |= V3D_RUNTIME_XR_SESSION_ROOT;
|
||||
wm_xr_session_toggle(wm, win, wm_xr_session_update_screen_on_exit_cb);
|
||||
wm_xr_session_update_screen(bmain, &wm->xr);
|
||||
|
||||
WM_event_add_notifier(C, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "DRW_engine.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
|
@ -38,6 +40,7 @@
|
|||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "wm_draw.h"
|
||||
#include "wm_event_system.h"
|
||||
#include "wm_surface.h"
|
||||
#include "wm_window.h"
|
||||
|
@ -102,6 +105,13 @@ static void wm_xr_session_exit_cb(void *customdata)
|
|||
|
||||
/* Free the entire runtime data (including session state and context), to play safe. */
|
||||
wm_xr_runtime_data_free(&xr_data->runtime);
|
||||
|
||||
LISTBASE_FOREACH (LinkData *, ld, &xr_data->full_blender_ui_screens) {
|
||||
if (ld->data != NULL)
|
||||
GPU_offscreen_free(ld->data);
|
||||
ld->data = NULL;
|
||||
}
|
||||
BLI_freelistN(&xr_data->full_blender_ui_screens);
|
||||
}
|
||||
|
||||
static void wm_xr_session_begin_info_create(wmXrData *xr_data,
|
||||
|
@ -157,14 +167,15 @@ bool WM_xr_session_is_ready(const wmXrData *xr)
|
|||
}
|
||||
|
||||
static void wm_xr_session_base_pose_calc(const Scene *scene,
|
||||
const XrSessionSettings *settings,
|
||||
const wmXrData *xr,
|
||||
GHOST_XrPose *r_base_pose,
|
||||
float *r_base_scale)
|
||||
{
|
||||
XrSessionSettings *settings = &xr->session_settings;
|
||||
const Object *base_pose_object = ((settings->base_pose_type == XR_BASE_POSE_OBJECT) &&
|
||||
settings->base_pose_object) ?
|
||||
settings->base_pose_object :
|
||||
scene->camera;
|
||||
NULL;
|
||||
|
||||
if (settings->base_pose_type == XR_BASE_POSE_CUSTOM) {
|
||||
float tmp_quatx[4], tmp_quatz[4];
|
||||
|
@ -178,17 +189,22 @@ static void wm_xr_session_base_pose_calc(const Scene *scene,
|
|||
float tmp_quat[4];
|
||||
float tmp_eul[3];
|
||||
|
||||
mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->object_to_world);
|
||||
mat4_to_loc_quat(
|
||||
r_base_pose->position, r_base_pose->orientation_quat, base_pose_object->object_to_world);
|
||||
// mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->object_to_world);
|
||||
|
||||
/* Only use rotation around Z-axis to align view with floor. */
|
||||
quat_to_eul(tmp_eul, tmp_quat);
|
||||
tmp_eul[0] = M_PI_2;
|
||||
tmp_eul[1] = 0;
|
||||
eul_to_quat(r_base_pose->orientation_quat, tmp_eul);
|
||||
// quat_to_eul(tmp_eul, tmp_quat);
|
||||
// tmp_eul[0] = M_PI_2;
|
||||
// tmp_eul[1] = 0;
|
||||
// eul_to_quat(r_base_pose->orientation_quat, tmp_eul);
|
||||
}
|
||||
else {
|
||||
copy_v3_fl(r_base_pose->position, 0.0f);
|
||||
axis_angle_to_quat_single(r_base_pose->orientation_quat, 'X', M_PI_2);
|
||||
mat4_to_loc_quat(r_base_pose->position,
|
||||
r_base_pose->orientation_quat,
|
||||
xr->runtime->worldspace_from_viewspace);
|
||||
// copy_v3_fl(r_base_pose->position, 0.0f);
|
||||
// axis_angle_to_quat_single(r_base_pose->orientation_quat, 'X', M_PI_2);
|
||||
}
|
||||
|
||||
*r_base_scale = settings->base_scale;
|
||||
|
@ -208,7 +224,7 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data,
|
|||
r_draw_data->surface_data = g_xr_surface->customdata;
|
||||
|
||||
wm_xr_session_base_pose_calc(
|
||||
r_draw_data->scene, settings, &r_draw_data->base_pose, &r_draw_data->base_scale);
|
||||
r_draw_data->scene, xr_data, &r_draw_data->base_pose, &r_draw_data->base_scale);
|
||||
}
|
||||
|
||||
wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
|
||||
|
@ -1179,6 +1195,7 @@ static void wm_xr_session_events_dispatch(wmXrData *xr,
|
|||
MEM_freeN(actions);
|
||||
}
|
||||
|
||||
// GG: XR update loop func
|
||||
void wm_xr_session_actions_update(wmWindowManager *wm)
|
||||
{
|
||||
wmXrData *xr = &wm->xr;
|
||||
|
@ -1235,7 +1252,6 @@ void wm_xr_session_actions_update(wmWindowManager *wm)
|
|||
if (!xr->runtime->area) {
|
||||
xr->runtime->area = ED_area_offscreen_create(win, SPACE_VIEW3D);
|
||||
}
|
||||
|
||||
/* Set XR area object type flags for operators. */
|
||||
View3D *v3d = xr->runtime->area->spacedata.first;
|
||||
v3d->object_type_exclude_viewport = settings->object_type_exclude_viewport;
|
||||
|
@ -1278,6 +1294,18 @@ void wm_xr_session_controller_data_populate(const wmXrAction *grip_action,
|
|||
surface_data->controller_art, wm_xr_draw_controllers, xr, REGION_DRAW_POST_VIEW);
|
||||
}
|
||||
}
|
||||
|
||||
// GG: TODO: Since the runtime may end before user explicitly deactivates it, then we need to
|
||||
// actually
|
||||
// clean this up elsewhere (look for general XR runtime free func ).
|
||||
// GG: TODO: this is tmp placement of code. I just need to get the core implemnetation working
|
||||
// before worry about proper implementation/blender-code-consistency
|
||||
if (surface_data) {
|
||||
if (surface_data->controller_art) {
|
||||
surface_data->draw_mirror_blender_ui_to_xr = ED_region_draw_cb_activate(
|
||||
surface_data->controller_art, draw_mirror_blender_ui_to_xr, xr, REGION_DRAW_POST_VIEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1295,6 +1323,18 @@ void wm_xr_session_controller_data_clear(wmXrSessionState *state)
|
|||
surface_data->controller_draw_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// GG: Move to proper location. I Think this is for literal hand control data clearing.
|
||||
if (g_xr_surface) {
|
||||
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
|
||||
if (surface_data && surface_data->controller_draw_handle) {
|
||||
if (surface_data->controller_art) {
|
||||
ED_region_draw_cb_exit(surface_data->controller_art,
|
||||
surface_data->draw_mirror_blender_ui_to_xr);
|
||||
}
|
||||
surface_data->draw_mirror_blender_ui_to_xr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */ /* XR-Session Actions */
|
||||
|
@ -1326,6 +1366,255 @@ static void wm_xr_session_surface_draw(bContext *C)
|
|||
Scene *scene;
|
||||
Depsgraph *depsgraph;
|
||||
wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
|
||||
|
||||
{
|
||||
// placed in draw() instead of update to reduce jitter problems
|
||||
wmWindow *win;
|
||||
int wn_index;
|
||||
LISTBASE_FOREACH_INDEX (wmWindow *, win, &wm->windows, wn_index) {
|
||||
// BLI_assert(wn_index < BLI_)
|
||||
LinkData *ld = BLI_findlink(&wm->xr.full_blender_ui_screens, wn_index);
|
||||
if (ld != NULL && wn_index < 32) {
|
||||
wm->xr.window_positions_xy[wn_index * 2 + 0] = win->posx;
|
||||
wm->xr.window_positions_xy[wn_index * 2 + 1] = win->posy;
|
||||
wm->xr.mouse_positions_per_window_xy[wn_index * 2 + 0] = win->eventstate->xy[0];
|
||||
wm->xr.mouse_positions_per_window_xy[wn_index * 2 + 1] = win->eventstate->xy[1];
|
||||
// this check doesnt work in general since mouse coords .. arent releative to the window??
|
||||
// I thin kthey're relative to the active window?
|
||||
/*if (win->eventstate->xy[0] >= 0 &&
|
||||
win->eventstate->xy[0] <= win->sizex &&
|
||||
win->eventstate->xy[1] >= 0 &&
|
||||
win->eventstate->xy[1] <= win->sizey)*/
|
||||
if (win->active != 0) {
|
||||
wm->xr.mouse_position_global_xy[0] = win->posx + win->eventstate->xy[0];
|
||||
wm->xr.mouse_position_global_xy[1] = win->posy + win->eventstate->xy[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
wmXrData *xr = &wm->xr;
|
||||
win = wm_xr_session_root_window_or_fallback_get(wm, wm->xr.runtime);
|
||||
copy_v2_v2_int(wm->xr.runtime->mouse_xy, win->eventstate->xy);
|
||||
xr->evil_C = C;
|
||||
copy_v3_v3(xr->runtime->cursor_location_worldspace, scene->cursor.location);
|
||||
|
||||
ARegion *v3d_region_under_mouse = NULL;
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
// View3D *v3d = NULL;
|
||||
xr->runtime->flags &= ~XR_RUNTIME_IS_MOUSE_OVER_V3D;
|
||||
ED_screen_areas_iter (win, screen, area) {
|
||||
if (area->spacetype != SPACE_VIEW3D) {
|
||||
continue;
|
||||
}
|
||||
// v3d = area->spacedata.first;
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (!region->visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (region->overlap) {
|
||||
continue;
|
||||
}
|
||||
if (region->draw_buffer->viewport == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (region->regiontype != RGN_TYPE_WINDOW) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int mouse_over_result = 0;
|
||||
SET_FLAG_FROM_TEST(mouse_over_result,
|
||||
ED_region_contains_xy(region, win->eventstate->xy),
|
||||
XR_RUNTIME_IS_MOUSE_OVER_V3D);
|
||||
xr->runtime->flags |= mouse_over_result;
|
||||
|
||||
v3d_region_under_mouse = region;
|
||||
}
|
||||
}
|
||||
zero_v3(wm->xr.runtime->v3d_origin);
|
||||
zero_v3(wm->xr.runtime->v3d_ray_dir);
|
||||
if (v3d_region_under_mouse != NULL) {
|
||||
float v3d_origin[3];
|
||||
float v3d_ray_dir[3];
|
||||
|
||||
float mval[2] = {
|
||||
win->eventstate->xy[0],
|
||||
win->eventstate->xy[1],
|
||||
};
|
||||
|
||||
mval[0] = mval[0] - v3d_region_under_mouse->winrct.xmin;
|
||||
mval[1] = mval[1] - v3d_region_under_mouse->winrct.ymin;
|
||||
ED_view3d_win_to_origin(v3d_region_under_mouse, mval, v3d_origin);
|
||||
ED_view3d_win_to_vector(v3d_region_under_mouse, mval, v3d_ray_dir);
|
||||
copy_v3_v3(wm->xr.runtime->v3d_origin, v3d_origin);
|
||||
copy_v3_v3(wm->xr.runtime->v3d_ray_dir, v3d_ray_dir);
|
||||
// wm->xr.runtime->v3d_clip_start = v3d->clip_start; // distance to draw UI from cam origin
|
||||
|
||||
// mval[0] = 0;
|
||||
// mval[1] = 0;
|
||||
// ED_view3d_win_to_origin(&wm->xr.runtime->world_viewplane_bottom_left_origin, mval,
|
||||
// v3d_origin); ED_view3d_win_to_vector(&wm->xr.runtime->world_viewplane_bottom_left_raydir,
|
||||
// mval, v3d_ray_dir);
|
||||
|
||||
// mval[0] = v3d_region_under_mouse->winx;
|
||||
// mval[1] = 0;
|
||||
// ED_view3d_win_to_origin(&wm->xr.runtime->world_viewplane_bottom_right_origin, mval,
|
||||
// v3d_origin); ED_view3d_win_to_vector(&wm->xr.runtime->world_viewplane_bottom_right_raydir,
|
||||
// mval, v3d_ray_dir);
|
||||
|
||||
// mval[0] = v3d_region_under_mouse->winx;
|
||||
// mval[1] = v3d_region_under_mouse->winy;
|
||||
// ED_view3d_win_to_origin(&wm->xr.runtime->world_viewplane_top_right_origin, mval,
|
||||
// v3d_origin); ED_view3d_win_to_vector(&wm->xr.runtime->world_viewplane_top_right_raydir,
|
||||
// mval, v3d_ray_dir);
|
||||
|
||||
// mval[0] = 0;
|
||||
// mval[1] = v3d_region_under_mouse->winy;
|
||||
// ED_view3d_win_to_origin(&wm->xr.runtime->world_viewplane_top_left_origin, mval,
|
||||
// v3d_origin); ED_view3d_win_to_vector(&wm->xr.runtime->world_viewplane_top_left_raydir,
|
||||
// mval, v3d_ray_dir); float v3d_projection_matrix[4][4];
|
||||
// {
|
||||
// RegionView3D *r3d = v3d_region_under_mouse->regiondata;
|
||||
// Scene *scene;
|
||||
// Depsgraph *depsgraph;
|
||||
// wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
|
||||
// rctf viewplane = {0};
|
||||
// float clip_start = 0;
|
||||
// float clip_end = 0;
|
||||
// bool is_ortho = ED_view3d_viewplane_get(depsgraph,
|
||||
// v3d,
|
||||
// r3d,
|
||||
// v3d_region_under_mouse->winx,
|
||||
// v3d_region_under_mouse->winy,
|
||||
// &viewplane,
|
||||
// &clip_start,
|
||||
// &clip_end,
|
||||
// NULL);
|
||||
|
||||
// if (is_ortho) {
|
||||
// orthographic_m4(v3d_projection_matrix,
|
||||
// viewplane.xmin,
|
||||
// viewplane.xmax,
|
||||
// viewplane.ymin,
|
||||
// viewplane.ymax,
|
||||
// clip_start,
|
||||
// clip_end);
|
||||
// }
|
||||
// else {
|
||||
// perspective_m4(v3d_projection_matrix,
|
||||
// viewplane.xmin,
|
||||
// viewplane.xmax,
|
||||
// viewplane.ymin,
|
||||
// viewplane.ymax,
|
||||
// clip_start,
|
||||
// clip_end);
|
||||
// }
|
||||
// }
|
||||
// takes region [0,1] to worldspace [world left/bottom, world right/top]
|
||||
RegionView3D *r3d = v3d_region_under_mouse->regiondata;
|
||||
copy_m4_m4(xr->runtime->worldspace_from_viewspace, r3d->viewinv);
|
||||
copy_m4_m4(xr->runtime->viewspace_from_worldspace, r3d->viewmat);
|
||||
|
||||
float worldspace_from_normalized_region[4][4];
|
||||
unit_m4(worldspace_from_normalized_region);
|
||||
{
|
||||
|
||||
// Scene *scene;
|
||||
// Depsgraph *depsgraph;
|
||||
// wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
|
||||
// Camera *cam_obj = scene->camera->data;
|
||||
|
||||
float worldspace_bottom_left[3];
|
||||
float worldspace_bottom_right[3];
|
||||
float worldspace_top_left[3];
|
||||
|
||||
float viewspace_from_ndc[4][4]; // same as projection input space
|
||||
copy_m4_m4(viewspace_from_ndc, r3d->persinv);
|
||||
float worldspace_from_viewspace[4][4];
|
||||
copy_m4_m4(worldspace_from_viewspace, r3d->viewinv);
|
||||
// invert_m4(worldspace_from_viewspace);
|
||||
|
||||
float worldspace_from_ndc[4][4];
|
||||
copy_m4_m4(worldspace_from_ndc, worldspace_from_viewspace);
|
||||
mul_m4_m4_post(worldspace_from_ndc, viewspace_from_ndc);
|
||||
|
||||
// GG: USE: besides changing this between [-1,1],
|
||||
// you can also move and scale the UI by unlocking the camera, zooming/inout and
|
||||
// panning then relocking the camera.
|
||||
// GG: TIP: GOTCHA: Wireframe bones dont show in XR... Solid do.
|
||||
float ndc_depth = .75f;
|
||||
|
||||
float ndc[3];
|
||||
ndc[0] = -1;
|
||||
ndc[1] = -1;
|
||||
ndc[2] = ndc_depth;
|
||||
// persinv is worldspace_from_ndc?, not viewspace_from_ndc?
|
||||
mul_v3_project_m4_v3(worldspace_bottom_left, viewspace_from_ndc, ndc);
|
||||
// mul_m4_v3(worldspace_from_viewspace, worldspace_bottom_left);
|
||||
// mul_m4_v3(worldspace_from_viewspace, worldspace_bottom_left);
|
||||
|
||||
// ndc[0] = 0;
|
||||
// ndc[1] = 0;
|
||||
// ndc[2] = -5;
|
||||
// mul_v3_project_m4_v3(worldspace_bottom_left, viewspace_from_ndc, ndc);
|
||||
// mul_m4_v3(worldspace_from_viewspace, worldspace_bottom_left);
|
||||
|
||||
ndc[0] = 1;
|
||||
ndc[1] = -1;
|
||||
ndc[2] = ndc_depth;
|
||||
mul_v3_project_m4_v3(worldspace_bottom_right, viewspace_from_ndc, ndc);
|
||||
// mul_m4_v3(worldspace_from_viewspace, worldspace_bottom_right);
|
||||
// mul_v3_project_m4_v3(worldspace_bottom_right, worldspace_from_ndc, ndc);
|
||||
|
||||
// ndc[0] = 1;
|
||||
// ndc[1] = 1;
|
||||
// ndc[2] = 0;
|
||||
// mul_v3_project_m4_v3(worldspace_top_right, worldspace_from_ndc, ndc);
|
||||
|
||||
ndc[0] = -1;
|
||||
ndc[1] = 1;
|
||||
ndc[2] = ndc_depth;
|
||||
mul_v3_project_m4_v3(worldspace_top_left, viewspace_from_ndc, ndc);
|
||||
// mul_m4_v3(worldspace_from_viewspace, worldspace_top_left);
|
||||
// mul_v3_project_m4_v3(worldspace_top_left, worldspace_from_ndc, ndc);
|
||||
|
||||
sub_v3_v3v3(
|
||||
worldspace_from_normalized_region[0], worldspace_bottom_right, worldspace_bottom_left);
|
||||
sub_v3_v3v3(
|
||||
worldspace_from_normalized_region[1], worldspace_top_left, worldspace_bottom_left);
|
||||
cross_v3_v3v3(worldspace_from_normalized_region[2],
|
||||
worldspace_from_normalized_region[0],
|
||||
worldspace_from_normalized_region[1]);
|
||||
copy_v3_v3(worldspace_from_normalized_region[3], worldspace_bottom_left);
|
||||
}
|
||||
|
||||
float windowspace_from_normalized_region[4][4];
|
||||
unit_m4(windowspace_from_normalized_region);
|
||||
{
|
||||
float windowspace_bottom_left[3] = {
|
||||
v3d_region_under_mouse->winrct.xmin, v3d_region_under_mouse->winrct.ymin, 0};
|
||||
float windowspace_bottom_right[3] = {
|
||||
v3d_region_under_mouse->winrct.xmax, v3d_region_under_mouse->winrct.ymin, 0};
|
||||
float windowspace_top_left[3] = {
|
||||
v3d_region_under_mouse->winrct.xmin, v3d_region_under_mouse->winrct.ymax, 0};
|
||||
sub_v3_v3v3(windowspace_from_normalized_region[0],
|
||||
windowspace_bottom_right,
|
||||
windowspace_bottom_left);
|
||||
sub_v3_v3v3(
|
||||
windowspace_from_normalized_region[1], windowspace_top_left, windowspace_bottom_left);
|
||||
cross_v3_v3v3(windowspace_from_normalized_region[2],
|
||||
windowspace_from_normalized_region[0],
|
||||
windowspace_from_normalized_region[1]);
|
||||
copy_v3_v3(windowspace_from_normalized_region[3], windowspace_bottom_left);
|
||||
}
|
||||
|
||||
float normalized_region_from_windowspace[4][4];
|
||||
invert_m4_m4(normalized_region_from_windowspace, windowspace_from_normalized_region);
|
||||
|
||||
mul_m4_m4m4(wm->xr.runtime->worldspace_from_windowspace,
|
||||
worldspace_from_normalized_region,
|
||||
normalized_region_from_windowspace);
|
||||
}
|
||||
}
|
||||
/* Might fail when force-redrawing windows with #WM_redraw_windows(), which is done on file
|
||||
* writing for example. */
|
||||
// BLI_assert(DEG_is_fully_evaluated(depsgraph));
|
||||
|
|
Loading…
Reference in a new issue