mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 16:00:26 +02:00
VR arms 3a.6: vr.body (arms, hands, off) and vr.fingers in the VR options
- vr.body = "arms" (default): arms and hands as before; "hands": the arms' bones shrunk to a point 3.5 cm behind each wrist along the hand's line so the cuff closes behind the hand (vr_hide_arm, after HaloCE-Quest-VR's vr_hide_forearms, CC0), no arm IK solved; "off": the hands model is not drawn (one model draw less an eye) and nothing of the arms posed; the weapon, its aim with both hands, barrel, laser and crosshair stay. - vr.c reads vr.body with the live settings (halo_vr_body_mode). - The VR options panel gets "Body" (Arms and hands / Hands only / Weapon only) and "Fingers" (Tracked / Off) rows; its twelve rows are 22 pixels apart (were 26) so the panel keeps its box. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
98e848de39
commit
6d2dcfaaec
7 files changed
+159
-5
No files matched your search
@@ -749,4 +749,68 @@ void vr_straighten_finger(
|
||||
vr_turn_subtree(skeleton, matrices, joints[1], rotation);
|
||||
}
|
||||
|
||||
/* ---------- hands alone (vr.body "hands")
|
||||
|
||||
The arm's bones (not the hand's, its fingers' or the weapon's) shrunk to
|
||||
nothing at a point 3.5 cm back from the wrist along the hand's line,
|
||||
knuckles to wrist: the cuff closes just behind the hand. Shrunk onto their
|
||||
own places, the forearm drew the wrist's skin to the elbow and the hand
|
||||
looked cut off (after HaloCE-Quest-VR, CC0, its vr_hide_forearms and
|
||||
vr_hand_back_axis). */
|
||||
void vr_hide_arm(
|
||||
struct vr_skeleton const *skeleton,
|
||||
real_matrix4x3 *matrices,
|
||||
short const bones[NUMBER_OF_VR_ARM_BONES],
|
||||
short const fingers[5][3],
|
||||
short gun)
|
||||
{
|
||||
real_point3d centre = matrices[bones[_vr_arm_hand]].position;
|
||||
real_point3d knuckles;
|
||||
real_vector3d back;
|
||||
boolean along = FALSE;
|
||||
short finger, node_index, found = 0;
|
||||
|
||||
knuckles.x = knuckles.y = knuckles.z = 0.0f;
|
||||
/* (the four fingers' bases: the thumb's sits off the line) */
|
||||
for (finger = 1; finger < 5; finger++)
|
||||
{
|
||||
if (fingers[finger][0] == NONE)
|
||||
continue;
|
||||
knuckles.x += matrices[fingers[finger][0]].position.x;
|
||||
knuckles.y += matrices[fingers[finger][0]].position.y;
|
||||
knuckles.z += matrices[fingers[finger][0]].position.z;
|
||||
found++;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
knuckles.x /= found;
|
||||
knuckles.y /= found;
|
||||
knuckles.z /= found;
|
||||
vr_point_minus(¢re, &knuckles, &back);
|
||||
along = vr_unit_vector(&back);
|
||||
}
|
||||
if (!along)
|
||||
{
|
||||
vr_point_minus(&matrices[bones[_vr_arm_fore]].position, ¢re, &back);
|
||||
along = vr_unit_vector(&back);
|
||||
}
|
||||
if (along)
|
||||
{
|
||||
centre.x += back.i * 0.035f * VR_UNITS_PER_METRE;
|
||||
centre.y += back.j * 0.035f * VR_UNITS_PER_METRE;
|
||||
centre.z += back.k * 0.035f * VR_UNITS_PER_METRE;
|
||||
}
|
||||
for (node_index = 0; node_index < skeleton->node_count; node_index++)
|
||||
{
|
||||
if (!vr_skeleton_under(skeleton, node_index, bones[_vr_arm_upper]) ||
|
||||
vr_skeleton_under(skeleton, node_index, bones[_vr_arm_hand]) ||
|
||||
(gun != NONE && vr_skeleton_under(skeleton, node_index, gun)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
matrices[node_index].scale = 0.0f;
|
||||
matrices[node_index].position = centre;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -71,6 +71,11 @@ joint */
|
||||
void vr_straighten_finger(struct vr_skeleton const *skeleton, real_matrix4x3 *matrices, short const joints[3],
|
||||
real amount);
|
||||
|
||||
/* the arm's bones shrunk to nothing just behind the wrist, the hand (with
|
||||
its fingers) and the weapon left: the hand alone */
|
||||
void vr_hide_arm(struct vr_skeleton const *skeleton, real_matrix4x3 *matrices,
|
||||
short const bones[NUMBER_OF_VR_ARM_BONES], short const fingers[5][3], short gun);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -141,6 +141,15 @@ int halo_vr_finger_curls(short local_player_index, int hand, float curls[4]);
|
||||
which the arms' bending is eased */
|
||||
int halo_vr_free_arm_bends(void);
|
||||
double halo_vr_pose_time(void);
|
||||
/* - what of the body is drawn (vr.body): the arms and hands, the hands
|
||||
alone, or neither (the weapon alone) */
|
||||
enum
|
||||
{
|
||||
HALO_VR_BODY_ARMS = 0,
|
||||
HALO_VR_BODY_HANDS,
|
||||
HALO_VR_BODY_OFF,
|
||||
};
|
||||
int halo_vr_body_mode(void);
|
||||
/* a hand has just been thrust forward: a melee attack (xinput_sdl.c) */
|
||||
int halo_vr_melee(void);
|
||||
/* the weight of the melee attack under way, from the swing's speed (0..1;
|
||||
|
||||
@@ -198,6 +198,10 @@ static const struct config_setting config_settings[] =
|
||||
{ "vr.two_hand_reach", _config_real, "0.2", "HALO_VR_TWO_HAND_REACH", _environment_value, _platform_android,
|
||||
"How near, in metres, the left hand must be to the weapon's foregrip for\n"
|
||||
"its grip button to take hold of it with both hands." },
|
||||
{ "vr.body", _config_string, "\"arms\"", "HALO_VR_BODY", _environment_value, _platform_android,
|
||||
"What of your body is drawn with the weapon: \"arms\", the arms and hands\n"
|
||||
"reaching from the shoulders to the controllers; \"hands\", the hands\n"
|
||||
"alone; \"off\", neither (the weapon alone)." },
|
||||
{ "vr.fingers", _config_boolean, "true", "HALO_VR_FINGERS", _environment_value, _platform_android,
|
||||
"The free hand's fingers follow the controller: the index finger the\n"
|
||||
"trigger, the others the grip, the thumb where it rests (on the Quest's\n"
|
||||
|
||||
@@ -235,6 +235,7 @@ static struct
|
||||
middle and the last two, curled 0 (open) to 1, and how fast */
|
||||
int fingers;
|
||||
int arm_ik; /* vr.arm_ik: the free arm bends at the elbow */
|
||||
int body_mode; /* vr.body: HALO_VR_BODY_* */
|
||||
float finger_curl[HALO_XR_HAND_COUNT][4];
|
||||
float finger_velocity[HALO_XR_HAND_COUNT][4];
|
||||
unsigned long long fingers_last_us;
|
||||
@@ -469,6 +470,12 @@ static void vr_read_live_settings(void)
|
||||
vr.comfort_vignette = (float)config_real("vr.comfort_vignette");
|
||||
vr.fingers = config_boolean("vr.fingers");
|
||||
vr.arm_ik = config_boolean("vr.arm_ik");
|
||||
{
|
||||
const char *body = config_string("vr.body");
|
||||
|
||||
vr.body_mode = !strcmp(body, "hands") ? HALO_VR_BODY_HANDS :
|
||||
!strcmp(body, "off") ? HALO_VR_BODY_OFF : HALO_VR_BODY_ARMS;
|
||||
}
|
||||
}
|
||||
|
||||
void halo_vr_initialize(void)
|
||||
@@ -1053,6 +1060,11 @@ int halo_vr_free_arm_bends(void)
|
||||
return vr.active && vr.arm_ik;
|
||||
}
|
||||
|
||||
int halo_vr_body_mode(void)
|
||||
{
|
||||
return vr.active ? vr.body_mode : HALO_VR_BODY_ARMS;
|
||||
}
|
||||
|
||||
double halo_vr_pose_time(void)
|
||||
{
|
||||
return (double)vr.frame_start_us * 1e-6;
|
||||
@@ -2840,6 +2852,7 @@ int halo_vr_finger_curls(short local_player_index, int hand, float curls[4])
|
||||
return 0;
|
||||
}
|
||||
int halo_vr_free_arm_bends(void) { return 0; }
|
||||
int halo_vr_body_mode(void) { return HALO_VR_BODY_ARMS; }
|
||||
double halo_vr_pose_time(void) { return 0.0; }
|
||||
void halo_vr_set_seat(short local_player_index, int seat, int armed, float vehicle_yaw)
|
||||
{
|
||||
|
||||
@@ -668,6 +668,10 @@ void first_person_weapon_draw(
|
||||
if (log_skin)
|
||||
model_vr_log_skin(first_person_interface->hands.index);
|
||||
}
|
||||
#endif
|
||||
#ifdef HALO_ANDROID
|
||||
/* VR: the weapon alone (vr.body "off") */
|
||||
if (halo_vr_body_mode()!=HALO_VR_BODY_OFF)
|
||||
#endif
|
||||
render_model(
|
||||
first_person_interface->hands.index,
|
||||
@@ -1571,6 +1575,7 @@ static void first_person_weapon_vr_arms(
|
||||
boolean gripping;
|
||||
boolean left_free;
|
||||
boolean rigid = !halo_vr_free_arm_bends();
|
||||
int body = halo_vr_body_mode();
|
||||
float hand_position[3], hand_forward[3], hand_up[3];
|
||||
|
||||
if (vr_arm_nodes.graph_index != graph_index)
|
||||
@@ -1692,6 +1697,9 @@ static void first_person_weapon_vr_arms(
|
||||
reference[2] = dot_product3d(&between, &weapon_camera->up);
|
||||
gripping = halo_vr_two_hand(local_player_index, foregrip, reference);
|
||||
}
|
||||
/* (the weapon alone: no hands to pose) */
|
||||
if (body == HALO_VR_BODY_OFF)
|
||||
return;
|
||||
if (!gripping && vr_arm_nodes.wrist[0] != NONE)
|
||||
{
|
||||
if (halo_vr_left_hand(local_player_index, hand_position, hand_forward, hand_up))
|
||||
@@ -1723,6 +1731,12 @@ static void first_person_weapon_vr_arms(
|
||||
pole.k = -global_up3d->k;
|
||||
vr_vector_scale_add(&pole, &left, outward * 0.6f);
|
||||
vr_vector_scale_add(&pole, &forward, -0.3f);
|
||||
bones[_vr_arm_upper] = vr_arm_nodes.upper[side];
|
||||
bones[_vr_arm_fore] = vr_arm_nodes.fore[side];
|
||||
bones[_vr_arm_hand] = vr_arm_nodes.wrist[side];
|
||||
/* (the hands alone: the arms are shrunk away below) */
|
||||
if (body == HALO_VR_BODY_HANDS)
|
||||
continue;
|
||||
if (!side && left_free && rigid)
|
||||
{
|
||||
/* the free left arm keeps its shape (vr_left_hand_free), but
|
||||
@@ -1732,15 +1746,25 @@ static void first_person_weapon_vr_arms(
|
||||
}
|
||||
/* the hand stays where it is (at the controller, or on the
|
||||
weapon): the arm bends to it */
|
||||
bones[_vr_arm_upper] = vr_arm_nodes.upper[side];
|
||||
bones[_vr_arm_fore] = vr_arm_nodes.fore[side];
|
||||
bones[_vr_arm_hand] = vr_arm_nodes.wrist[side];
|
||||
vr_solve_arm(&vr_arm_skeleton, node_matrices, bones, shoulder, &node_matrices[bones[_vr_arm_hand]].position,
|
||||
&pole, TRUE, &vr_arm_history[side]);
|
||||
vr_distribute_arm_twist(node_matrices, bones, &animated_forearm[side], &animated_wrist[side],
|
||||
&vr_arm_history[side]);
|
||||
}
|
||||
first_person_weapon_vr_fingers(local_player_index, node_matrices, left_free, hand_forward, hand_up);
|
||||
if (body == HALO_VR_BODY_HANDS)
|
||||
{
|
||||
for (side = 0; side < 2; side++)
|
||||
{
|
||||
short bones[NUMBER_OF_VR_ARM_BONES];
|
||||
|
||||
bones[_vr_arm_upper] = vr_arm_nodes.upper[side];
|
||||
bones[_vr_arm_fore] = vr_arm_nodes.fore[side];
|
||||
bones[_vr_arm_hand] = vr_arm_nodes.wrist[side];
|
||||
if (bones[_vr_arm_upper] != NONE && bones[_vr_arm_fore] != NONE && bones[_vr_arm_hand] != NONE)
|
||||
vr_hide_arm(&vr_arm_skeleton, node_matrices, bones, vr_arm_nodes.fingers[side], vr_arm_nodes.gun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6645,6 +6645,7 @@ they change), and from it a page of what the controllers' buttons do. */
|
||||
|
||||
int config_boolean(char const *name);
|
||||
double config_real(char const *name);
|
||||
char const *config_string(char const *name);
|
||||
int config_write(char const *name, char const *value);
|
||||
int config_write_boolean(char const *name, int value);
|
||||
|
||||
@@ -6658,12 +6659,15 @@ enum
|
||||
_vr_option_laser,
|
||||
_vr_option_crosshair,
|
||||
_vr_option_motion_tracker,
|
||||
_vr_option_body,
|
||||
_vr_option_fingers,
|
||||
_vr_option_controls,
|
||||
_vr_option_quit,
|
||||
NUMBER_OF_VR_OPTIONS,
|
||||
|
||||
VR_OPTIONS_TOP = 98,
|
||||
VR_OPTIONS_ROW_HEIGHT = 26,
|
||||
/* (twelve rows between the title and the footer, in the box) */
|
||||
VR_OPTIONS_TOP = 94,
|
||||
VR_OPTIONS_ROW_HEIGHT = 22,
|
||||
VR_OPTIONS_FOOTER = 362,
|
||||
|
||||
_vr_controls_on_foot = 0,
|
||||
@@ -6688,6 +6692,23 @@ static real const vr_snap_angles[] = { 30.0f, 45.0f, 60.0f, 90.0f };
|
||||
static real const vr_smooth_speeds[] = { 60.0f, 90.0f, 120.0f, 150.0f, 180.0f };
|
||||
static real const vr_vignettes[] = { 0.0f, 0.35f, 0.7f, 1.0f };
|
||||
static char const *const vr_vignette_names[] = { "Off", "Light", "Medium", "Strong" };
|
||||
/* vr.body's values, and as the panel shows them */
|
||||
static char const *const vr_bodies[] = { "arms", "hands", "off" };
|
||||
static char const *const vr_body_names[] = { "Arms and hands", "Hands only", "Weapon only" };
|
||||
|
||||
static short ui_vr_options_body(
|
||||
void)
|
||||
{
|
||||
char const *body = config_string("vr.body");
|
||||
short index;
|
||||
|
||||
for (index = 0; index < (short)NUMBEROF(vr_bodies); index++)
|
||||
{
|
||||
if (body && strcmp(body, vr_bodies[index]) == 0)
|
||||
return index;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static boolean ui_vr_options_screen(
|
||||
void)
|
||||
@@ -6753,6 +6774,11 @@ static void ui_vr_options_change(
|
||||
case _vr_option_motion_tracker:
|
||||
config_write_boolean("vr.motion_tracker_on_wrist", !config_boolean("vr.motion_tracker_on_wrist"));
|
||||
break;
|
||||
case _vr_option_body:
|
||||
config_write("vr.body", vr_bodies[(ui_vr_options_body() + change + (short)NUMBEROF(vr_bodies)) %
|
||||
(short)NUMBEROF(vr_bodies)]);
|
||||
break;
|
||||
case _vr_option_fingers: config_write_boolean("vr.fingers", !config_boolean("vr.fingers")); break;
|
||||
case _vr_option_controls:
|
||||
ui_vr_options_globals.controls = TRUE;
|
||||
ui_vr_options_globals.page = _vr_controls_on_foot;
|
||||
@@ -7179,6 +7205,15 @@ static void ui_vr_options_render(
|
||||
label = "Motion tracker";
|
||||
snprintf(value, sizeof(value), "%s", config_boolean("vr.motion_tracker_on_wrist") ? "On the wrist" : "In the HUD");
|
||||
break;
|
||||
case _vr_option_body:
|
||||
label = "Body";
|
||||
snprintf(value, sizeof(value), "%s", vr_body_names[ui_vr_options_body()]);
|
||||
break;
|
||||
case _vr_option_fingers:
|
||||
label = "Fingers";
|
||||
snprintf(value, sizeof(value), "%s", config_boolean("vr.fingers") ? "Tracked" : "Off");
|
||||
unused = ui_vr_options_body() == 2;
|
||||
break;
|
||||
case _vr_option_controls:
|
||||
label = "Controller buttons...";
|
||||
break;
|
||||
|
||||
Reference in new issue
Block a user