OpenXR: VR Advanced Locomotion Phase 1
Includes the following changes to the existing Locomotion system for VR Scene Inspection: * new VR Navigation Preferences and VR Session Settings * changes to XR raycast logic and its visualization * new XR vignette that appears when moving * snap turning Pull Request: https://projects.blender.org/blender/blender/pulls/144241
This commit is contained in:
committed by
Julian Eisel
parent
1df4a09539
commit
dde9d21b91
@@ -208,6 +208,14 @@ const UserDef U_default = {
|
|||||||
.flag = 0,
|
.flag = 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.xr_navigation =
|
||||||
|
{
|
||||||
|
.vignette_intensity = 60.0f,
|
||||||
|
.turn_amount = DEG2RAD(30),
|
||||||
|
.turn_speed = DEG2RAD(60),
|
||||||
|
.flag = USER_XR_NAV_SNAP_TURN,
|
||||||
|
},
|
||||||
|
|
||||||
.space_data =
|
.space_data =
|
||||||
{
|
{
|
||||||
.section_active = USER_SECTION_INTERFACE,
|
.section_active = USER_SECTION_INTERFACE,
|
||||||
@@ -246,4 +254,12 @@ const UserDef U_default = {
|
|||||||
{
|
{
|
||||||
.is_dirty = 0,
|
.is_dirty = 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.xr_navigation =
|
||||||
|
{
|
||||||
|
.vignette_intensity = 60.0f,
|
||||||
|
.turn_amount = DEG2RAD(30),
|
||||||
|
.turn_speed = DEG2RAD(60),
|
||||||
|
.flag = USER_XR_NAV_SNAP_TURN,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ if "bpy" in locals():
|
|||||||
importlib.reload(gui)
|
importlib.reload(gui)
|
||||||
importlib.reload(operators)
|
importlib.reload(operators)
|
||||||
importlib.reload(properties)
|
importlib.reload(properties)
|
||||||
|
importlib.reload(preferences)
|
||||||
else:
|
else:
|
||||||
from . import action_map, gui, operators, properties
|
from . import action_map, gui, operators, properties, preferences
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ def register():
|
|||||||
gui.register()
|
gui.register()
|
||||||
operators.register()
|
operators.register()
|
||||||
properties.register()
|
properties.register()
|
||||||
|
preferences.register()
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
@@ -50,3 +52,4 @@ def unregister():
|
|||||||
gui.unregister()
|
gui.unregister()
|
||||||
operators.unregister()
|
operators.unregister()
|
||||||
properties.unregister()
|
properties.unregister()
|
||||||
|
preferences.unregister()
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ actionconfig_data = \
|
|||||||
("teleport", {"type": 'FLOAT', "user_paths": ['/user/hand/left', '/user/hand/right'], "op": 'wm.xr_navigation_teleport', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("teleport", {"type": 'FLOAT', "user_paths": ['/user/hand/left', '/user/hand/right'], "op": 'wm.xr_navigation_teleport', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("interpolation", 0.9),
|
[("interpolation", 0.9),
|
||||||
("color", (0.0, 1.0, 1.0, 1.0)),
|
("hit_color", (0.0, 1.0, 1.0, 1.0)),
|
||||||
|
("miss_color", (1.0, 0.0, 0.0, 1.0)),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
@@ -74,6 +75,7 @@ actionconfig_data = \
|
|||||||
("fly_forward", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_forward", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_FORWARD'),
|
[("mode", 'VIEWER_FORWARD'),
|
||||||
|
("alt_mode", 'UP'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -92,6 +94,7 @@ actionconfig_data = \
|
|||||||
("fly_back", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_back", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_BACK'),
|
[("mode", 'VIEWER_BACK'),
|
||||||
|
("alt_mode", 'DOWN'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -110,6 +113,7 @@ actionconfig_data = \
|
|||||||
("fly_left", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_left", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_LEFT'),
|
[("mode", 'VIEWER_LEFT'),
|
||||||
|
("alt_mode", 'TURNLEFT'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -128,6 +132,7 @@ actionconfig_data = \
|
|||||||
("fly_right", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_right", {"type": 'FLOAT', "user_paths": ['/user/hand/left'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_RIGHT'),
|
[("mode", 'VIEWER_RIGHT'),
|
||||||
|
("alt_mode", 'TURNRIGHT'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -146,8 +151,8 @@ actionconfig_data = \
|
|||||||
("fly_up", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_up", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'UP'),
|
[("mode", 'UP'),
|
||||||
("speed_min", 0.014),
|
("alt_mode", 'VIEWER_FORWARD'),
|
||||||
("speed_max", 0.042),
|
("alt_lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
@@ -165,8 +170,8 @@ actionconfig_data = \
|
|||||||
("fly_down", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_down", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'DOWN'),
|
[("mode", 'DOWN'),
|
||||||
("speed_min", 0.014),
|
("alt_mode", 'VIEWER_BACK'),
|
||||||
("speed_max", 0.042),
|
("alt_lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
@@ -184,8 +189,8 @@ actionconfig_data = \
|
|||||||
("fly_turnleft", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_turnleft", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'TURNLEFT'),
|
[("mode", 'TURNLEFT'),
|
||||||
("speed_min", 0.01),
|
("alt_mode", 'VIEWER_LEFT'),
|
||||||
("speed_max", 0.03),
|
("alt_lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
@@ -203,8 +208,8 @@ actionconfig_data = \
|
|||||||
("fly_turnright", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_turnright", {"type": 'FLOAT', "user_paths": ['/user/hand/right'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'TURNRIGHT'),
|
[("mode", 'TURNRIGHT'),
|
||||||
("speed_min", 0.01),
|
("alt_mode", 'VIEWER_RIGHT'),
|
||||||
("speed_max", 0.03),
|
("alt_lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
@@ -261,7 +266,8 @@ actionconfig_data = \
|
|||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("interpolation", 0.9),
|
[("interpolation", 0.9),
|
||||||
("from_viewer", True),
|
("from_viewer", True),
|
||||||
("color", (0.0, 1.0, 1.0, 1.0)),
|
("hit_color", (0.0, 1.0, 1.0, 1.0)),
|
||||||
|
("miss_color", (1.0, 0.0, 0.0, 1.0)),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
@@ -278,6 +284,7 @@ actionconfig_data = \
|
|||||||
("fly_forward", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_forward", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_FORWARD'),
|
[("mode", 'VIEWER_FORWARD'),
|
||||||
|
("alt_mode", 'UP'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -289,6 +296,7 @@ actionconfig_data = \
|
|||||||
("fly_back", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_back", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_BACK'),
|
[("mode", 'VIEWER_BACK'),
|
||||||
|
("alt_mode", 'DOWN'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -300,6 +308,7 @@ actionconfig_data = \
|
|||||||
("fly_left", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_left", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_LEFT'),
|
[("mode", 'VIEWER_LEFT'),
|
||||||
|
("alt_mode", 'TURNLEFT'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -311,6 +320,7 @@ actionconfig_data = \
|
|||||||
("fly_right", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_right", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'VIEWER_RIGHT'),
|
[("mode", 'VIEWER_RIGHT'),
|
||||||
|
("alt_mode", 'TURNRIGHT'),
|
||||||
("lock_location_z", True),
|
("lock_location_z", True),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -322,9 +332,9 @@ actionconfig_data = \
|
|||||||
("fly_up", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_up", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'UP'),
|
[("mode", 'UP'),
|
||||||
("speed_min", 0.014),
|
("alt_mode", 'VIEWER_FORWARD'),
|
||||||
("speed_max", 0.042),
|
("alt_lock_location_z", True),
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/y'], "threshold": '0.30000001192092896', "axis_region": 'POSITIVE'}),
|
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/y'], "threshold": '0.30000001192092896', "axis_region": 'POSITIVE'}),
|
||||||
@@ -334,9 +344,9 @@ actionconfig_data = \
|
|||||||
("fly_down", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_down", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'DOWN'),
|
[("mode", 'DOWN'),
|
||||||
("speed_min", 0.014),
|
("alt_mode", 'VIEWER_BACK'),
|
||||||
("speed_max", 0.042),
|
("alt_lock_location_z", True),
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/y'], "threshold": '0.30000001192092896', "axis_region": 'NEGATIVE'}),
|
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/y'], "threshold": '0.30000001192092896', "axis_region": 'NEGATIVE'}),
|
||||||
@@ -346,9 +356,9 @@ actionconfig_data = \
|
|||||||
("fly_turnleft", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_turnleft", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'TURNLEFT'),
|
[("mode", 'TURNLEFT'),
|
||||||
("speed_min", 0.01),
|
("alt_mode", 'VIEWER_LEFT'),
|
||||||
("speed_max", 0.03),
|
("alt_lock_location_z", True),
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/x'], "threshold": '0.30000001192092896', "axis_region": 'NEGATIVE'}),
|
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/x'], "threshold": '0.30000001192092896', "axis_region": 'NEGATIVE'}),
|
||||||
@@ -358,9 +368,9 @@ actionconfig_data = \
|
|||||||
("fly_turnright", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
("fly_turnright", {"type": 'FLOAT', "user_paths": ['/user/gamepad'], "op": 'wm.xr_navigation_fly', "op_mode": 'MODAL', "bimanual": 'False', "haptic_name": '', "haptic_match_user_paths": 'False', "haptic_duration": '0.0', "haptic_frequency": '0.0', "haptic_amplitude": '0.0', "haptic_mode": 'PRESS'},
|
||||||
{"op_properties":
|
{"op_properties":
|
||||||
[("mode", 'TURNRIGHT'),
|
[("mode", 'TURNRIGHT'),
|
||||||
("speed_min", 0.01),
|
("alt_mode", 'VIEWER_RIGHT'),
|
||||||
("speed_max", 0.03),
|
("alt_lock_location_z", True),
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{"bindings":
|
{"bindings":
|
||||||
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/x'], "threshold": '0.30000001192092896', "axis_region": 'POSITIVE'}),
|
[("gamepad", {"profile": '/interaction_profiles/microsoft/xbox_controller', "component_paths": ['/input/thumbstick_right/x'], "threshold": '0.30000001192092896', "axis_region": 'POSITIVE'}),
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class VRDefaultActions(Enum):
|
|||||||
FLY_TURNLEFT = "fly_turnleft"
|
FLY_TURNLEFT = "fly_turnleft"
|
||||||
FLY_TURNRIGHT = "fly_turnright"
|
FLY_TURNRIGHT = "fly_turnright"
|
||||||
NAV_RESET = "nav_reset"
|
NAV_RESET = "nav_reset"
|
||||||
|
SWAP_HANDS = "swap_hands"
|
||||||
HAPTIC = "haptic"
|
HAPTIC = "haptic"
|
||||||
HAPTIC_LEFT = "haptic_left"
|
HAPTIC_LEFT = "haptic_left"
|
||||||
HAPTIC_RIGHT = "haptic_right"
|
HAPTIC_RIGHT = "haptic_right"
|
||||||
@@ -1146,6 +1147,91 @@ def vr_defaults_create_default(session_state):
|
|||||||
'ANY',
|
'ANY',
|
||||||
'ANY')
|
'ANY')
|
||||||
|
|
||||||
|
ami = vr_defaults_action_add(am,
|
||||||
|
VRDefaultActions.SWAP_HANDS.value,
|
||||||
|
["/user/hand/left",
|
||||||
|
"/user/hand/right"],
|
||||||
|
"wm.xr_navigation_swap_hands",
|
||||||
|
'PRESS',
|
||||||
|
False,
|
||||||
|
"haptic",
|
||||||
|
True,
|
||||||
|
0.3,
|
||||||
|
3000.0,
|
||||||
|
0.5,
|
||||||
|
'PRESS')
|
||||||
|
if ami:
|
||||||
|
"""
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.HUAWEI.value,
|
||||||
|
VRDefaultActionprofiles.HUAWEI.value,
|
||||||
|
["/input/back/click",
|
||||||
|
"/input/back/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
"""
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.INDEX.value,
|
||||||
|
VRDefaultActionprofiles.INDEX.value,
|
||||||
|
["/input/b/click",
|
||||||
|
"/input/b/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.OCULUS.value,
|
||||||
|
VRDefaultActionprofiles.OCULUS.value,
|
||||||
|
["/input/y/click",
|
||||||
|
"/input/b/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.REVERB_G2.value,
|
||||||
|
VRDefaultActionprofiles.REVERB_G2.value,
|
||||||
|
["/input/y/click",
|
||||||
|
"/input/b/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
"""
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.VIVE.value,
|
||||||
|
VRDefaultActionprofiles.VIVE.value,
|
||||||
|
["/input/menu/click",
|
||||||
|
"/input/menu/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
"""
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.VIVE_COSMOS.value,
|
||||||
|
VRDefaultActionprofiles.VIVE_COSMOS.value,
|
||||||
|
["/input/y/click",
|
||||||
|
"/input/b/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.VIVE_FOCUS.value,
|
||||||
|
VRDefaultActionprofiles.VIVE_FOCUS.value,
|
||||||
|
["/input/y/click",
|
||||||
|
"/input/b/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
"""
|
||||||
|
vr_defaults_actionbinding_add(ami,
|
||||||
|
VRDefaultActionbindings.WMR.value,
|
||||||
|
VRDefaultActionprofiles.WMR.value,
|
||||||
|
["/input/menu/click",
|
||||||
|
"/input/menu/click"],
|
||||||
|
0.3,
|
||||||
|
'ANY',
|
||||||
|
'ANY')
|
||||||
|
"""
|
||||||
|
|
||||||
ami = vr_defaults_haptic_action_add(am,
|
ami = vr_defaults_haptic_action_add(am,
|
||||||
VRDefaultActions.HAPTIC.value,
|
VRDefaultActions.HAPTIC.value,
|
||||||
["/user/hand/left",
|
["/user/hand/left",
|
||||||
|
|||||||
@@ -97,7 +97,9 @@ class VIEW3D_PT_vr_session_view(Panel):
|
|||||||
col = layout.column(align=True)
|
col = layout.column(align=True)
|
||||||
col.prop(session_settings, "clip_start", text="Clip Start")
|
col.prop(session_settings, "clip_start", text="Clip Start")
|
||||||
col.prop(session_settings, "clip_end", text="End", text_ctxt=i18n_contexts.id_camera)
|
col.prop(session_settings, "clip_end", text="End", text_ctxt=i18n_contexts.id_camera)
|
||||||
|
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.prop(session_settings, "fly_speed", text="Fly Speed")
|
||||||
|
|
||||||
class VIEW3D_PT_vr_session_view_object_type_visibility(VIEW3D_PT_object_type_visibility):
|
class VIEW3D_PT_vr_session_view_object_type_visibility(VIEW3D_PT_object_type_visibility):
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
|||||||
67
scripts/addons_core/viewport_vr_preview/preferences.py
Normal file
67
scripts/addons_core/viewport_vr_preview/preferences.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from bpy.types import (
|
||||||
|
Panel,
|
||||||
|
)
|
||||||
|
|
||||||
|
class USERPREF_PT_vr_navigation(Panel):
|
||||||
|
bl_space_type = 'PREFERENCES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_context = "navigation"
|
||||||
|
bl_label = "VR Navigation"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
width = context.region.width
|
||||||
|
ui_scale = context.preferences.system.ui_scale
|
||||||
|
# No horizontal margin if region is rather small.
|
||||||
|
is_wide = width > (350 * ui_scale)
|
||||||
|
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False # No animation.
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
if is_wide:
|
||||||
|
row.label() # Needed so col below is centered.
|
||||||
|
|
||||||
|
col = row.column()
|
||||||
|
col.ui_units_x = 50
|
||||||
|
|
||||||
|
# Implemented by sub-classes.
|
||||||
|
self.draw_centered(context, col)
|
||||||
|
|
||||||
|
if is_wide:
|
||||||
|
row.label() # Needed so col above is centered.
|
||||||
|
|
||||||
|
def draw_centered(self, context, layout):
|
||||||
|
prefs = context.preferences
|
||||||
|
nav = prefs.inputs.xr_navigation
|
||||||
|
|
||||||
|
col = layout.column()
|
||||||
|
|
||||||
|
col.row().prop(nav, "vignette_intensity", text="Vignette Intensity")
|
||||||
|
|
||||||
|
if nav.snap_turn:
|
||||||
|
col.row().prop(nav, "turn_amount", text="Turn Amount")
|
||||||
|
else:
|
||||||
|
col.row().prop(nav, "turn_speed", text="Turn Speed")
|
||||||
|
|
||||||
|
col.row().prop(nav, "snap_turn", text="Snap Turn")
|
||||||
|
col.row().prop(nav, "invert_rotation", text="Invert Rotation")
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
USERPREF_PT_vr_navigation,
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
from bpy.utils import register_class
|
||||||
|
for cls in classes:
|
||||||
|
register_class(cls)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
from bpy.utils import unregister_class
|
||||||
|
for cls in classes:
|
||||||
|
unregister_class(cls)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
/* Blender file format version. */
|
/* Blender file format version. */
|
||||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||||
#define BLENDER_FILE_SUBVERSION 98
|
#define BLENDER_FILE_SUBVERSION 99
|
||||||
|
|
||||||
/* Minimum Blender version that supports reading file written with the current
|
/* Minimum Blender version that supports reading file written with the current
|
||||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||||
|
|||||||
@@ -3772,6 +3772,12 @@ void blo_do_versions_500(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 99)) {
|
||||||
|
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
|
||||||
|
wm->xr.session_settings.fly_speed = 3.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||||
|
|||||||
@@ -381,6 +381,11 @@ static void blo_update_defaults_paint(Paint *paint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void blo_update_defaults_windowmanager(wmWindowManager *wm)
|
||||||
|
{
|
||||||
|
wm->xr.session_settings.fly_speed = 3.0f;
|
||||||
|
}
|
||||||
|
|
||||||
static void blo_update_defaults_scene(Main *bmain, Scene *scene)
|
static void blo_update_defaults_scene(Main *bmain, Scene *scene)
|
||||||
{
|
{
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
@@ -618,6 +623,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||||||
|
|
||||||
/* Work-spaces. */
|
/* Work-spaces. */
|
||||||
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
|
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
|
||||||
|
blo_update_defaults_windowmanager(wm);
|
||||||
|
|
||||||
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
||||||
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
|
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
|
||||||
WorkSpaceLayout *layout = BKE_workspace_active_layout_for_workspace_get(
|
WorkSpaceLayout *layout = BKE_workspace_active_layout_for_workspace_get(
|
||||||
|
|||||||
@@ -1691,6 +1691,13 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!USER_VERSION_ATLEAST(500, 99)) {
|
||||||
|
userdef->xr_navigation.vignette_intensity = 50.0f;
|
||||||
|
userdef->xr_navigation.turn_amount = DEG2RAD(30);
|
||||||
|
userdef->xr_navigation.turn_speed = DEG2RAD(60);
|
||||||
|
userdef->xr_navigation.flag = USER_XR_NAV_SNAP_TURN;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||||
* code here, and wrap it inside a USER_VERSION_ATLEAST check.
|
* code here, and wrap it inside a USER_VERSION_ATLEAST check.
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace blender::draw::overlay {
|
|||||||
class Background : Overlay {
|
class Background : Overlay {
|
||||||
private:
|
private:
|
||||||
PassSimple bg_ps_ = {"Background"};
|
PassSimple bg_ps_ = {"Background"};
|
||||||
|
PassSimple bg_vignette_ps_ = {"Background Vignette"};
|
||||||
|
|
||||||
gpu::FrameBuffer *framebuffer_ref_ = nullptr;
|
gpu::FrameBuffer *framebuffer_ref_ = nullptr;
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ class Background : Overlay {
|
|||||||
DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;
|
DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;
|
||||||
float4 color_override(0.0f, 0.0f, 0.0f, 0.0f);
|
float4 color_override(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
int background_type;
|
int background_type;
|
||||||
|
const float vignette_aperture = state.v3d->vignette_aperture, vignette_falloff = 0.15f;
|
||||||
|
|
||||||
if (state.is_viewport_image_render && !state.draw_background) {
|
if (state.is_viewport_image_render && !state.draw_background) {
|
||||||
background_type = BG_SOLID;
|
background_type = BG_SOLID;
|
||||||
@@ -96,7 +98,26 @@ class Background : Overlay {
|
|||||||
bg_ps_.bind_texture("depth_buffer", &res.depth_tx);
|
bg_ps_.bind_texture("depth_buffer", &res.depth_tx);
|
||||||
bg_ps_.push_constant("color_override", color_override);
|
bg_ps_.push_constant("color_override", color_override);
|
||||||
bg_ps_.push_constant("bg_type", background_type);
|
bg_ps_.push_constant("bg_type", background_type);
|
||||||
|
bg_ps_.push_constant("vignette_enabled", false);
|
||||||
bg_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
bg_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||||
|
|
||||||
|
if (state.vignette_enabled) {
|
||||||
|
bg_vignette_ps_.init();
|
||||||
|
bg_vignette_ps_.framebuffer_set(&framebuffer_ref_);
|
||||||
|
|
||||||
|
bg_vignette_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
|
||||||
|
bg_vignette_ps_.shader_set(res.shaders->background_fill.get());
|
||||||
|
bg_vignette_ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
|
||||||
|
bg_vignette_ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
|
||||||
|
bg_vignette_ps_.bind_texture("color_buffer", &res.color_render_tx);
|
||||||
|
bg_vignette_ps_.bind_texture("depth_buffer", &res.depth_tx);
|
||||||
|
bg_vignette_ps_.push_constant("color_override", color_override);
|
||||||
|
bg_vignette_ps_.push_constant("bg_type", background_type);
|
||||||
|
bg_vignette_ps_.push_constant("vignette_enabled", true);
|
||||||
|
bg_vignette_ps_.push_constant("vignette_aperture", vignette_aperture);
|
||||||
|
bg_vignette_ps_.push_constant("vignette_falloff", vignette_falloff);
|
||||||
|
bg_vignette_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_output(Framebuffer &framebuffer, Manager &manager, View &view) final
|
void draw_output(Framebuffer &framebuffer, Manager &manager, View &view) final
|
||||||
@@ -104,6 +125,12 @@ class Background : Overlay {
|
|||||||
framebuffer_ref_ = framebuffer;
|
framebuffer_ref_ = framebuffer;
|
||||||
manager.submit(bg_ps_, view);
|
manager.submit(bg_ps_, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_vignette(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
framebuffer_ref_ = framebuffer;
|
||||||
|
manager.submit(bg_vignette_ps_, view);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::draw::overlay
|
} // namespace blender::draw::overlay
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ void Instance::init()
|
|||||||
state.xray_opacity = state.xray_enabled ? XRAY_ALPHA(state.v3d) : 1.0f;
|
state.xray_opacity = state.xray_enabled ? XRAY_ALPHA(state.v3d) : 1.0f;
|
||||||
state.xray_flag_enabled = SHADING_XRAY_FLAG_ENABLED(state.v3d->shading) &&
|
state.xray_flag_enabled = SHADING_XRAY_FLAG_ENABLED(state.v3d->shading) &&
|
||||||
!state.is_depth_only_drawing;
|
!state.is_depth_only_drawing;
|
||||||
|
state.vignette_enabled = ctx->mode == DRWContext::VIEWPORT_XR &&
|
||||||
|
state.v3d->vignette_aperture < M_SQRT1_2;
|
||||||
|
|
||||||
const bool viewport_uses_workbench = state.v3d->shading.type <= OB_SOLID ||
|
const bool viewport_uses_workbench = state.v3d->shading.type <= OB_SOLID ||
|
||||||
BKE_scene_uses_blender_workbench(state.scene);
|
BKE_scene_uses_blender_workbench(state.scene);
|
||||||
@@ -962,6 +964,10 @@ void Instance::draw_v3d(Manager &manager, View &view)
|
|||||||
cursor.draw_output(resources.overlay_output_color_only_fb, manager, view);
|
cursor.draw_output(resources.overlay_output_color_only_fb, manager, view);
|
||||||
|
|
||||||
draw_text(resources.overlay_output_color_only_fb);
|
draw_text(resources.overlay_output_color_only_fb);
|
||||||
|
|
||||||
|
if (state.vignette_enabled) {
|
||||||
|
background.draw_vignette(resources.overlay_output_color_only_fb, manager, view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ struct State {
|
|||||||
bool draw_background = false;
|
bool draw_background = false;
|
||||||
/** True if the render engine outputs satisfactory depth information to the depth buffer. */
|
/** True if the render engine outputs satisfactory depth information to the depth buffer. */
|
||||||
bool is_render_depth_available = false;
|
bool is_render_depth_available = false;
|
||||||
|
/** Whether we should render a vignette over the scene. */
|
||||||
|
bool vignette_enabled = false;
|
||||||
/** Should text draw in this mode? */
|
/** Should text draw in this mode? */
|
||||||
bool show_text = false;
|
bool show_text = false;
|
||||||
bool hide_overlays = false;
|
bool hide_overlays = false;
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ SAMPLER(0, sampler2D, color_buffer)
|
|||||||
SAMPLER(1, sampler2DDepth, depth_buffer)
|
SAMPLER(1, sampler2DDepth, depth_buffer)
|
||||||
PUSH_CONSTANT(int, bg_type)
|
PUSH_CONSTANT(int, bg_type)
|
||||||
PUSH_CONSTANT(float4, color_override)
|
PUSH_CONSTANT(float4, color_override)
|
||||||
|
PUSH_CONSTANT(float, vignette_aperture)
|
||||||
|
PUSH_CONSTANT(float, vignette_falloff)
|
||||||
|
PUSH_CONSTANT(bool, vignette_enabled)
|
||||||
FRAGMENT_SOURCE("overlay_background_frag.glsl")
|
FRAGMENT_SOURCE("overlay_background_frag.glsl")
|
||||||
FRAGMENT_OUT(0, float4, frag_color)
|
FRAGMENT_OUT(0, float4, frag_color)
|
||||||
ADDITIONAL_INFO(gpu_fullscreen)
|
ADDITIONAL_INFO(gpu_fullscreen)
|
||||||
|
|||||||
@@ -31,8 +31,19 @@ void main()
|
|||||||
* This removes the alpha channel and put the background behind reference images
|
* This removes the alpha channel and put the background behind reference images
|
||||||
* while masking the reference images by the render alpha.
|
* while masking the reference images by the render alpha.
|
||||||
*/
|
*/
|
||||||
float alpha = texture(color_buffer, screen_uv).a;
|
|
||||||
float depth = texture(depth_buffer, screen_uv).r;
|
float alpha;
|
||||||
|
float depth;
|
||||||
|
|
||||||
|
if (vignette_enabled) {
|
||||||
|
const float dist = length(screen_uv - 0.5f);
|
||||||
|
alpha = smoothstep(vignette_aperture, vignette_aperture + vignette_falloff, dist);
|
||||||
|
depth = 0.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alpha = texture(color_buffer, screen_uv).a;
|
||||||
|
depth = texture(depth_buffer, screen_uv).r;
|
||||||
|
}
|
||||||
|
|
||||||
float3 bg_col;
|
float3 bg_col;
|
||||||
float3 col_high;
|
float3 col_high;
|
||||||
@@ -90,11 +101,16 @@ void main()
|
|||||||
|
|
||||||
bg_col = mix(bg_col, color_override.rgb, color_override.a);
|
bg_col = mix(bg_col, color_override.rgb, color_override.a);
|
||||||
|
|
||||||
/* Mimic alpha under behavior. Result is premultiplied. */
|
if (vignette_enabled) {
|
||||||
frag_color = float4(bg_col, 1.0f) * (1.0f - alpha);
|
frag_color = float4(bg_col, alpha);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Mimic alpha under behavior. Result is premultiplied. */
|
||||||
|
frag_color = float4(bg_col, 1.0f) * (1.0f - alpha);
|
||||||
|
|
||||||
/* Special case: If the render is not transparent, do not clear alpha values. */
|
/* Special case: If the render is not transparent, do not clear alpha values. */
|
||||||
if (depth == 1.0f && alpha == 1.0f) {
|
if (depth == 1.0f && alpha == 1.0f) {
|
||||||
frag_color.a = 1.0f;
|
frag_color.a = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||||||
const float winmat[4][4],
|
const float winmat[4][4],
|
||||||
float clip_start,
|
float clip_start,
|
||||||
float clip_end,
|
float clip_end,
|
||||||
|
float vignette_aperture,
|
||||||
bool is_xr_surface,
|
bool is_xr_surface,
|
||||||
bool is_image_render,
|
bool is_image_render,
|
||||||
bool draw_background,
|
bool draw_background,
|
||||||
|
|||||||
@@ -1884,6 +1884,7 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||||||
const float winmat[4][4],
|
const float winmat[4][4],
|
||||||
float clip_start,
|
float clip_start,
|
||||||
float clip_end,
|
float clip_end,
|
||||||
|
float vignette_aperture,
|
||||||
bool is_xr_surface,
|
bool is_xr_surface,
|
||||||
bool is_image_render,
|
bool is_image_render,
|
||||||
bool draw_background,
|
bool draw_background,
|
||||||
@@ -1965,6 +1966,7 @@ void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
|||||||
v3d.clip_end = clip_end;
|
v3d.clip_end = clip_end;
|
||||||
/* Actually not used since we pass in the projection matrix. */
|
/* Actually not used since we pass in the projection matrix. */
|
||||||
v3d.lens = 0;
|
v3d.lens = 0;
|
||||||
|
v3d.vignette_aperture = vignette_aperture;
|
||||||
|
|
||||||
/* WORKAROUND: Disable overscan because it is not supported for arbitrary input matrices.
|
/* WORKAROUND: Disable overscan because it is not supported for arbitrary input matrices.
|
||||||
* The proper fix to this would be to support arbitrary matrices in `eevee::Camera::sync()`. */
|
* The proper fix to this would be to support arbitrary matrices in `eevee::Camera::sync()`. */
|
||||||
|
|||||||
@@ -486,6 +486,7 @@ set(GLSL_SRC
|
|||||||
shaders/infos/gpu_shader_sequencer_infos.hh
|
shaders/infos/gpu_shader_sequencer_infos.hh
|
||||||
shaders/infos/gpu_shader_simple_lighting_infos.hh
|
shaders/infos/gpu_shader_simple_lighting_infos.hh
|
||||||
shaders/infos/gpu_shader_text_infos.hh
|
shaders/infos/gpu_shader_text_infos.hh
|
||||||
|
shaders/infos/gpu_shader_xr_raycast_infos.hh
|
||||||
shaders/infos/gpu_srgb_to_framebuffer_space_infos.hh
|
shaders/infos/gpu_srgb_to_framebuffer_space_infos.hh
|
||||||
|
|
||||||
shaders/gpu_shader_depth_only_frag.glsl
|
shaders/gpu_shader_depth_only_frag.glsl
|
||||||
@@ -540,6 +541,7 @@ set(GLSL_SRC
|
|||||||
|
|
||||||
shaders/gpu_shader_text_vert.glsl
|
shaders/gpu_shader_text_vert.glsl
|
||||||
shaders/gpu_shader_text_frag.glsl
|
shaders/gpu_shader_text_frag.glsl
|
||||||
|
shaders/gpu_shader_xr_raycast_vert.glsl
|
||||||
shaders/gpu_shader_keyframe_shape_vert.glsl
|
shaders/gpu_shader_keyframe_shape_vert.glsl
|
||||||
shaders/gpu_shader_keyframe_shape_frag.glsl
|
shaders/gpu_shader_keyframe_shape_frag.glsl
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ enum GPUBuiltinShader {
|
|||||||
/** Draw sequencer zebra pattern (overexposed regions). */
|
/** Draw sequencer zebra pattern (overexposed regions). */
|
||||||
GPU_SHADER_SEQUENCER_ZEBRA,
|
GPU_SHADER_SEQUENCER_ZEBRA,
|
||||||
|
|
||||||
|
/** Draw xr raycast as a ruled spline surface. */
|
||||||
|
GPU_SHADER_XR_RAYCAST,
|
||||||
|
|
||||||
/** Compute shaders to generate 2d index buffers (mainly for curve drawing). */
|
/** Compute shaders to generate 2d index buffers (mainly for curve drawing). */
|
||||||
GPU_SHADER_INDEXBUF_POINTS,
|
GPU_SHADER_INDEXBUF_POINTS,
|
||||||
GPU_SHADER_INDEXBUF_LINES,
|
GPU_SHADER_INDEXBUF_LINES,
|
||||||
|
|||||||
11
source/blender/gpu/GPU_xr_defines.hh
Normal file
11
source/blender/gpu/GPU_xr_defines.hh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup gpu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define XR_MAX_RAYCASTS 8
|
||||||
@@ -119,6 +119,8 @@ static const char *builtin_shader_create_info_name(GPUBuiltinShader shader)
|
|||||||
return "gpu_shader_index_2d_array_lines";
|
return "gpu_shader_index_2d_array_lines";
|
||||||
case GPU_SHADER_INDEXBUF_TRIS:
|
case GPU_SHADER_INDEXBUF_TRIS:
|
||||||
return "gpu_shader_index_2d_array_tris";
|
return "gpu_shader_index_2d_array_tris";
|
||||||
|
case GPU_SHADER_XR_RAYCAST:
|
||||||
|
return "gpu_shader_xr_raycast";
|
||||||
default:
|
default:
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
43
source/blender/gpu/shaders/gpu_shader_xr_raycast_vert.glsl
Normal file
43
source/blender/gpu/shaders/gpu_shader_xr_raycast_vert.glsl
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2016-2024 Blender Authors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include "infos/gpu_shader_xr_raycast_infos.hh"
|
||||||
|
|
||||||
|
VERTEX_SHADER_CREATE_INFO(gpu_shader_xr_raycast)
|
||||||
|
|
||||||
|
vec3 catmull_rom(vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t)
|
||||||
|
{
|
||||||
|
float t2 = t * t;
|
||||||
|
float t3 = t2 * t;
|
||||||
|
return 0.5 * ((2.0 * p1) + (-p0 + p2) * t + (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 +
|
||||||
|
(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 get_control_point(int idx)
|
||||||
|
{
|
||||||
|
idx = clamp(idx, 0, control_point_count - 1);
|
||||||
|
return control_points[idx].xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
int sample_idx = gl_VertexID >> 1;
|
||||||
|
float side = ((gl_VertexID & 1) != 0) ? -1.0 : 1.0;
|
||||||
|
|
||||||
|
/** Interpolate within the range: [0, segment_count] */
|
||||||
|
float sample_value = float(sample_idx) * float(control_point_count - 1) /
|
||||||
|
float(sample_count - 1);
|
||||||
|
|
||||||
|
int segment_idx = int(sample_value);
|
||||||
|
float t = sample_value - float(segment_idx);
|
||||||
|
|
||||||
|
vec3 p0 = get_control_point(segment_idx - 1);
|
||||||
|
vec3 p1 = get_control_point(segment_idx + 0);
|
||||||
|
vec3 p2 = get_control_point(segment_idx + 1);
|
||||||
|
vec3 p3 = get_control_point(segment_idx + 2);
|
||||||
|
|
||||||
|
vec3 pos = catmull_rom(p0, p1, p2, p3, t) + 0.5 * width * side * right_vector;
|
||||||
|
|
||||||
|
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup gpu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef GPU_SHADER
|
||||||
|
# pragma once
|
||||||
|
# include "gpu_glsl_cpp_stubs.hh"
|
||||||
|
|
||||||
|
# include "GPU_shader_shared.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "GPU_xr_defines.hh"
|
||||||
|
#include "gpu_shader_create_info.hh"
|
||||||
|
|
||||||
|
GPU_SHADER_CREATE_INFO(gpu_shader_xr_raycast)
|
||||||
|
DEFINE_VALUE("XR_MAX_RAYCASTS", STRINGIFY(XR_MAX_RAYCASTS))
|
||||||
|
FRAGMENT_OUT(0, float4, fragColor)
|
||||||
|
PUSH_CONSTANT_ARRAY(float4, control_points, XR_MAX_RAYCASTS + 1)
|
||||||
|
PUSH_CONSTANT(float4x4, ModelViewProjectionMatrix)
|
||||||
|
PUSH_CONSTANT(float4, color)
|
||||||
|
PUSH_CONSTANT(float3, right_vector)
|
||||||
|
PUSH_CONSTANT(float, width)
|
||||||
|
PUSH_CONSTANT(int, control_point_count)
|
||||||
|
PUSH_CONSTANT(int, sample_count)
|
||||||
|
VERTEX_SOURCE("gpu_shader_xr_raycast_vert.glsl")
|
||||||
|
FRAGMENT_SOURCE("gpu_shader_uniform_color_frag.glsl")
|
||||||
|
ADDITIONAL_INFO(gpu_srgb_to_framebuffer_space)
|
||||||
|
DO_STATIC_COMPILATION()
|
||||||
|
GPU_SHADER_CREATE_END()
|
||||||
@@ -167,6 +167,14 @@ typedef struct WalkNavigation {
|
|||||||
char _pad0[6];
|
char _pad0[6];
|
||||||
} WalkNavigation;
|
} WalkNavigation;
|
||||||
|
|
||||||
|
typedef struct XrNavigation {
|
||||||
|
float vignette_intensity;
|
||||||
|
float turn_speed;
|
||||||
|
float turn_amount;
|
||||||
|
short flag;
|
||||||
|
char _pad0[2];
|
||||||
|
} XrNavigation;
|
||||||
|
|
||||||
typedef struct UserDef_Runtime {
|
typedef struct UserDef_Runtime {
|
||||||
/** Mark as changed so the preferences are saved on exit. */
|
/** Mark as changed so the preferences are saved on exit. */
|
||||||
char is_dirty;
|
char is_dirty;
|
||||||
@@ -619,6 +627,7 @@ typedef struct UserDef {
|
|||||||
char statusbar_flag; /* eUserpref_StatusBar_Flag */
|
char statusbar_flag; /* eUserpref_StatusBar_Flag */
|
||||||
|
|
||||||
struct WalkNavigation walk_navigation;
|
struct WalkNavigation walk_navigation;
|
||||||
|
struct XrNavigation xr_navigation;
|
||||||
|
|
||||||
/** The UI for the user preferences. */
|
/** The UI for the user preferences. */
|
||||||
UserDef_SpaceData space_data;
|
UserDef_SpaceData space_data;
|
||||||
@@ -1108,6 +1117,12 @@ typedef enum eUserpref_FactorDisplay {
|
|||||||
USER_FACTOR_AS_PERCENTAGE = 1,
|
USER_FACTOR_AS_PERCENTAGE = 1,
|
||||||
} eUserpref_FactorDisplay;
|
} eUserpref_FactorDisplay;
|
||||||
|
|
||||||
|
/** #UserDef.xr_navigation_flag */
|
||||||
|
typedef enum eUserpref_XrNavigationFlags {
|
||||||
|
USER_XR_NAV_SNAP_TURN = (1 << 0),
|
||||||
|
USER_XR_NAV_INVERT_ROTATION = (1 << 1),
|
||||||
|
} eUserpref_XrNavigationFlags;
|
||||||
|
|
||||||
typedef enum eUserpref_RenderDisplayType {
|
typedef enum eUserpref_RenderDisplayType {
|
||||||
USER_RENDER_DISPLAY_NONE = 0,
|
USER_RENDER_DISPLAY_NONE = 0,
|
||||||
USER_RENDER_DISPLAY_SCREEN = 1,
|
USER_RENDER_DISPLAY_SCREEN = 1,
|
||||||
|
|||||||
@@ -350,7 +350,8 @@ typedef struct View3D {
|
|||||||
|
|
||||||
float lens, grid;
|
float lens, grid;
|
||||||
float clip_start, clip_end;
|
float clip_start, clip_end;
|
||||||
float ofs[3] DNA_DEPRECATED;
|
float vignette_aperture;
|
||||||
|
float ofs[2] DNA_DEPRECATED;
|
||||||
|
|
||||||
char _pad[1];
|
char _pad[1];
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ typedef struct XrSessionSettings {
|
|||||||
/** Object type settings to apply to VR view (unlike shading, not shared with window 3D-View). */
|
/** 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_viewport;
|
||||||
int object_type_exclude_select;
|
int object_type_exclude_select;
|
||||||
|
|
||||||
|
/** Fly speed. */
|
||||||
|
float fly_speed;
|
||||||
|
float padding;
|
||||||
} XrSessionSettings;
|
} XrSessionSettings;
|
||||||
|
|
||||||
typedef enum eXrSessionFlag {
|
typedef enum eXrSessionFlag {
|
||||||
|
|||||||
@@ -531,6 +531,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
|
|||||||
SDNA_DEFAULT_DECL_EX(UserDef_SpaceData, UserDef.space_data),
|
SDNA_DEFAULT_DECL_EX(UserDef_SpaceData, UserDef.space_data),
|
||||||
SDNA_DEFAULT_DECL_EX(UserDef_FileSpaceData, UserDef.file_space_data),
|
SDNA_DEFAULT_DECL_EX(UserDef_FileSpaceData, UserDef.file_space_data),
|
||||||
SDNA_DEFAULT_DECL_EX(WalkNavigation, UserDef.walk_navigation),
|
SDNA_DEFAULT_DECL_EX(WalkNavigation, UserDef.walk_navigation),
|
||||||
|
SDNA_DEFAULT_DECL_EX(XrNavigation, UserDef.xr_navigation),
|
||||||
SDNA_DEFAULT_DECL(bUserAssetLibrary),
|
SDNA_DEFAULT_DECL(bUserAssetLibrary),
|
||||||
SDNA_DEFAULT_DECL(bUserExtensionRepo),
|
SDNA_DEFAULT_DECL(bUserExtensionRepo),
|
||||||
SDNA_DEFAULT_DECL(bUserAssetShelfSettings),
|
SDNA_DEFAULT_DECL(bUserAssetShelfSettings),
|
||||||
|
|||||||
@@ -4754,6 +4754,43 @@ static void rna_def_userdef_walk_navigation(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Reverse Mouse", "Reverse the vertical movement of the mouse");
|
RNA_def_property_ui_text(prop, "Reverse Mouse", "Reverse the vertical movement of the mouse");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_def_userdef_xr_navigation(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
srna = RNA_def_struct(brna, "XrNavigation", nullptr);
|
||||||
|
RNA_def_struct_sdna(srna, "XrNavigation");
|
||||||
|
RNA_def_struct_ui_text(srna, "VR Navigation", "VR navigation settings");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "vignette_intensity", PROP_FLOAT, PROP_PERCENTAGE);
|
||||||
|
RNA_def_property_range(prop, 0, 100.0);
|
||||||
|
RNA_def_property_ui_range(prop, 0, 100.0, 1000, 0);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Vignette Intensity", "Intensity of vignette that appears when moving");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "turn_speed", PROP_FLOAT, PROP_ANGLE);
|
||||||
|
RNA_def_property_range(prop, 0, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, 0, FLT_MAX, 1000, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Turn Speed", "Turn speed in degrees per second");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "turn_amount", PROP_FLOAT, PROP_ANGLE);
|
||||||
|
RNA_def_property_range(prop, 0, DEG2RAD(360));
|
||||||
|
RNA_def_property_ui_range(prop, 0, DEG2RAD(360), 1000, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Turn Amount", "Amount in degrees per turn when using snap turn");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "snap_turn", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_XR_NAV_SNAP_TURN);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop,
|
||||||
|
"Snap Turn",
|
||||||
|
"Instantly rotates the camera by a fixed angle instead of smoothly turning");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "invert_rotation", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_XR_NAV_INVERT_ROTATION);
|
||||||
|
RNA_def_property_ui_text(prop, "Invert Rotation", "Reverses the direction of rotation input");
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_def_userdef_view(BlenderRNA *brna)
|
static void rna_def_userdef_view(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
static const EnumPropertyItem timecode_styles[] = {
|
static const EnumPropertyItem timecode_styles[] = {
|
||||||
@@ -6493,6 +6530,12 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
|||||||
"restarting Blender for changes to take effect)");
|
"restarting Blender for changes to take effect)");
|
||||||
RNA_def_property_update(prop, 0, "rna_userdef_input_devices");
|
RNA_def_property_update(prop, 0, "rna_userdef_input_devices");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "xr_navigation", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_pointer_sdna(prop, nullptr, "xr_navigation");
|
||||||
|
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||||
|
RNA_def_property_struct_type(prop, "XrNavigation");
|
||||||
|
RNA_def_property_ui_text(prop, "XR Navigation", "Settings for navigation in XR");
|
||||||
|
|
||||||
# ifdef WITH_INPUT_NDOF
|
# ifdef WITH_INPUT_NDOF
|
||||||
/* 3D mouse settings */
|
/* 3D mouse settings */
|
||||||
/* global options */
|
/* global options */
|
||||||
@@ -7439,6 +7482,7 @@ void RNA_def_userdef(BlenderRNA *brna)
|
|||||||
rna_def_userdef_dothemes(brna);
|
rna_def_userdef_dothemes(brna);
|
||||||
rna_def_userdef_solidlight(brna);
|
rna_def_userdef_solidlight(brna);
|
||||||
rna_def_userdef_walk_navigation(brna);
|
rna_def_userdef_walk_navigation(brna);
|
||||||
|
rna_def_userdef_xr_navigation(brna);
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "Preferences", nullptr);
|
srna = RNA_def_struct(brna, "Preferences", nullptr);
|
||||||
RNA_def_struct_sdna(srna, "UserDef");
|
RNA_def_struct_sdna(srna, "UserDef");
|
||||||
|
|||||||
@@ -2035,16 +2035,22 @@ static void rna_def_xr_session_settings(BlenderRNA *brna)
|
|||||||
|
|
||||||
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
|
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
|
||||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
|
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 0.1 * 100, 3);
|
||||||
RNA_def_property_ui_text(prop, "Clip Start", "VR viewport near clipping distance");
|
RNA_def_property_ui_text(prop, "Clip Start", "VR viewport near clipping distance");
|
||||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, nullptr);
|
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, nullptr);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
|
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
|
||||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
|
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10 * 100, 3);
|
||||||
RNA_def_property_ui_text(prop, "Clip End", "VR viewport far clipping distance");
|
RNA_def_property_ui_text(prop, "Clip End", "VR viewport far clipping distance");
|
||||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, nullptr);
|
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, nullptr);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "fly_speed", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 0.5 * 100, 3);
|
||||||
|
RNA_def_property_ui_text(prop, "Fly Speed", "Fly speed in meters per second");
|
||||||
|
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, nullptr);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_positional_tracking", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_positional_tracking", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_funcs(prop,
|
RNA_def_property_boolean_funcs(prop,
|
||||||
"rna_XrSessionSettings_use_positional_tracking_get",
|
"rna_XrSessionSettings_use_positional_tracking_get",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ set(INC
|
|||||||
gizmo/intern
|
gizmo/intern
|
||||||
../compositor
|
../compositor
|
||||||
../editors/include
|
../editors/include
|
||||||
|
../gpu
|
||||||
../makesrna
|
../makesrna
|
||||||
../../../intern/memutil
|
../../../intern/memutil
|
||||||
|
|
||||||
|
|||||||
@@ -2180,6 +2180,9 @@ void WM_xr_session_state_nav_rotation_set(wmXrData *xr, const float rotation[4])
|
|||||||
bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale);
|
bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale);
|
||||||
void WM_xr_session_state_nav_scale_set(wmXrData *xr, float scale);
|
void WM_xr_session_state_nav_scale_set(wmXrData *xr, float scale);
|
||||||
void WM_xr_session_state_navigation_reset(wmXrSessionState *state);
|
void WM_xr_session_state_navigation_reset(wmXrSessionState *state);
|
||||||
|
void WM_xr_session_state_vignette_reset(wmXrSessionState *state);
|
||||||
|
void WM_xr_session_state_vignette_activate(wmXrData *xr);
|
||||||
|
void WM_xr_session_state_vignette_update(wmXrSessionState *state);
|
||||||
|
|
||||||
ARegionType *WM_xr_surface_controller_region_type_get();
|
ARegionType *WM_xr_surface_controller_region_type_get();
|
||||||
|
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ void wm_xr_runtime_data_free(wmXrRuntimeData **runtime)
|
|||||||
if ((*runtime)->area) {
|
if ((*runtime)->area) {
|
||||||
wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
|
wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
|
||||||
wmWindow *win = wm_xr_session_root_window_or_fallback_get(wm, (*runtime));
|
wmWindow *win = wm_xr_session_root_window_or_fallback_get(wm, (*runtime));
|
||||||
|
|
||||||
|
WM_event_remove_handlers_by_area(&win->handlers, (*runtime)->area);
|
||||||
ED_area_offscreen_free(wm, win, (*runtime)->area);
|
ED_area_offscreen_free(wm, win, (*runtime)->area);
|
||||||
(*runtime)->area = nullptr;
|
(*runtime)->area = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
#include "GPU_state.hh"
|
#include "GPU_state.hh"
|
||||||
#include "GPU_viewport.hh"
|
#include "GPU_viewport.hh"
|
||||||
|
|
||||||
|
#include "UI_resources.hh"
|
||||||
|
|
||||||
#include "WM_api.hh"
|
#include "WM_api.hh"
|
||||||
|
|
||||||
#include "wm_xr_intern.hh"
|
#include "wm_xr_intern.hh"
|
||||||
@@ -180,6 +182,7 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
|
|||||||
winmat,
|
winmat,
|
||||||
settings->clip_start,
|
settings->clip_start,
|
||||||
settings->clip_end,
|
settings->clip_end,
|
||||||
|
session_state->vignette_data->aperture,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
@@ -337,7 +340,7 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
|
|||||||
break;
|
break;
|
||||||
case XR_CONTROLLER_DRAW_DARK_RAY:
|
case XR_CONTROLLER_DRAW_DARK_RAY:
|
||||||
case XR_CONTROLLER_DRAW_LIGHT_RAY:
|
case XR_CONTROLLER_DRAW_LIGHT_RAY:
|
||||||
draw_ray = true;
|
draw_ray = !state->is_raycast_shown;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ struct wmXrSessionState {
|
|||||||
|
|
||||||
bool force_reset_to_base_pose;
|
bool force_reset_to_base_pose;
|
||||||
bool is_view_data_set;
|
bool is_view_data_set;
|
||||||
|
bool swap_hands;
|
||||||
|
bool is_raycast_shown;
|
||||||
|
|
||||||
/** Current navigation transforms. */
|
/** Current navigation transforms. */
|
||||||
GHOST_XrPose nav_pose;
|
GHOST_XrPose nav_pose;
|
||||||
@@ -72,6 +74,12 @@ struct wmXrSessionState {
|
|||||||
struct wmXrActionSet *active_action_set;
|
struct wmXrActionSet *active_action_set;
|
||||||
/* Name of the action set (if any) to activate before the next actions sync. */
|
/* Name of the action set (if any) to activate before the next actions sync. */
|
||||||
char active_action_set_next[64]; /* #MAX_NAME. */
|
char active_action_set_next[64]; /* #MAX_NAME. */
|
||||||
|
|
||||||
|
/** The current state and parameters of the vignette that appears while moving. */
|
||||||
|
struct wmXrVignetteData *vignette_data;
|
||||||
|
|
||||||
|
/** Model used to draw teleportation raycast. */
|
||||||
|
blender::gpu::Batch *raycast_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wmXrRuntimeData {
|
struct wmXrRuntimeData {
|
||||||
@@ -200,6 +208,22 @@ struct wmXrActionSet {
|
|||||||
ListBase active_haptic_actions;
|
ListBase active_haptic_actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wmXrVignetteData {
|
||||||
|
/** Vignette state. */
|
||||||
|
float aperture;
|
||||||
|
float aperture_velocity;
|
||||||
|
|
||||||
|
/** Vignette parameters. */
|
||||||
|
float initial_aperture;
|
||||||
|
float initial_aperture_velocity;
|
||||||
|
|
||||||
|
float aperture_min;
|
||||||
|
float aperture_max;
|
||||||
|
|
||||||
|
float aperture_velocity_max;
|
||||||
|
float aperture_velocity_delta;
|
||||||
|
};
|
||||||
|
|
||||||
/* `wm_xr.cc` */
|
/* `wm_xr.cc` */
|
||||||
|
|
||||||
wmXrRuntimeData *wm_xr_runtime_data_create();
|
wmXrRuntimeData *wm_xr_runtime_data_create();
|
||||||
|
|||||||
@@ -37,6 +37,10 @@
|
|||||||
#include "GPU_immediate.hh"
|
#include "GPU_immediate.hh"
|
||||||
#include "GPU_state.hh"
|
#include "GPU_state.hh"
|
||||||
|
|
||||||
|
#include "GPU_batch_presets.hh"
|
||||||
|
#include "GPU_matrix.hh"
|
||||||
|
#include "GPU_xr_defines.hh"
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "RNA_access.hh"
|
#include "RNA_access.hh"
|
||||||
@@ -529,6 +533,11 @@ static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *ac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm_xr_navigation_grab_cancel(bContext * /*C*/, wmOperator *op)
|
||||||
|
{
|
||||||
|
wm_xr_grab_uninit(op);
|
||||||
|
}
|
||||||
|
|
||||||
static wmOperatorStatus wm_xr_navigation_grab_modal(bContext *C,
|
static wmOperatorStatus wm_xr_navigation_grab_modal(bContext *C,
|
||||||
wmOperator *op,
|
wmOperator *op,
|
||||||
const wmEvent *event)
|
const wmEvent *event)
|
||||||
@@ -542,6 +551,8 @@ static wmOperatorStatus wm_xr_navigation_grab_modal(bContext *C,
|
|||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
wmXrData *xr = &wm->xr;
|
wmXrData *xr = &wm->xr;
|
||||||
|
|
||||||
|
WM_xr_session_state_vignette_activate(xr);
|
||||||
|
|
||||||
const bool do_bimanual = wm_xr_navigation_grab_can_do_bimanual(actiondata, data);
|
const bool do_bimanual = wm_xr_navigation_grab_can_do_bimanual(actiondata, data);
|
||||||
|
|
||||||
data->loc_lock = RNA_boolean_get(op->ptr, "lock_location");
|
data->loc_lock = RNA_boolean_get(op->ptr, "lock_location");
|
||||||
@@ -588,6 +599,7 @@ static void WM_OT_xr_navigation_grab(wmOperatorType *ot)
|
|||||||
/* Callbacks. */
|
/* Callbacks. */
|
||||||
ot->invoke = wm_xr_navigation_grab_invoke;
|
ot->invoke = wm_xr_navigation_grab_invoke;
|
||||||
ot->exec = wm_xr_navigation_grab_exec;
|
ot->exec = wm_xr_navigation_grab_exec;
|
||||||
|
ot->cancel = wm_xr_navigation_grab_cancel;
|
||||||
ot->modal = wm_xr_navigation_grab_modal;
|
ot->modal = wm_xr_navigation_grab_modal;
|
||||||
ot->poll = wm_xr_operator_sessionactive;
|
ot->poll = wm_xr_operator_sessionactive;
|
||||||
|
|
||||||
@@ -613,21 +625,60 @@ static void WM_OT_xr_navigation_grab(wmOperatorType *ot)
|
|||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static const float g_xr_default_raycast_axis[3] = {0.0f, 0.0f, -1.0f};
|
static const float g_xr_default_raycast_axis[3] = {0.0f, 0.0f, -1.0f};
|
||||||
static const float g_xr_default_raycast_color[4] = {0.35f, 0.35f, 1.0f, 1.0f};
|
static const float g_xr_default_raycast_hit_color[4] = {0.35f, 0.35f, 1.0f, 1.0f};
|
||||||
|
static const float g_xr_default_raycast_miss_color[4] = {1.0f, 0.35f, 0.35f, 1.0f};
|
||||||
|
static const float g_xr_default_raycast_fallback_color[4] = {0.35f, 0.35f, 1.0f, 1.0f};
|
||||||
|
|
||||||
|
enum XrRaycastResult : uint8_t {
|
||||||
|
XR_RAYCAST_MISS,
|
||||||
|
XR_RAYCAST_HIT,
|
||||||
|
XR_RAYCAST_FALLBACK,
|
||||||
|
};
|
||||||
|
|
||||||
struct XrRaycastData {
|
struct XrRaycastData {
|
||||||
|
/** Raycast info */
|
||||||
bool from_viewer;
|
bool from_viewer;
|
||||||
float origin[3];
|
|
||||||
|
/** Raycast results */
|
||||||
|
XrRaycastResult result;
|
||||||
|
int num_points;
|
||||||
|
float points[XR_MAX_RAYCASTS + 1][4];
|
||||||
float direction[3];
|
float direction[3];
|
||||||
float end[3];
|
|
||||||
|
/** Raycast visualization parameters */
|
||||||
float color[4];
|
float color[4];
|
||||||
|
float raycast_width;
|
||||||
|
float destination_size;
|
||||||
|
int sample_count;
|
||||||
|
|
||||||
|
blender::gpu::Batch *raycast_model;
|
||||||
|
|
||||||
void *draw_handle;
|
void *draw_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void wm_xr_raycast_destination_draw(const XrRaycastData *data)
|
||||||
|
{
|
||||||
|
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
||||||
|
|
||||||
|
blender::gpu::Batch *sphere = GPU_batch_preset_sphere(2);
|
||||||
|
GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
|
||||||
|
GPU_batch_uniform_4fv(sphere, "color", data->color);
|
||||||
|
|
||||||
|
GPU_matrix_push();
|
||||||
|
GPU_matrix_translate_3fv(data->points[data->num_points - 1]);
|
||||||
|
GPU_matrix_scale_1f(data->destination_size);
|
||||||
|
GPU_batch_draw(sphere);
|
||||||
|
GPU_matrix_pop();
|
||||||
|
}
|
||||||
|
|
||||||
static void wm_xr_raycast_draw(const bContext * /*C*/, ARegion * /*region*/, void *customdata)
|
static void wm_xr_raycast_draw(const bContext * /*C*/, ARegion * /*region*/, void *customdata)
|
||||||
{
|
{
|
||||||
const XrRaycastData *data = static_cast<const XrRaycastData *>(customdata);
|
const XrRaycastData *data = static_cast<const XrRaycastData *>(customdata);
|
||||||
|
|
||||||
|
if (data->result != XR_RAYCAST_MISS) {
|
||||||
|
wm_xr_raycast_destination_draw(data);
|
||||||
|
}
|
||||||
|
|
||||||
GPUVertFormat *format = immVertexFormat();
|
GPUVertFormat *format = immVertexFormat();
|
||||||
uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32_32);
|
uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32_32);
|
||||||
|
|
||||||
@@ -638,32 +689,37 @@ static void wm_xr_raycast_draw(const bContext * /*C*/, ARegion * /*region*/, voi
|
|||||||
GPU_depth_test(GPU_DEPTH_NONE);
|
GPU_depth_test(GPU_DEPTH_NONE);
|
||||||
GPU_point_size(7.0f);
|
GPU_point_size(7.0f);
|
||||||
|
|
||||||
immBegin(GPU_PRIM_POINTS, 1);
|
immBegin(GPU_PRIM_POINTS, data->num_points - 1);
|
||||||
immVertex3fv(pos, data->end);
|
|
||||||
|
for (int i = 1; i < data->num_points; ++i) {
|
||||||
|
immVertex3fv(pos, data->points[i]);
|
||||||
|
}
|
||||||
|
|
||||||
immEnd();
|
immEnd();
|
||||||
|
immUnbindProgram();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint col = GPU_vertformat_attr_add(
|
BLI_assert(data->raycast_model != nullptr);
|
||||||
format, "color", blender::gpu::VertAttrType::SFLOAT_32_32_32_32);
|
|
||||||
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_FLAT_COLOR);
|
|
||||||
|
|
||||||
float viewport[4];
|
float forward[3];
|
||||||
GPU_viewport_size_get_f(viewport);
|
float right[3];
|
||||||
immUniform2fv("viewportSize", &viewport[2]);
|
|
||||||
|
|
||||||
immUniform1f("lineWidth", 3.0f * U.pixelsize);
|
sub_v3_v3v3(forward, data->points[data->num_points - 1], data->points[0]);
|
||||||
|
copy_v3_fl3(right, forward[1], -forward[0], 0.0f);
|
||||||
|
normalize_v3(right);
|
||||||
|
|
||||||
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
||||||
|
|
||||||
immBegin(GPU_PRIM_LINES, 2);
|
GPU_batch_program_set_builtin(data->raycast_model, GPU_SHADER_XR_RAYCAST);
|
||||||
immAttrSkip(col);
|
GPU_batch_uniform_4fv_array(
|
||||||
immVertex3fv(pos, data->origin);
|
data->raycast_model, "control_points", XR_MAX_RAYCASTS + 1, data->points);
|
||||||
immAttr4fv(col, data->color);
|
GPU_batch_uniform_4fv(data->raycast_model, "color", data->color);
|
||||||
immVertex3fv(pos, data->end);
|
GPU_batch_uniform_3fv(data->raycast_model, "right_vector", right);
|
||||||
immEnd();
|
GPU_batch_uniform_1f(data->raycast_model, "width", data->raycast_width);
|
||||||
|
GPU_batch_uniform_1i(data->raycast_model, "control_point_count", data->num_points);
|
||||||
|
GPU_batch_uniform_1i(data->raycast_model, "sample_count", data->sample_count);
|
||||||
|
GPU_batch_draw(data->raycast_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
immUnbindProgram();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm_xr_raycast_init(wmOperator *op)
|
static void wm_xr_raycast_init(wmOperator *op)
|
||||||
@@ -712,27 +768,34 @@ static void wm_xr_raycast_update(wmOperator *op,
|
|||||||
const wmXrActionData *actiondata)
|
const wmXrActionData *actiondata)
|
||||||
{
|
{
|
||||||
XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
|
XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
|
||||||
float ray_length, axis[3];
|
float axis[3], nav_scale;
|
||||||
|
|
||||||
|
WM_xr_session_state_nav_scale_get(xr, &nav_scale);
|
||||||
|
|
||||||
data->from_viewer = RNA_boolean_get(op->ptr, "from_viewer");
|
data->from_viewer = RNA_boolean_get(op->ptr, "from_viewer");
|
||||||
|
data->raycast_width = RNA_float_get(op->ptr, "raycast_scale") * nav_scale;
|
||||||
|
data->sample_count = RNA_int_get(op->ptr, "sample_count");
|
||||||
RNA_float_get_array(op->ptr, "axis", axis);
|
RNA_float_get_array(op->ptr, "axis", axis);
|
||||||
RNA_float_get_array(op->ptr, "color", data->color);
|
|
||||||
|
|
||||||
if (data->from_viewer) {
|
if (data->from_viewer) {
|
||||||
float viewer_rot[4];
|
float viewer_rot[4];
|
||||||
WM_xr_session_state_viewer_pose_location_get(xr, data->origin);
|
WM_xr_session_state_viewer_pose_location_get(xr, data->points[0]);
|
||||||
WM_xr_session_state_viewer_pose_rotation_get(xr, viewer_rot);
|
WM_xr_session_state_viewer_pose_rotation_get(xr, viewer_rot);
|
||||||
mul_qt_v3(viewer_rot, axis);
|
mul_qt_v3(viewer_rot, axis);
|
||||||
ray_length = (xr->session_settings.clip_start + xr->session_settings.clip_end) / 2.0f;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_v3_v3(data->origin, actiondata->controller_loc);
|
if (!xr->runtime->session_state.raycast_model) {
|
||||||
|
xr->runtime->session_state.raycast_model = GPU_batch_create_procedural(
|
||||||
|
GPU_PRIM_TRI_STRIP, 2 * data->sample_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->raycast_model = xr->runtime->session_state.raycast_model;
|
||||||
|
|
||||||
|
copy_v3_v3(data->points[0], actiondata->controller_loc);
|
||||||
mul_qt_v3(actiondata->controller_rot, axis);
|
mul_qt_v3(actiondata->controller_rot, axis);
|
||||||
ray_length = xr->session_settings.clip_end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_v3_v3(data->direction, axis);
|
copy_v3_v3(data->direction, axis);
|
||||||
madd_v3_v3v3fl(data->end, data->origin, data->direction, ray_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm_xr_raycast(Scene *scene,
|
static void wm_xr_raycast(Scene *scene,
|
||||||
@@ -779,8 +842,6 @@ static void wm_xr_raycast(Scene *scene,
|
|||||||
* controller.
|
* controller.
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
#define XR_DEFAULT_FLY_SPEED_MOVE 0.054f
|
|
||||||
|
|
||||||
enum eXrFlyMode {
|
enum eXrFlyMode {
|
||||||
XR_FLY_FORWARD = 0,
|
XR_FLY_FORWARD = 0,
|
||||||
XR_FLY_BACK = 1,
|
XR_FLY_BACK = 1,
|
||||||
@@ -800,6 +861,9 @@ enum eXrFlyMode {
|
|||||||
struct XrFlyData {
|
struct XrFlyData {
|
||||||
float viewer_rot[4];
|
float viewer_rot[4];
|
||||||
double time_prev;
|
double time_prev;
|
||||||
|
|
||||||
|
/* Only used for snap turn, where the action should be executed only once. */
|
||||||
|
bool is_finished;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
|
static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
|
||||||
@@ -946,6 +1010,11 @@ static wmOperatorStatus wm_xr_navigation_fly_exec(bContext * /*C*/, wmOperator *
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm_xr_navigation_fly_cancel(bContext * /*C*/, wmOperator *op)
|
||||||
|
{
|
||||||
|
wm_xr_fly_uninit(op);
|
||||||
|
}
|
||||||
|
|
||||||
static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C,
|
static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C,
|
||||||
wmOperator *op,
|
wmOperator *op,
|
||||||
const wmEvent *event)
|
const wmEvent *event)
|
||||||
@@ -964,22 +1033,41 @@ static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C,
|
|||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
wmXrData *xr = &wm->xr;
|
wmXrData *xr = &wm->xr;
|
||||||
eXrFlyMode mode;
|
eXrFlyMode mode;
|
||||||
bool turn, locz_lock, dir_lock, speed_frame_based;
|
bool turn, snap_turn, invert_rotation, swap_hands, locz_lock, dir_lock, speed_frame_based;
|
||||||
bool speed_interp_cubic = false;
|
bool speed_interp_cubic = false;
|
||||||
float speed, speed_max, speed_p0[2], speed_p1[2];
|
float speed, speed_max, speed_p0[2], speed_p1[2], button_state;
|
||||||
GHOST_XrPose nav_pose;
|
GHOST_XrPose nav_pose;
|
||||||
float nav_mat[4][4], delta[4][4], out[4][4];
|
float nav_mat[4][4], delta[4][4], out[4][4];
|
||||||
|
|
||||||
const double time_now = BLI_time_now_seconds();
|
const double time_now = BLI_time_now_seconds(), delta_time = time_now - data->time_prev;
|
||||||
|
data->time_prev = time_now;
|
||||||
|
|
||||||
mode = (eXrFlyMode)RNA_enum_get(op->ptr, "mode");
|
swap_hands = xr->runtime->session_state.swap_hands;
|
||||||
|
mode = (eXrFlyMode)RNA_enum_get(op->ptr, swap_hands ? "alt_mode" : "mode");
|
||||||
turn = ELEM(mode, XR_FLY_TURNLEFT, XR_FLY_TURNRIGHT);
|
turn = ELEM(mode, XR_FLY_TURNLEFT, XR_FLY_TURNRIGHT);
|
||||||
|
snap_turn = U.xr_navigation.flag & USER_XR_NAV_SNAP_TURN;
|
||||||
|
invert_rotation = U.xr_navigation.flag & USER_XR_NAV_INVERT_ROTATION;
|
||||||
|
|
||||||
locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
|
locz_lock = RNA_boolean_get(op->ptr, swap_hands ? "alt_lock_location_z" : "lock_location_z");
|
||||||
dir_lock = RNA_boolean_get(op->ptr, "lock_direction");
|
dir_lock = RNA_boolean_get(op->ptr, swap_hands ? "alt_lock_direction" : "lock_direction");
|
||||||
speed_frame_based = RNA_boolean_get(op->ptr, "speed_frame_based");
|
|
||||||
speed = RNA_float_get(op->ptr, "speed_min");
|
if (turn) {
|
||||||
speed_max = RNA_float_get(op->ptr, "speed_max");
|
speed_frame_based = false;
|
||||||
|
|
||||||
|
if (snap_turn) {
|
||||||
|
speed_max = U.xr_navigation.turn_amount;
|
||||||
|
speed = speed_max;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
speed_max = U.xr_navigation.turn_speed;
|
||||||
|
speed = speed_max * RNA_boolean_get(op->ptr, "turn_speed_factor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
speed_frame_based = RNA_boolean_get(op->ptr, "speed_frame_based");
|
||||||
|
speed_max = xr->session_settings.fly_speed;
|
||||||
|
speed = speed_max * RNA_float_get(op->ptr, "fly_speed_factor");
|
||||||
|
}
|
||||||
|
|
||||||
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "speed_interpolation0");
|
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "speed_interpolation0");
|
||||||
if (prop && RNA_property_is_set(op->ptr, prop)) {
|
if (prop && RNA_property_is_set(op->ptr, prop)) {
|
||||||
@@ -1007,14 +1095,15 @@ static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C,
|
|||||||
/* Interpolate between min/max speeds based on button state. */
|
/* Interpolate between min/max speeds based on button state. */
|
||||||
switch (actiondata->type) {
|
switch (actiondata->type) {
|
||||||
case XR_BOOLEAN_INPUT:
|
case XR_BOOLEAN_INPUT:
|
||||||
|
button_state = 1.0f;
|
||||||
speed = speed_max;
|
speed = speed_max;
|
||||||
break;
|
break;
|
||||||
case XR_FLOAT_INPUT:
|
case XR_FLOAT_INPUT:
|
||||||
case XR_VECTOR2F_INPUT: {
|
case XR_VECTOR2F_INPUT: {
|
||||||
float state = (actiondata->type == XR_FLOAT_INPUT) ? fabsf(actiondata->state[0]) :
|
button_state = (actiondata->type == XR_FLOAT_INPUT) ? fabsf(actiondata->state[0]) :
|
||||||
len_v2(actiondata->state);
|
len_v2(actiondata->state);
|
||||||
float speed_t = (actiondata->float_threshold < 1.0f) ?
|
float speed_t = (actiondata->float_threshold < 1.0f) ?
|
||||||
(state - actiondata->float_threshold) /
|
(button_state - actiondata->float_threshold) /
|
||||||
(1.0f - actiondata->float_threshold) :
|
(1.0f - actiondata->float_threshold) :
|
||||||
1.0f;
|
1.0f;
|
||||||
if (speed_interp_cubic) {
|
if (speed_interp_cubic) {
|
||||||
@@ -1041,21 +1130,29 @@ static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!speed_frame_based) {
|
|
||||||
/* Adjust speed based on last update time. */
|
|
||||||
speed *= time_now - data->time_prev;
|
|
||||||
}
|
|
||||||
data->time_prev = time_now;
|
|
||||||
|
|
||||||
WM_xr_session_state_nav_location_get(xr, nav_pose.position);
|
WM_xr_session_state_nav_location_get(xr, nav_pose.position);
|
||||||
WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
|
WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
|
||||||
wm_xr_pose_to_mat(&nav_pose, nav_mat);
|
wm_xr_pose_to_mat(&nav_pose, nav_mat);
|
||||||
|
|
||||||
if (turn) {
|
if (turn) {
|
||||||
if (dir_lock) {
|
if (dir_lock || (snap_turn && data->is_finished) ||
|
||||||
|
(snap_turn && button_state < RNA_float_get(op->ptr, "snap_turn_threshold")))
|
||||||
|
{
|
||||||
unit_m4(delta);
|
unit_m4(delta);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (!snap_turn) {
|
||||||
|
WM_xr_session_state_vignette_activate(xr);
|
||||||
|
speed *= delta_time;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->is_finished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invert_rotation) {
|
||||||
|
speed *= -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_XrPose viewer_pose;
|
GHOST_XrPose viewer_pose;
|
||||||
float viewer_mat[4][4], nav_inv[4][4];
|
float viewer_mat[4][4], nav_inv[4][4];
|
||||||
|
|
||||||
@@ -1070,10 +1167,16 @@ static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C,
|
|||||||
else {
|
else {
|
||||||
float nav_scale, ref_quat[4];
|
float nav_scale, ref_quat[4];
|
||||||
|
|
||||||
|
WM_xr_session_state_vignette_activate(xr);
|
||||||
|
|
||||||
/* Adjust speed for base and navigation scale. */
|
/* Adjust speed for base and navigation scale. */
|
||||||
WM_xr_session_state_nav_scale_get(xr, &nav_scale);
|
WM_xr_session_state_nav_scale_get(xr, &nav_scale);
|
||||||
speed *= xr->session_settings.base_scale * nav_scale;
|
speed *= xr->session_settings.base_scale * nav_scale;
|
||||||
|
|
||||||
|
if (!speed_frame_based) {
|
||||||
|
speed *= delta_time;
|
||||||
|
}
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
/* Move relative to navigation space. */
|
/* Move relative to navigation space. */
|
||||||
case XR_FLY_FORWARD:
|
case XR_FLY_FORWARD:
|
||||||
@@ -1140,6 +1243,7 @@ static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
|
|||||||
/* Callbacks. */
|
/* Callbacks. */
|
||||||
ot->invoke = wm_xr_navigation_fly_invoke;
|
ot->invoke = wm_xr_navigation_fly_invoke;
|
||||||
ot->exec = wm_xr_navigation_fly_exec;
|
ot->exec = wm_xr_navigation_fly_exec;
|
||||||
|
ot->cancel = wm_xr_navigation_fly_cancel;
|
||||||
ot->modal = wm_xr_navigation_fly_modal;
|
ot->modal = wm_xr_navigation_fly_modal;
|
||||||
ot->poll = wm_xr_operator_sessionactive;
|
ot->poll = wm_xr_operator_sessionactive;
|
||||||
|
|
||||||
@@ -1179,6 +1283,15 @@ static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
|
|||||||
prop = RNA_def_enum(ot->srna, "mode", fly_modes, XR_FLY_VIEWER_FORWARD, "Mode", "Fly mode");
|
prop = RNA_def_enum(ot->srna, "mode", fly_modes, XR_FLY_VIEWER_FORWARD, "Mode", "Fly mode");
|
||||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_NAVIGATION);
|
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_NAVIGATION);
|
||||||
|
|
||||||
|
RNA_def_float(ot->srna,
|
||||||
|
"snap_turn_threshold",
|
||||||
|
0.95f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
"Snap Turn Threshold",
|
||||||
|
"Input state threshold when using snap turn",
|
||||||
|
0.0f,
|
||||||
|
1.0f);
|
||||||
RNA_def_boolean(
|
RNA_def_boolean(
|
||||||
ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
|
ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
|
||||||
RNA_def_boolean(ot->srna,
|
RNA_def_boolean(ot->srna,
|
||||||
@@ -1188,27 +1301,27 @@ static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
|
|||||||
"Limit movement to viewer's initial direction");
|
"Limit movement to viewer's initial direction");
|
||||||
RNA_def_boolean(ot->srna,
|
RNA_def_boolean(ot->srna,
|
||||||
"speed_frame_based",
|
"speed_frame_based",
|
||||||
true,
|
false,
|
||||||
"Frame Based Speed",
|
"Frame Based Speed",
|
||||||
"Apply fixed movement deltas every update");
|
"Apply fixed movement deltas every update");
|
||||||
RNA_def_float(ot->srna,
|
RNA_def_float(ot->srna,
|
||||||
"speed_min",
|
"turn_speed_factor",
|
||||||
XR_DEFAULT_FLY_SPEED_MOVE / 3.0f,
|
1.0 / 3.0f,
|
||||||
0.0f,
|
0.0f,
|
||||||
1000.0f,
|
1.0f,
|
||||||
"Minimum Speed",
|
"Turn Speed Factor",
|
||||||
"Minimum move (turn) speed in meters (radians) per second or frame",
|
"Ratio between the min and max turn speed",
|
||||||
0.0f,
|
0.0f,
|
||||||
1000.0f);
|
1.0f);
|
||||||
RNA_def_float(ot->srna,
|
RNA_def_float(ot->srna,
|
||||||
"speed_max",
|
"fly_speed_factor",
|
||||||
XR_DEFAULT_FLY_SPEED_MOVE,
|
1.0 / 3.0f,
|
||||||
0.0f,
|
0.0f,
|
||||||
1000.0f,
|
1.0f,
|
||||||
"Maximum Speed",
|
"Fly Speed Factor",
|
||||||
"Maximum move (turn) speed in meters (radians) per second or frame",
|
"Ratio between the min and max fly speed",
|
||||||
0.0f,
|
0.0f,
|
||||||
1000.0f);
|
1.0f);
|
||||||
RNA_def_float_vector(ot->srna,
|
RNA_def_float_vector(ot->srna,
|
||||||
"speed_interpolation0",
|
"speed_interpolation0",
|
||||||
2,
|
2,
|
||||||
@@ -1229,6 +1342,23 @@ static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
|
|||||||
"Second cubic spline control point between min/max speeds",
|
"Second cubic spline control point between min/max speeds",
|
||||||
0.0f,
|
0.0f,
|
||||||
1.0f);
|
1.0f);
|
||||||
|
|
||||||
|
RNA_def_enum(ot->srna,
|
||||||
|
"alt_mode",
|
||||||
|
fly_modes,
|
||||||
|
XR_FLY_VIEWER_FORWARD,
|
||||||
|
"Mode (Alt)",
|
||||||
|
"Fly mode when hands are swapped");
|
||||||
|
RNA_def_boolean(ot->srna,
|
||||||
|
"alt_lock_location_z",
|
||||||
|
false,
|
||||||
|
"Lock Elevation (Alt)",
|
||||||
|
"When hands are swapped, prevent changes to viewer elevation");
|
||||||
|
RNA_def_boolean(ot->srna,
|
||||||
|
"alt_lock_direction",
|
||||||
|
false,
|
||||||
|
"Lock Direction (Alt)",
|
||||||
|
"When hands are swapped, limit movement to viewer's initial direction");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
@@ -1239,68 +1369,221 @@ static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
|
|||||||
* Casts a ray from an XR controller's pose and teleports to any hit geometry.
|
* Casts a ray from an XR controller's pose and teleports to any hit geometry.
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static void wm_xr_navigation_teleport(bContext *C,
|
static float wm_xr_navigation_teleport_pose_calc(wmXrData *xr,
|
||||||
wmXrData *xr,
|
float nav_destination[3],
|
||||||
const float origin[3],
|
const float destination[4],
|
||||||
const float direction[3],
|
const float normal[3],
|
||||||
float *ray_dist,
|
const bool teleport_axes[3],
|
||||||
bool selectable_only,
|
float teleport_t,
|
||||||
const bool teleport_axes[3],
|
float teleport_ofs,
|
||||||
float teleport_t,
|
float vertical_ofs)
|
||||||
float teleport_ofs)
|
{
|
||||||
|
float nav_location[3], nav_rotation[4], viewer_location[3];
|
||||||
|
WM_xr_session_state_nav_location_get(xr, nav_location);
|
||||||
|
WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
|
||||||
|
WM_xr_session_state_viewer_pose_location_get(xr, viewer_location);
|
||||||
|
|
||||||
|
float nav_axes[3][3], projected[3], v0[3], v1[3], destination_with_ofs[3];
|
||||||
|
|
||||||
|
copy_v3_fl(nav_destination, 0.0f);
|
||||||
|
copy_v3_v3(destination_with_ofs, destination);
|
||||||
|
destination_with_ofs[2] += vertical_ofs;
|
||||||
|
|
||||||
|
wm_xr_basenav_rotation_calc(xr, nav_rotation, nav_rotation);
|
||||||
|
quat_to_mat3(nav_axes, nav_rotation);
|
||||||
|
|
||||||
|
/* Project locations onto navigation axes. */
|
||||||
|
for (int a = 0; a < 3; ++a) {
|
||||||
|
project_v3_v3v3_normalized(projected, nav_location, nav_axes[a]);
|
||||||
|
if (teleport_axes[a]) {
|
||||||
|
/* Interpolate between projected locations. */
|
||||||
|
project_v3_v3v3_normalized(v0, destination_with_ofs, nav_axes[a]);
|
||||||
|
project_v3_v3v3_normalized(v1, viewer_location, nav_axes[a]);
|
||||||
|
sub_v3_v3(v0, v1);
|
||||||
|
madd_v3_v3fl(projected, v0, teleport_t);
|
||||||
|
/* Subtract offset. */
|
||||||
|
project_v3_v3v3_normalized(v0, normal, nav_axes[a]);
|
||||||
|
madd_v3_v3fl(projected, v0, teleport_ofs);
|
||||||
|
}
|
||||||
|
/* Add to final location. */
|
||||||
|
add_v3_v3(nav_destination, projected);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len_v3v3(viewer_location, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wm_xr_navigation_teleport_ground_plane(float points[XR_MAX_RAYCASTS + 1][4],
|
||||||
|
int *num_points,
|
||||||
|
float *ray_dist)
|
||||||
|
{
|
||||||
|
constexpr uint z = 2;
|
||||||
|
for (int i = 1; i < *num_points; ++i) {
|
||||||
|
float *startpoint = points[i - 1], *endpoint = points[i];
|
||||||
|
|
||||||
|
if ((startpoint[z] < 0) == (endpoint[z] < 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startpoint[z] == endpoint[z]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float segment_ray_dist = len_v3v3(startpoint, endpoint);
|
||||||
|
float alpha = startpoint[z] / (startpoint[z] - endpoint[z]);
|
||||||
|
interp_v3_v3v3(endpoint, startpoint, endpoint, alpha);
|
||||||
|
|
||||||
|
*ray_dist = segment_ray_dist * (i - 1) + len_v3v3(startpoint, endpoint);
|
||||||
|
*num_points = i + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XrRaycastResult wm_xr_navigation_teleport(bContext *C,
|
||||||
|
wmXrData *xr,
|
||||||
|
float nav_destination[3],
|
||||||
|
float points[XR_MAX_RAYCASTS + 1][4],
|
||||||
|
const float direction[3],
|
||||||
|
int *num_points,
|
||||||
|
float *ray_dist,
|
||||||
|
float *destination_dist,
|
||||||
|
bool selectable_only,
|
||||||
|
const bool teleport_axes[3],
|
||||||
|
float teleport_t,
|
||||||
|
float teleport_ofs,
|
||||||
|
float gravity,
|
||||||
|
float head_height)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||||
float location[3];
|
|
||||||
float normal[3];
|
|
||||||
int index;
|
int index;
|
||||||
const Object *ob = nullptr;
|
const Object *ob = nullptr;
|
||||||
float obmat[4][4];
|
float obmat[4][4];
|
||||||
|
|
||||||
wm_xr_raycast(scene,
|
float normal[3], segment_direction[3];
|
||||||
depsgraph,
|
float vertical_ofs = 0;
|
||||||
origin,
|
XrRaycastResult result = XR_RAYCAST_MISS;
|
||||||
direction,
|
|
||||||
ray_dist,
|
|
||||||
selectable_only,
|
|
||||||
location,
|
|
||||||
normal,
|
|
||||||
&index,
|
|
||||||
&ob,
|
|
||||||
obmat);
|
|
||||||
|
|
||||||
/* Teleport. */
|
copy_v3_v3(segment_direction, direction);
|
||||||
if (ob) {
|
copy_v3_fl3(normal, 0, 1, 0);
|
||||||
float nav_location[3], nav_rotation[4], viewer_location[3];
|
|
||||||
float nav_axes[3][3], projected[3], v0[3], v1[3];
|
|
||||||
float out[3] = {0.0f, 0.0f, 0.0f};
|
|
||||||
|
|
||||||
WM_xr_session_state_nav_location_get(xr, nav_location);
|
/* When ray_dist == 0 or -1, the raycast is a line of infinite length. */
|
||||||
WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
|
if (*ray_dist <= 0.0f) {
|
||||||
WM_xr_session_state_viewer_pose_location_get(xr, viewer_location);
|
*num_points = 2;
|
||||||
|
}
|
||||||
|
|
||||||
wm_xr_basenav_rotation_calc(xr, nav_rotation, nav_rotation);
|
const float segment_length = *ray_dist / (*num_points - 1);
|
||||||
quat_to_mat3(nav_axes, nav_rotation);
|
float segment_ray_dist = 0.0f;
|
||||||
|
*ray_dist = 0.0f;
|
||||||
|
|
||||||
/* Project locations onto navigation axes. */
|
for (int i = 1; i < *num_points; ++i) {
|
||||||
for (int a = 0; a < 3; ++a) {
|
segment_ray_dist = segment_length;
|
||||||
project_v3_v3v3_normalized(projected, nav_location, nav_axes[a]);
|
wm_xr_raycast(scene,
|
||||||
if (teleport_axes[a]) {
|
depsgraph,
|
||||||
/* Interpolate between projected locations. */
|
points[i - 1],
|
||||||
project_v3_v3v3_normalized(v0, location, nav_axes[a]);
|
segment_direction,
|
||||||
project_v3_v3v3_normalized(v1, viewer_location, nav_axes[a]);
|
&segment_ray_dist,
|
||||||
sub_v3_v3(v0, v1);
|
selectable_only,
|
||||||
madd_v3_v3fl(projected, v0, teleport_t);
|
points[i],
|
||||||
/* Subtract offset. */
|
normal,
|
||||||
project_v3_v3v3_normalized(v0, normal, nav_axes[a]);
|
&index,
|
||||||
madd_v3_v3fl(projected, v0, teleport_ofs);
|
&ob,
|
||||||
|
obmat);
|
||||||
|
|
||||||
|
*ray_dist += segment_ray_dist;
|
||||||
|
|
||||||
|
if (ob) {
|
||||||
|
*num_points = i + 1;
|
||||||
|
|
||||||
|
/** Ensure normal faces the correct direction */
|
||||||
|
if (dot_v3v3(segment_direction, normal) > 0) {
|
||||||
|
mul_v3_fl(normal, -1.0f);
|
||||||
}
|
}
|
||||||
/* Add to final location. */
|
|
||||||
add_v3_v3(out, projected);
|
result = XR_RAYCAST_HIT;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
WM_xr_session_state_nav_location_set(xr, out);
|
madd_v3_v3v3fl(points[i], points[i - 1], segment_direction, segment_length);
|
||||||
|
|
||||||
|
/* Apply gravity */
|
||||||
|
segment_direction[2] -= gravity;
|
||||||
|
normalize_v3(segment_direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fall back to raycast intersecting with the ground plane. */
|
||||||
|
if (result == XR_RAYCAST_MISS) {
|
||||||
|
vertical_ofs = head_height;
|
||||||
|
|
||||||
|
if (wm_xr_navigation_teleport_ground_plane(points, num_points, ray_dist)) {
|
||||||
|
result = XR_RAYCAST_FALLBACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != XR_RAYCAST_MISS) {
|
||||||
|
float origin[3], dummy_dest[3], dummy_normal[3];
|
||||||
|
|
||||||
|
/* Raycast downward to see if we're on the floor */
|
||||||
|
copy_v3_fl3(segment_direction, 0, 0, -1);
|
||||||
|
|
||||||
|
copy_v3_v3(origin, points[*num_points - 1]);
|
||||||
|
madd_v3_v3fl(origin, normal, teleport_ofs);
|
||||||
|
madd_v3_v3fl(origin, segment_direction, -vertical_ofs);
|
||||||
|
|
||||||
|
segment_ray_dist = head_height;
|
||||||
|
ob = nullptr;
|
||||||
|
wm_xr_raycast(scene,
|
||||||
|
depsgraph,
|
||||||
|
origin,
|
||||||
|
segment_direction,
|
||||||
|
&segment_ray_dist,
|
||||||
|
selectable_only,
|
||||||
|
dummy_dest,
|
||||||
|
dummy_normal,
|
||||||
|
&index,
|
||||||
|
&ob,
|
||||||
|
obmat);
|
||||||
|
|
||||||
|
/* Raycast upward to make sure we don't clip through the ceiling */
|
||||||
|
if (ob) {
|
||||||
|
vertical_ofs = head_height - segment_ray_dist;
|
||||||
|
copy_v3_fl3(segment_direction, 0, 0, 1);
|
||||||
|
|
||||||
|
copy_v3_v3(origin, points[*num_points - 1]);
|
||||||
|
madd_v3_v3fl(origin, normal, teleport_ofs);
|
||||||
|
|
||||||
|
segment_ray_dist = vertical_ofs;
|
||||||
|
ob = nullptr;
|
||||||
|
wm_xr_raycast(scene,
|
||||||
|
depsgraph,
|
||||||
|
origin,
|
||||||
|
segment_direction,
|
||||||
|
&segment_ray_dist,
|
||||||
|
selectable_only,
|
||||||
|
dummy_dest,
|
||||||
|
dummy_normal,
|
||||||
|
&index,
|
||||||
|
&ob,
|
||||||
|
obmat);
|
||||||
|
|
||||||
|
if (ob) {
|
||||||
|
vertical_ofs = max_ff(0.0f, segment_ray_dist - teleport_ofs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate teleportation destination in navigation space */
|
||||||
|
*destination_dist = wm_xr_navigation_teleport_pose_calc(xr,
|
||||||
|
nav_destination,
|
||||||
|
points[*num_points - 1],
|
||||||
|
normal,
|
||||||
|
teleport_axes,
|
||||||
|
teleport_t,
|
||||||
|
teleport_ofs,
|
||||||
|
vertical_ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static wmOperatorStatus wm_xr_navigation_teleport_invoke(bContext *C,
|
static wmOperatorStatus wm_xr_navigation_teleport_invoke(bContext *C,
|
||||||
@@ -1328,6 +1611,11 @@ static wmOperatorStatus wm_xr_navigation_teleport_exec(bContext * /*C*/, wmOpera
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm_xr_navigation_teleport_cancel(bContext * /*C*/, wmOperator *op)
|
||||||
|
{
|
||||||
|
wm_xr_raycast_uninit(op);
|
||||||
|
}
|
||||||
|
|
||||||
static wmOperatorStatus wm_xr_navigation_teleport_modal(bContext *C,
|
static wmOperatorStatus wm_xr_navigation_teleport_modal(bContext *C,
|
||||||
wmOperator *op,
|
wmOperator *op,
|
||||||
const wmEvent *event)
|
const wmEvent *event)
|
||||||
@@ -1340,32 +1628,66 @@ static wmOperatorStatus wm_xr_navigation_teleport_modal(bContext *C,
|
|||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
wmXrData *xr = &wm->xr;
|
wmXrData *xr = &wm->xr;
|
||||||
|
|
||||||
|
xr->runtime->session_state.is_raycast_shown = true;
|
||||||
wm_xr_raycast_update(op, xr, actiondata);
|
wm_xr_raycast_update(op, xr, actiondata);
|
||||||
|
|
||||||
|
XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
|
||||||
|
float nav_scale, ray_dist, destination_dist, nav_destination[3];
|
||||||
|
bool teleport_axes[3];
|
||||||
|
|
||||||
|
WM_xr_session_state_nav_scale_get(xr, &nav_scale);
|
||||||
|
|
||||||
|
RNA_boolean_get_array(op->ptr, "teleport_axes", teleport_axes);
|
||||||
|
const float teleport_t = RNA_float_get(op->ptr, "interpolation");
|
||||||
|
const float teleport_ofs = RNA_float_get(op->ptr, "offset") * nav_scale;
|
||||||
|
const float gravity = RNA_float_get(op->ptr, "gravity");
|
||||||
|
const float head_height = xr->runtime->session_state.prev_local_pose.position[1] * nav_scale;
|
||||||
|
const bool selectable_only = RNA_boolean_get(op->ptr, "selectable_only");
|
||||||
|
ray_dist = RNA_float_get(op->ptr, "distance") * nav_scale;
|
||||||
|
|
||||||
|
data->num_points = XR_MAX_RAYCASTS + 1;
|
||||||
|
data->result = wm_xr_navigation_teleport(C,
|
||||||
|
xr,
|
||||||
|
nav_destination,
|
||||||
|
data->points,
|
||||||
|
data->direction,
|
||||||
|
&data->num_points,
|
||||||
|
&ray_dist,
|
||||||
|
&destination_dist,
|
||||||
|
selectable_only,
|
||||||
|
teleport_axes,
|
||||||
|
teleport_t,
|
||||||
|
teleport_ofs,
|
||||||
|
gravity,
|
||||||
|
head_height);
|
||||||
|
|
||||||
|
data->destination_size = RNA_float_get(op->ptr, "destination_scale") *
|
||||||
|
sqrt(destination_dist / nav_scale) * nav_scale;
|
||||||
|
|
||||||
|
switch (data->result) {
|
||||||
|
case XR_RAYCAST_MISS:
|
||||||
|
RNA_float_get_array(op->ptr, "miss_color", data->color);
|
||||||
|
break;
|
||||||
|
case XR_RAYCAST_HIT:
|
||||||
|
RNA_float_get_array(op->ptr, "hit_color", data->color);
|
||||||
|
break;
|
||||||
|
case XR_RAYCAST_FALLBACK:
|
||||||
|
RNA_float_get_array(op->ptr, "fallback_color", data->color);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event->val) {
|
switch (event->val) {
|
||||||
case KM_PRESS:
|
case KM_PRESS:
|
||||||
return OPERATOR_RUNNING_MODAL;
|
return OPERATOR_RUNNING_MODAL;
|
||||||
case KM_RELEASE: {
|
case KM_RELEASE: {
|
||||||
XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
|
if (data->result != XR_RAYCAST_MISS) {
|
||||||
bool selectable_only, teleport_axes[3];
|
WM_xr_session_state_nav_location_set(xr, nav_destination);
|
||||||
float teleport_t, teleport_ofs, ray_dist;
|
}
|
||||||
|
|
||||||
RNA_boolean_get_array(op->ptr, "teleport_axes", teleport_axes);
|
|
||||||
teleport_t = RNA_float_get(op->ptr, "interpolation");
|
|
||||||
teleport_ofs = RNA_float_get(op->ptr, "offset");
|
|
||||||
selectable_only = RNA_boolean_get(op->ptr, "selectable_only");
|
|
||||||
ray_dist = RNA_float_get(op->ptr, "distance");
|
|
||||||
|
|
||||||
wm_xr_navigation_teleport(C,
|
|
||||||
xr,
|
|
||||||
data->origin,
|
|
||||||
data->direction,
|
|
||||||
&ray_dist,
|
|
||||||
selectable_only,
|
|
||||||
teleport_axes,
|
|
||||||
teleport_t,
|
|
||||||
teleport_ofs);
|
|
||||||
|
|
||||||
|
xr->runtime->session_state.is_raycast_shown = false;
|
||||||
wm_xr_raycast_uninit(op);
|
wm_xr_raycast_uninit(op);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
@@ -1388,6 +1710,7 @@ static void WM_OT_xr_navigation_teleport(wmOperatorType *ot)
|
|||||||
/* Callbacks. */
|
/* Callbacks. */
|
||||||
ot->invoke = wm_xr_navigation_teleport_invoke;
|
ot->invoke = wm_xr_navigation_teleport_invoke;
|
||||||
ot->exec = wm_xr_navigation_teleport_exec;
|
ot->exec = wm_xr_navigation_teleport_exec;
|
||||||
|
ot->cancel = wm_xr_navigation_teleport_cancel;
|
||||||
ot->modal = wm_xr_navigation_teleport_modal;
|
ot->modal = wm_xr_navigation_teleport_modal;
|
||||||
ot->poll = wm_xr_operator_sessionactive;
|
ot->poll = wm_xr_operator_sessionactive;
|
||||||
|
|
||||||
@@ -1411,7 +1734,7 @@ static void WM_OT_xr_navigation_teleport(wmOperatorType *ot)
|
|||||||
1.0f);
|
1.0f);
|
||||||
RNA_def_float(ot->srna,
|
RNA_def_float(ot->srna,
|
||||||
"offset",
|
"offset",
|
||||||
0.0f,
|
0.25f,
|
||||||
0.0f,
|
0.0f,
|
||||||
FLT_MAX,
|
FLT_MAX,
|
||||||
"Offset",
|
"Offset",
|
||||||
@@ -1425,13 +1748,49 @@ static void WM_OT_xr_navigation_teleport(wmOperatorType *ot)
|
|||||||
"Only allow selectable objects to influence raycast result");
|
"Only allow selectable objects to influence raycast result");
|
||||||
RNA_def_float(ot->srna,
|
RNA_def_float(ot->srna,
|
||||||
"distance",
|
"distance",
|
||||||
BVH_RAYCAST_DIST_MAX,
|
80.0,
|
||||||
0.0,
|
0.0,
|
||||||
BVH_RAYCAST_DIST_MAX,
|
BVH_RAYCAST_DIST_MAX,
|
||||||
"",
|
"",
|
||||||
"Maximum raycast distance",
|
"Maximum raycast distance",
|
||||||
0.0,
|
0.0,
|
||||||
BVH_RAYCAST_DIST_MAX);
|
BVH_RAYCAST_DIST_MAX);
|
||||||
|
RNA_def_float(ot->srna,
|
||||||
|
"gravity",
|
||||||
|
0.1,
|
||||||
|
0.0,
|
||||||
|
FLT_MAX,
|
||||||
|
"Gravity",
|
||||||
|
"Downward curvature applied to raycast",
|
||||||
|
0.0,
|
||||||
|
FLT_MAX);
|
||||||
|
RNA_def_float(ot->srna,
|
||||||
|
"raycast_scale",
|
||||||
|
0.02f,
|
||||||
|
0.0f,
|
||||||
|
FLT_MAX,
|
||||||
|
"Raycast Scale",
|
||||||
|
"Width of the raycast visualization",
|
||||||
|
0.0f,
|
||||||
|
FLT_MAX);
|
||||||
|
RNA_def_float(ot->srna,
|
||||||
|
"destination_scale",
|
||||||
|
0.05f,
|
||||||
|
0.0f,
|
||||||
|
FLT_MAX,
|
||||||
|
"Destination Scale",
|
||||||
|
"Width of the destination visualization",
|
||||||
|
0.0f,
|
||||||
|
FLT_MAX);
|
||||||
|
RNA_def_int(ot->srna,
|
||||||
|
"sample_count",
|
||||||
|
48,
|
||||||
|
2,
|
||||||
|
INT_MAX,
|
||||||
|
"Sample Count",
|
||||||
|
"Number of interpolation samples for the raycast visualization",
|
||||||
|
2,
|
||||||
|
INT_MAX);
|
||||||
RNA_def_boolean(
|
RNA_def_boolean(
|
||||||
ot->srna, "from_viewer", false, "From Viewer", "Use viewer pose as raycast origin");
|
ot->srna, "from_viewer", false, "From Viewer", "Use viewer pose as raycast origin");
|
||||||
RNA_def_float_vector(ot->srna,
|
RNA_def_float_vector(ot->srna,
|
||||||
@@ -1445,13 +1804,33 @@ static void WM_OT_xr_navigation_teleport(wmOperatorType *ot)
|
|||||||
-1.0f,
|
-1.0f,
|
||||||
1.0f);
|
1.0f);
|
||||||
RNA_def_float_color(ot->srna,
|
RNA_def_float_color(ot->srna,
|
||||||
"color",
|
"hit_color",
|
||||||
4,
|
4,
|
||||||
g_xr_default_raycast_color,
|
g_xr_default_raycast_hit_color,
|
||||||
0.0f,
|
0.0f,
|
||||||
1.0f,
|
1.0f,
|
||||||
"Color",
|
"Hit Color",
|
||||||
"Raycast color",
|
"Color of raycast when it succeeds",
|
||||||
|
0.0f,
|
||||||
|
1.0f);
|
||||||
|
RNA_def_float_color(ot->srna,
|
||||||
|
"miss_color",
|
||||||
|
4,
|
||||||
|
g_xr_default_raycast_miss_color,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
"Miss Color",
|
||||||
|
"Color of raycast when it misses",
|
||||||
|
0.0f,
|
||||||
|
1.0f);
|
||||||
|
RNA_def_float_color(ot->srna,
|
||||||
|
"fallback_color",
|
||||||
|
4,
|
||||||
|
g_xr_default_raycast_fallback_color,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
"Fallback Color",
|
||||||
|
"Color of raycast when a fallback case succeeds",
|
||||||
0.0f,
|
0.0f,
|
||||||
1.0f);
|
1.0f);
|
||||||
}
|
}
|
||||||
@@ -1547,6 +1926,74 @@ static void WM_OT_xr_navigation_reset(wmOperatorType *ot)
|
|||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name XR Navigation Swap Hands
|
||||||
|
*
|
||||||
|
* Resets XR navigation deltas relative to session base pose.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
static wmOperatorStatus wm_xr_navigation_swap_hands_invoke(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const wmEvent *event)
|
||||||
|
{
|
||||||
|
if (!wm_xr_operator_test_event(op, event)) {
|
||||||
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
WM_event_add_modal_handler(C, op);
|
||||||
|
|
||||||
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
|
wmXrData *xr = &wm->xr;
|
||||||
|
|
||||||
|
xr->runtime->session_state.swap_hands = true;
|
||||||
|
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wmOperatorStatus wm_xr_navigation_swap_hands_exec(bContext * /*C*/, wmOperator * /*op*/)
|
||||||
|
{
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wmOperatorStatus wm_xr_navigation_swap_hands_modal(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const wmEvent *event)
|
||||||
|
{
|
||||||
|
if (!wm_xr_operator_test_event(op, event)) {
|
||||||
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
|
wmXrData *xr = &wm->xr;
|
||||||
|
|
||||||
|
switch (event->val) {
|
||||||
|
case KM_PRESS:
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
case KM_RELEASE:
|
||||||
|
xr->runtime->session_state.swap_hands = false;
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WM_OT_xr_navigation_swap_hands(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* Identifiers. */
|
||||||
|
ot->name = "XR Navigation Swap Hands";
|
||||||
|
ot->idname = "WM_OT_xr_navigation_swap_hands";
|
||||||
|
ot->description = "Swap VR navigation controls between left / right controllers";
|
||||||
|
|
||||||
|
/* Callbacks. */
|
||||||
|
ot->invoke = wm_xr_navigation_swap_hands_invoke;
|
||||||
|
ot->exec = wm_xr_navigation_swap_hands_exec;
|
||||||
|
ot->modal = wm_xr_navigation_swap_hands_modal;
|
||||||
|
ot->poll = wm_xr_operator_sessionactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Operator Registration
|
/** \name Operator Registration
|
||||||
* \{ */
|
* \{ */
|
||||||
@@ -1558,6 +2005,7 @@ void wm_xr_operatortypes_register()
|
|||||||
WM_operatortype_append(WM_OT_xr_navigation_fly);
|
WM_operatortype_append(WM_OT_xr_navigation_fly);
|
||||||
WM_operatortype_append(WM_OT_xr_navigation_teleport);
|
WM_operatortype_append(WM_OT_xr_navigation_teleport);
|
||||||
WM_operatortype_append(WM_OT_xr_navigation_reset);
|
WM_operatortype_append(WM_OT_xr_navigation_reset);
|
||||||
|
WM_operatortype_append(WM_OT_xr_navigation_swap_hands);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ static void wm_xr_session_create_cb()
|
|||||||
settings->base_scale = 1.0f;
|
settings->base_scale = 1.0f;
|
||||||
}
|
}
|
||||||
state->prev_base_scale = settings->base_scale;
|
state->prev_base_scale = settings->base_scale;
|
||||||
|
|
||||||
|
/* Initialize vignette. */
|
||||||
|
state->vignette_data = MEM_callocN<wmXrVignetteData>(__func__);
|
||||||
|
WM_xr_session_state_vignette_reset(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm_xr_session_controller_data_free(wmXrSessionState *state)
|
static void wm_xr_session_controller_data_free(wmXrSessionState *state)
|
||||||
@@ -84,9 +88,27 @@ static void wm_xr_session_controller_data_free(wmXrSessionState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm_xr_session_vignette_data_free(wmXrSessionState *state)
|
||||||
|
{
|
||||||
|
if (state->vignette_data) {
|
||||||
|
MEM_freeN(state->vignette_data);
|
||||||
|
state->vignette_data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_xr_session_raycast_model_free(wmXrSessionState *state)
|
||||||
|
{
|
||||||
|
if (state->raycast_model) {
|
||||||
|
GPU_batch_discard(state->raycast_model);
|
||||||
|
state->raycast_model = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wm_xr_session_data_free(wmXrSessionState *state)
|
void wm_xr_session_data_free(wmXrSessionState *state)
|
||||||
{
|
{
|
||||||
wm_xr_session_controller_data_free(state);
|
wm_xr_session_controller_data_free(state);
|
||||||
|
wm_xr_session_vignette_data_free(state);
|
||||||
|
wm_xr_session_raycast_model_free(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm_xr_session_exit_cb(void *customdata)
|
static void wm_xr_session_exit_cb(void *customdata)
|
||||||
@@ -384,6 +406,8 @@ void wm_xr_session_state_update(const XrSessionSettings *settings,
|
|||||||
state->is_view_data_set = true;
|
state->is_view_data_set = true;
|
||||||
/* Assume this was already done through wm_xr_session_draw_data_update(). */
|
/* Assume this was already done through wm_xr_session_draw_data_update(). */
|
||||||
state->force_reset_to_base_pose = false;
|
state->force_reset_to_base_pose = false;
|
||||||
|
|
||||||
|
WM_xr_session_state_vignette_update(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr)
|
wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr)
|
||||||
@@ -572,6 +596,52 @@ void WM_xr_session_state_navigation_reset(wmXrSessionState *state)
|
|||||||
unit_qt(state->nav_pose.orientation_quat);
|
unit_qt(state->nav_pose.orientation_quat);
|
||||||
state->nav_scale = 1.0f;
|
state->nav_scale = 1.0f;
|
||||||
state->is_navigation_dirty = true;
|
state->is_navigation_dirty = true;
|
||||||
|
state->swap_hands = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_xr_session_state_vignette_reset(wmXrSessionState *state)
|
||||||
|
{
|
||||||
|
wmXrVignetteData *data = state->vignette_data;
|
||||||
|
|
||||||
|
/* Reset vignette state */
|
||||||
|
data->aperture = 1.0f;
|
||||||
|
data->aperture_velocity = 0.0f;
|
||||||
|
|
||||||
|
/* Set default vignette parameters */
|
||||||
|
data->initial_aperture = 0.25f;
|
||||||
|
data->initial_aperture_velocity = -0.03f;
|
||||||
|
|
||||||
|
data->aperture_min = 0.08f;
|
||||||
|
data->aperture_max = 0.3f;
|
||||||
|
|
||||||
|
data->aperture_velocity_max = 0.002f;
|
||||||
|
data->aperture_velocity_delta = 0.01f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_xr_session_state_vignette_activate(wmXrData *xr)
|
||||||
|
{
|
||||||
|
if (WM_xr_session_exists(xr)) {
|
||||||
|
wmXrVignetteData *data = xr->runtime->session_state.vignette_data;
|
||||||
|
data->aperture_velocity = data->initial_aperture_velocity;
|
||||||
|
data->aperture = min_ff(data->aperture, data->initial_aperture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_xr_session_state_vignette_update(wmXrSessionState *state)
|
||||||
|
{
|
||||||
|
wmXrVignetteData *data = state->vignette_data;
|
||||||
|
|
||||||
|
const float vignette_intensity = U.xr_navigation.vignette_intensity;
|
||||||
|
const float aperture_min = interpf(
|
||||||
|
data->aperture_min, data->aperture_max, vignette_intensity * 0.01f);
|
||||||
|
data->aperture_velocity = min_ff(data->aperture_velocity_max,
|
||||||
|
data->aperture_velocity + data->aperture_velocity_delta);
|
||||||
|
|
||||||
|
if (data->aperture == aperture_min) {
|
||||||
|
data->aperture_velocity = data->aperture_velocity_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->aperture = clamp_f(data->aperture + data->aperture_velocity, aperture_min, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|||||||
Reference in New Issue
Block a user