mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 16:00:26 +02:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
770f8881e0 | ||
|
|
38ab192749 | ||
|
|
6299503191 | ||
|
|
7242151017 | ||
|
|
4b8f8dde8b |
No files matched your search
@@ -794,6 +794,12 @@ the eyes reads it. Shown only while it is. */
|
||||
|
||||
#define WRIST_IMAGE_SIZE 512
|
||||
#define CROSSHAIR_IMAGE_SIZE 256
|
||||
/* the names layer: HALO_XR_MAXIMUM_NAMES slots of 4:1, one over another */
|
||||
#define NAMES_IMAGE_WIDTH 512
|
||||
#define NAMES_IMAGE_HEIGHT (NAMES_IMAGE_WIDTH / 4 * HALO_XR_MAXIMUM_NAMES)
|
||||
/* a name's slot, as the game draws it: wider than its image's 4:1 (the
|
||||
game's 640x480 drawn square): the height a slot shows at, to its width */
|
||||
#define NAME_SLOT_ASPECT (30.0f / 160.0f)
|
||||
#define WRIST_BEHIND_PALM 0.05f
|
||||
#define WRIST_DOWN_HANDLE 0.02f
|
||||
#define WRIST_ABOVE_HAND 0.04f
|
||||
@@ -1032,8 +1038,15 @@ int host_xr_initialize(struct halo_xr_info *info, float wanted_refresh_rate)
|
||||
{
|
||||
int size = layer == HALO_XR_LAYER_WRIST || layer == HALO_XR_LAYER_SCOPE ? WRIST_IMAGE_SIZE :
|
||||
layer == HALO_XR_LAYER_CROSSHAIR ? CROSSHAIR_IMAGE_SIZE : 0;
|
||||
int width = size ? size : xr.eye_width;
|
||||
int height = size ? size : xr.eye_height;
|
||||
|
||||
if (!swapchain_create(&xr.swapchains[layer], size ? size : xr.eye_width, size ? size : xr.eye_height))
|
||||
if (layer == HALO_XR_LAYER_NAMES)
|
||||
{
|
||||
width = NAMES_IMAGE_WIDTH;
|
||||
height = NAMES_IMAGE_HEIGHT;
|
||||
}
|
||||
if (!swapchain_create(&xr.swapchains[layer], width, height))
|
||||
return 0;
|
||||
}
|
||||
if (!copy_initialize() || !actions_initialize())
|
||||
@@ -1354,7 +1367,8 @@ int host_xr_end_frame(const struct halo_xr_submit *submit)
|
||||
XrCompositionLayerQuad wrist = { XR_TYPE_COMPOSITION_LAYER_QUAD };
|
||||
XrCompositionLayerQuad scope = { XR_TYPE_COMPOSITION_LAYER_QUAD };
|
||||
XrCompositionLayerQuad crosshair = { XR_TYPE_COMPOSITION_LAYER_QUAD };
|
||||
const XrCompositionLayerBaseHeader *layers[5];
|
||||
XrCompositionLayerQuad names[HALO_XR_MAXIMUM_NAMES];
|
||||
const XrCompositionLayerBaseHeader *layers[5 + HALO_XR_MAXIMUM_NAMES];
|
||||
uint32_t layer_count = 0;
|
||||
int eye;
|
||||
|
||||
@@ -1458,6 +1472,34 @@ int host_xr_end_frame(const struct halo_xr_submit *submit)
|
||||
layers[layer_count++] = (const XrCompositionLayerBaseHeader *)&crosshair;
|
||||
}
|
||||
|
||||
if (xr.frame_state.shouldRender && submit->name_count > 0 && xr.swapchains[HALO_XR_LAYER_NAMES].filled)
|
||||
{
|
||||
struct xr_swapchain *swapchain = &xr.swapchains[HALO_XR_LAYER_NAMES];
|
||||
int slot_height = swapchain->height / HALO_XR_MAXIMUM_NAMES;
|
||||
int name;
|
||||
|
||||
for (name = 0; name < submit->name_count && name < HALO_XR_MAXIMUM_NAMES; name++)
|
||||
{
|
||||
XrCompositionLayerQuad *quad_name = &names[name];
|
||||
|
||||
memset(quad_name, 0, sizeof(*quad_name));
|
||||
quad_name->type = XR_TYPE_COMPOSITION_LAYER_QUAD;
|
||||
quad_name->layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
quad_name->space = xr.local_space;
|
||||
quad_name->eyeVisibility = XR_EYE_VISIBILITY_BOTH;
|
||||
quad_name->subImage.swapchain = swapchain->handle;
|
||||
/* (slot 0 at the image's top: GL's rows run bottom up) */
|
||||
quad_name->subImage.imageRect.offset.x = 0;
|
||||
quad_name->subImage.imageRect.offset.y = swapchain->height - (name + 1) * slot_height;
|
||||
quad_name->subImage.imageRect.extent.width = swapchain->width;
|
||||
quad_name->subImage.imageRect.extent.height = slot_height;
|
||||
quad_name->size.width = submit->name_widths[name];
|
||||
quad_name->size.height = submit->name_widths[name] * NAME_SLOT_ASPECT;
|
||||
pose_to_xr(&quad_name->pose, &submit->name_poses[name]);
|
||||
layers[layer_count++] = (const XrCompositionLayerBaseHeader *)quad_name;
|
||||
}
|
||||
}
|
||||
|
||||
end.displayTime = xr.frame_state.predictedDisplayTime;
|
||||
end.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
|
||||
end.layerCount = layer_count;
|
||||
|
||||
@@ -27,7 +27,10 @@ enum
|
||||
HALO_XR_LAYER_WRIST = 3, /* the motion tracker, on the left wrist */
|
||||
HALO_XR_LAYER_SCOPE = 4, /* the zoomed view, a disc over the weapon */
|
||||
HALO_XR_LAYER_CROSSHAIR = 5, /* the weapon's crosshair, where it aims */
|
||||
HALO_XR_LAYER_COUNT = 6,
|
||||
HALO_XR_LAYER_NAMES = 6, /* players' names, each a quad over a head */
|
||||
HALO_XR_LAYER_COUNT = 7,
|
||||
/* the names layer's slots, one a name, stacked from its top */
|
||||
HALO_XR_MAXIMUM_NAMES = 8,
|
||||
|
||||
/* host_xr_copy_layer's clear_alpha: the source's alpha kept, made
|
||||
opaque, or cut to a disc (premultiplied) */
|
||||
@@ -147,6 +150,12 @@ struct halo_xr_submit
|
||||
int crosshair;
|
||||
float crosshair_size;
|
||||
struct halo_xr_pose crosshair_pose;
|
||||
/* the names layer was filled: its first name_count slots, each shown
|
||||
this wide (metres, a slot's height following from its shape), here in
|
||||
LOCAL space, facing the eyes */
|
||||
int name_count;
|
||||
float name_widths[HALO_XR_MAXIMUM_NAMES];
|
||||
struct halo_xr_pose name_poses[HALO_XR_MAXIMUM_NAMES];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -140,6 +140,15 @@ out (halo_vr_scope_pass). */
|
||||
int halo_vr_scope(short local_player_index, float magnification, float position[3], float forward[3], float up[3],
|
||||
float *vertical_field_of_view);
|
||||
int halo_vr_scope_pass(void);
|
||||
/* Players' names over their heads (hud.c, render.c): whether they are drawn
|
||||
apart this frame; the slot a name is drawn into (left, top, right, bottom
|
||||
of the game's 640x480); a name's place (world units, over the head),
|
||||
giving its slot (-1: no more); and the slots, drawn on the cleared back
|
||||
buffer, taken (it is cleared again) */
|
||||
int halo_vr_names_apart(void);
|
||||
void halo_vr_name_slot(int slot, short bounds[4]);
|
||||
int halo_vr_add_name(const float point[3]);
|
||||
void halo_vr_capture_names(void);
|
||||
/* how much higher than a rifle's the weapon in hand has its scope's disc
|
||||
(metres; render.c, before halo_vr_scope) */
|
||||
void halo_vr_set_scope_raise(float metres);
|
||||
@@ -181,6 +190,11 @@ enum
|
||||
};
|
||||
void halo_vr_set_seat(short local_player_index, int seat, int armed, float vehicle_yaw);
|
||||
void halo_vr_set_seat_frame(short local_player_index, float vehicle_yaw);
|
||||
/* At an open vehicle's wheel (a Warthog's), each frame (render.c): the
|
||||
driver's hands on it as drawn (world units, from the game's camera), or
|
||||
NULL; the player's own hands turn it. And whether they hold it. */
|
||||
void halo_vr_set_wheel(short local_player_index, const float left[3], const float right[3]);
|
||||
int halo_vr_wheel_held(void);
|
||||
/* whether a seated player's view stays in first person (director.c) */
|
||||
int halo_vr_vehicle_first_person(void);
|
||||
/* VR test aid (debug.vehicle_spawn): both sticks held in for a moment asks
|
||||
|
||||
@@ -221,6 +221,13 @@ static const struct config_setting config_settings[] =
|
||||
{ "vr.vehicle_pitch_degrees", _config_real, "45", "HALO_VR_VEHICLE_PITCH", _environment_value, _platform_android,
|
||||
"Driving, the right stick pushed fully up or down aims this many degrees\n"
|
||||
"above or below the horizon (a Banshee climbs or dives)." },
|
||||
{ "vr.vehicle_wheel", _config_boolean, "true", "HALO_VR_VEHICLE_WHEEL", _environment_value, _platform_android,
|
||||
"At an open vehicle's wheel (a Warthog's), grip it with one hand or both and\n"
|
||||
"turn it to steer, the right trigger the throttle and the left the brake;\n"
|
||||
"let go, and the right stick steers." },
|
||||
{ "vr.vehicle_wheel_degrees", _config_real, "90", "HALO_VR_VEHICLE_WHEEL_DEGREES", _environment_value,
|
||||
_platform_android,
|
||||
"The wheel turned this many degrees either way steers fully." },
|
||||
{ "vr.comfort_vignette", _config_real, "0.7", "HALO_VR_COMFORT_VIGNETTE", _environment_value, _platform_android,
|
||||
"How far the view darkens from its edges while a vehicle turns you\n"
|
||||
"(0 never, 1 to a small window)." },
|
||||
|
||||
+260
-1
@@ -107,6 +107,16 @@ static struct
|
||||
float vehicle_steer_angle; /* radians */
|
||||
float vehicle_gun_steer_angle; /* radians: steering that aims guns too */
|
||||
float vehicle_pitch_angle;
|
||||
/* the wheel of an open vehicle (a Warthog's: wheel_update) */
|
||||
int vehicle_wheel; /* vr.vehicle_wheel: the hands turn it */
|
||||
float vehicle_wheel_angle; /* radians: turned this far, it steers fully */
|
||||
int wheel_valid; /* where it is, as last drawn */
|
||||
float wheel_hands_drawn[2][3]; /* the driver's drawn hands on it, from the camera (world units) */
|
||||
int wheel_held[HALO_XR_HAND_COUNT];
|
||||
int wheel_hands; /* the hands that held it last frame (bits) */
|
||||
float wheel_reference; /* their turn about the column last frame */
|
||||
float wheel_turn; /* the wheel's turn (radians, anticlockwise as the driver sees it) */
|
||||
int wheel_logged;
|
||||
float vehicle_steer_curve; /* the stick's deflection to this power */
|
||||
float vehicle_steer_smoothing; /* seconds */
|
||||
float steer[2]; /* the steering as smoothed: aside, up (-1..1) */
|
||||
@@ -134,6 +144,11 @@ static struct
|
||||
float scope_size;
|
||||
int crosshair;
|
||||
int crosshair_captured; /* this frame (halo_vr_capture_crosshair) */
|
||||
/* players' names this frame (halo_vr_add_name), and whether their
|
||||
slots were taken (halo_vr_capture_names) */
|
||||
int name_count;
|
||||
float name_points[HALO_XR_MAXIMUM_NAMES][3];
|
||||
int names_captured;
|
||||
/* the barrel of the weapon as drawn (halo_vr_set_barrel): where shots,
|
||||
the crosshair and the laser start */
|
||||
float barrel[3];
|
||||
@@ -242,6 +257,7 @@ the target), keeping the size it has in the HUD: this part of the HUD. */
|
||||
static void cross3(const float a[3], const float b[3], float out[3]);
|
||||
static float normalize3(float v[3]);
|
||||
static int crosshair_pose(struct halo_xr_pose *pose, float *size);
|
||||
static int name_pose(const float point[3], struct halo_xr_pose *pose, float *width);
|
||||
static int weapon_hand_tracked(short local_player_index);
|
||||
static void controller_axes(float forward[3], float up[3], float right[3]);
|
||||
static void hand_offset(float out[3]);
|
||||
@@ -449,6 +465,10 @@ void halo_vr_initialize(void)
|
||||
vr.vehicle_steer_angle = (float)config_real("vr.vehicle_steer_degrees") * PI / 180.0f;
|
||||
vr.vehicle_gun_steer_angle = (float)config_real("vr.vehicle_gun_steer_degrees") * PI / 180.0f;
|
||||
vr.vehicle_pitch_angle = (float)config_real("vr.vehicle_pitch_degrees") * PI / 180.0f;
|
||||
vr.vehicle_wheel = config_boolean("vr.vehicle_wheel");
|
||||
vr.vehicle_wheel_angle = (float)config_real("vr.vehicle_wheel_degrees") * PI / 180.0f;
|
||||
if (vr.vehicle_wheel_angle < 10.0f * PI / 180.0f)
|
||||
vr.vehicle_wheel_angle = 10.0f * PI / 180.0f;
|
||||
vr.vehicle_steer_curve = (float)config_real("vr.vehicle_steer_curve");
|
||||
vr.vehicle_steer_smoothing = (float)config_real("vr.vehicle_steer_smoothing");
|
||||
vr.comfort_vignette = (float)config_real("vr.comfort_vignette");
|
||||
@@ -551,7 +571,8 @@ static void grenade_update(void)
|
||||
const struct halo_xr_hand *hand = &vr.frame.hands[HALO_XR_HAND_LEFT];
|
||||
unsigned long long now = now_us();
|
||||
int valid = hand->active && (hand->flags & HALO_XR_POSE_VALID);
|
||||
int held = valid && vr.last_overlay_mode != HALO_XR_OVERLAY_SCREEN &&
|
||||
/* (at a wheel the left trigger brakes: xinput_sdl.c) */
|
||||
int held = valid && vr.last_overlay_mode != HALO_XR_OVERLAY_SCREEN && !vr.wheel_hands &&
|
||||
hand->trigger > (vr.grenade_held ? 0.2f : 0.3f);
|
||||
int count = vr.grenade_sample_count;
|
||||
|
||||
@@ -731,7 +752,9 @@ static void melee_update(void)
|
||||
continue;
|
||||
}
|
||||
/* (a grenade's throw is not a blow) */
|
||||
/* (nor is turning the wheel) */
|
||||
if (vr.hand_last_valid[hand] && seconds > 0.0f && seconds < 0.1f && vr.melee_swing_speed > 0.0f &&
|
||||
!vr.wheel_held[hand] &&
|
||||
vr.last_overlay_mode != HALO_XR_OVERLAY_SCREEN && now >= vr.melee_ready_us &&
|
||||
!(hand == HALO_XR_HAND_LEFT && (vr.grenade_held || now - vr.grenade_released_us < 500000)))
|
||||
{
|
||||
@@ -817,6 +840,138 @@ static void turn_update(void)
|
||||
seat_body();
|
||||
}
|
||||
|
||||
/* At an open vehicle's wheel (a Warthog's, vr.vehicle_wheel), a hand that
|
||||
grips near it takes hold of it, and the hands turn it about its column: both
|
||||
by the line between them, one about the wheel's middle. Where it is, the
|
||||
driver's hands as drawn hold it (halo_vr_set_wheel); its column runs from
|
||||
there back towards the driver, tipped up WHEEL_COLUMN_TILT. Held, its turn
|
||||
steers (halo_vr_aim); let go, the right stick does. */
|
||||
#define WHEEL_REACH 0.35f /* metres from its middle */
|
||||
#define WHEEL_COLUMN_TILT (45.0f * PI / 180.0f) /* from the horizontal */
|
||||
|
||||
static void wheel_release(void)
|
||||
{
|
||||
int hand;
|
||||
|
||||
for (hand = 0; hand < HALO_XR_HAND_COUNT; hand++)
|
||||
vr.wheel_held[hand] = 0;
|
||||
vr.wheel_hands = 0;
|
||||
}
|
||||
|
||||
static void wheel_update(void)
|
||||
{
|
||||
static const float local_up[3] = { 0.0f, 1.0f, 0.0f };
|
||||
float world[3], centre[3], forward_game[3], forward[3], column[3], up[3], side[3], line[3];
|
||||
float heading = seat_heading(), along, angle;
|
||||
int hand, axis, hands = 0;
|
||||
|
||||
if (vr.seat_mode != HALO_VR_SEAT_STEER || !vr.vehicle_wheel || !vr.wheel_valid || !vr.frame.focused ||
|
||||
vr.last_overlay_mode == HALO_XR_OVERLAY_SCREEN)
|
||||
{
|
||||
wheel_release();
|
||||
return;
|
||||
}
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
{
|
||||
world[axis] = vr.game_camera[axis] +
|
||||
(vr.wheel_hands_drawn[0][axis] + vr.wheel_hands_drawn[1][axis]) * 0.5f;
|
||||
}
|
||||
world_to_local(world, centre);
|
||||
if (!vr.wheel_logged)
|
||||
{
|
||||
float apart[3];
|
||||
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
apart[axis] = (vr.wheel_hands_drawn[0][axis] - vr.wheel_hands_drawn[1][axis]) * METRES_PER_WORLD_UNIT;
|
||||
platform_log("VR: wheel at %.2f %.2f %.2f (LOCAL), the hands %.2f m apart", centre[0], centre[1], centre[2],
|
||||
sqrtf(apart[0] * apart[0] + apart[1] * apart[1] + apart[2] * apart[2]));
|
||||
vr.wheel_logged = 1;
|
||||
}
|
||||
/* its column, and the wheel's up and left about it */
|
||||
forward_game[0] = cosf(heading);
|
||||
forward_game[1] = sinf(heading);
|
||||
forward_game[2] = 0.0f;
|
||||
game_to_local(forward_game, forward);
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
column[axis] = -forward[axis] * cosf(WHEEL_COLUMN_TILT) + local_up[axis] * sinf(WHEEL_COLUMN_TILT);
|
||||
along = local_up[0] * column[0] + local_up[1] * column[1] + local_up[2] * column[2];
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
up[axis] = local_up[axis] - column[axis] * along;
|
||||
normalize3(up);
|
||||
cross3(column, up, side);
|
||||
for (hand = 0; hand < HALO_XR_HAND_COUNT; hand++)
|
||||
{
|
||||
const struct halo_xr_hand *state = &vr.frame.hands[hand];
|
||||
float apart[3];
|
||||
|
||||
if (!state->active || !(state->flags & HALO_XR_POSE_VALID) || state->squeeze < 0.35f)
|
||||
{
|
||||
vr.wheel_held[hand] = 0;
|
||||
continue;
|
||||
}
|
||||
if (!vr.wheel_held[hand])
|
||||
{
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
apart[axis] = state->grip.position[axis] - centre[axis];
|
||||
if (state->squeeze < 0.6f ||
|
||||
sqrtf(apart[0] * apart[0] + apart[1] * apart[1] + apart[2] * apart[2]) > WHEEL_REACH)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
vr.wheel_held[hand] = 1;
|
||||
host_xr_haptic(hand, 0.3f, 0.05f);
|
||||
}
|
||||
hands |= 1 << hand;
|
||||
}
|
||||
if (!hands)
|
||||
{
|
||||
vr.wheel_hands = 0;
|
||||
return;
|
||||
}
|
||||
/* the hands' turn about the column */
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
{
|
||||
line[axis] = hands == ((1 << HALO_XR_HAND_LEFT) | (1 << HALO_XR_HAND_RIGHT)) ?
|
||||
vr.frame.hands[HALO_XR_HAND_LEFT].grip.position[axis] -
|
||||
vr.frame.hands[HALO_XR_HAND_RIGHT].grip.position[axis] :
|
||||
vr.frame.hands[hands & (1 << HALO_XR_HAND_LEFT) ? HALO_XR_HAND_LEFT : HALO_XR_HAND_RIGHT]
|
||||
.grip.position[axis] - centre[axis];
|
||||
}
|
||||
angle = atan2f(line[0] * side[0] + line[1] * side[1] + line[2] * side[2],
|
||||
line[0] * up[0] + line[1] * up[1] + line[2] * up[2]);
|
||||
if (!vr.wheel_hands)
|
||||
{
|
||||
/* taken hold of: turned as far as it steers now */
|
||||
vr.wheel_turn = -vr.steer[0] * vr.vehicle_wheel_angle;
|
||||
}
|
||||
else if (hands == vr.wheel_hands)
|
||||
{
|
||||
vr.wheel_turn += wrap_angle(angle - vr.wheel_reference);
|
||||
}
|
||||
if (vr.wheel_turn > vr.vehicle_wheel_angle)
|
||||
vr.wheel_turn = vr.vehicle_wheel_angle;
|
||||
if (vr.wheel_turn < -vr.vehicle_wheel_angle)
|
||||
vr.wheel_turn = -vr.vehicle_wheel_angle;
|
||||
vr.wheel_reference = angle;
|
||||
vr.wheel_hands = hands;
|
||||
}
|
||||
|
||||
void halo_vr_set_wheel(short local_player_index, const float left[3], const float right[3])
|
||||
{
|
||||
if (!vr.active || local_player_index != 0)
|
||||
return;
|
||||
vr.wheel_valid = left && right;
|
||||
if (!vr.wheel_valid)
|
||||
return;
|
||||
memcpy(vr.wheel_hands_drawn[0], left, sizeof(vr.wheel_hands_drawn[0]));
|
||||
memcpy(vr.wheel_hands_drawn[1], right, sizeof(vr.wheel_hands_drawn[1]));
|
||||
}
|
||||
|
||||
int halo_vr_wheel_held(void)
|
||||
{
|
||||
return vr.active && vr.wheel_hands != 0;
|
||||
}
|
||||
|
||||
/* The comfort vignette: while a vehicle turns the player (from 15 degrees a
|
||||
second, fully at 60), the eye images darken from their edges; it comes in
|
||||
quickly and goes slowly. */
|
||||
@@ -1021,6 +1176,8 @@ void halo_vr_frame_begin(void)
|
||||
vr.eyes_captured = 0;
|
||||
vr.scope_captured = 0;
|
||||
vr.crosshair_captured = 0;
|
||||
vr.name_count = 0;
|
||||
vr.names_captured = 0;
|
||||
vr.overlay_mode = HALO_XR_OVERLAY_SCREEN;
|
||||
vr.overlay_blend = 0;
|
||||
if (vr.frame.recentred)
|
||||
@@ -1035,6 +1192,7 @@ void halo_vr_frame_begin(void)
|
||||
vr_recentre();
|
||||
}
|
||||
turn_update();
|
||||
wheel_update();
|
||||
vignette_update();
|
||||
vehicle_spawn_update();
|
||||
look_update();
|
||||
@@ -1087,6 +1245,20 @@ void halo_vr_present(unsigned int back_buffer_texture)
|
||||
weapon aims */
|
||||
if (vr.crosshair_captured && vr.overlay_mode == HALO_XR_OVERLAY_HEAD_LOCKED)
|
||||
submit.crosshair = crosshair_pose(&submit.crosshair_pose, &submit.crosshair_size);
|
||||
/* the names, each over its player's head */
|
||||
if (vr.names_captured && submit.eyes && vr.overlay_mode == HALO_XR_OVERLAY_HEAD_LOCKED)
|
||||
{
|
||||
int name;
|
||||
|
||||
for (name = 0; name < vr.name_count; name++)
|
||||
{
|
||||
if (name_pose(vr.name_points[name], &submit.name_poses[submit.name_count],
|
||||
&submit.name_widths[submit.name_count]))
|
||||
{
|
||||
submit.name_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vr.scope_captured && submit.eyes)
|
||||
{
|
||||
submit.scope = 1;
|
||||
@@ -1372,6 +1544,13 @@ int halo_vr_aim(short local_player_index, float current_yaw, float current_pitch
|
||||
amount = amount > 0.0f ? powf(amount > 1.0f ? 1.0f : amount, vr.vehicle_steer_curve) : 0.0f;
|
||||
if (stick[axis] < 0.0f)
|
||||
amount = -amount;
|
||||
if (axis == 0 && vr.wheel_hands)
|
||||
{
|
||||
/* (the hands on the wheel steer, as they turn it: clockwise
|
||||
to the right) */
|
||||
vr.steer[0] = -vr.wheel_turn / vr.vehicle_wheel_angle;
|
||||
continue;
|
||||
}
|
||||
vr.steer[axis] += (amount - vr.steer[axis]) * blend;
|
||||
}
|
||||
/* (a Ghost or a Banshee aims its guns as it steers: less, finer) */
|
||||
@@ -1947,6 +2126,82 @@ static int crosshair_pose(struct halo_xr_pose *pose, float *size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ---------- players' names
|
||||
|
||||
Names over the heads (hud.c) are drawn into slots of a region of the back
|
||||
buffer, one under another, before the HUD, and each slot is shown on a quad
|
||||
of its own over its player's head, facing the eyes, as wide as the name
|
||||
looks at the HUD's distance: in VR the HUD is a screen at one distance,
|
||||
where names drawn on it hung before the eyes. */
|
||||
|
||||
#define NAME_SLOT_LEFT 240
|
||||
#define NAME_SLOT_WIDTH 160
|
||||
#define NAME_SLOT_HEIGHT 30
|
||||
/* how large a name looks against the HUD's text (smaller: over a head, not
|
||||
on the screen before the eyes) */
|
||||
#define NAME_SCALE 0.6f
|
||||
|
||||
int halo_vr_names_apart(void)
|
||||
{
|
||||
return vr.active && halo_vr_stereo_frame();
|
||||
}
|
||||
|
||||
void halo_vr_name_slot(int slot, short bounds[4])
|
||||
{
|
||||
bounds[0] = NAME_SLOT_LEFT;
|
||||
bounds[1] = (short)(slot * NAME_SLOT_HEIGHT);
|
||||
bounds[2] = NAME_SLOT_LEFT + NAME_SLOT_WIDTH;
|
||||
bounds[3] = (short)((slot + 1) * NAME_SLOT_HEIGHT);
|
||||
}
|
||||
|
||||
int halo_vr_add_name(const float point[3])
|
||||
{
|
||||
int slot = vr.name_count;
|
||||
|
||||
if (slot >= HALO_XR_MAXIMUM_NAMES)
|
||||
return -1;
|
||||
memcpy(vr.name_points[slot], point, sizeof(vr.name_points[slot]));
|
||||
vr.name_count++;
|
||||
return slot;
|
||||
}
|
||||
|
||||
void halo_vr_capture_names(void)
|
||||
{
|
||||
if (vr.name_count > 0)
|
||||
{
|
||||
vr.names_captured = host_xr_copy_layer_region(HALO_XR_LAYER_NAMES, d3d8_back_buffer_texture(),
|
||||
HALO_XR_COPY_ALPHA, NAME_SLOT_LEFT / 640.0f, 0.0f, (NAME_SLOT_LEFT + NAME_SLOT_WIDTH) / 640.0f,
|
||||
HALO_XR_MAXIMUM_NAMES * NAME_SLOT_HEIGHT / 480.0f);
|
||||
}
|
||||
d3d8_clear_back_buffer(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
static int name_pose(const float point[3], struct halo_xr_pose *pose, float *width)
|
||||
{
|
||||
static const float world_up[3] = { 0.0f, 1.0f, 0.0f };
|
||||
float x[3], y[3], z[3];
|
||||
float distance;
|
||||
float angle;
|
||||
int axis;
|
||||
|
||||
world_to_local(point, pose->position);
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
z[axis] = vr.frame.head.position[axis] - pose->position[axis];
|
||||
distance = normalize3(z);
|
||||
/* (facing the eyes, upright) */
|
||||
if (distance < 0.05f)
|
||||
return 0;
|
||||
cross3(world_up, z, x);
|
||||
if (normalize3(x) < 1e-4f)
|
||||
return 0;
|
||||
cross3(z, x, y);
|
||||
quaternion_from_axes(x, y, z, pose->orientation);
|
||||
/* (as wide as the slot looks on the HUD, smaller) */
|
||||
angle = (float)NAME_SLOT_WIDTH / 640.0f * vr.hud_width / vr.hud_distance * NAME_SCALE;
|
||||
*width = 2.0f * distance * tanf(angle * 0.5f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ---------- the scope
|
||||
|
||||
Zoomed in, the weapon shows its view on a disc over the barrel, like a
|
||||
@@ -2175,6 +2430,10 @@ int halo_vr_scope(short local_player_index, float magnification, float position[
|
||||
return 0;
|
||||
}
|
||||
int halo_vr_scope_pass(void) { return 0; }
|
||||
int halo_vr_names_apart(void) { return 0; }
|
||||
void halo_vr_name_slot(int slot, short bounds[4]) { (void)slot; (void)bounds; }
|
||||
int halo_vr_add_name(const float point[3]) { (void)point; return -1; }
|
||||
void halo_vr_capture_names(void) {}
|
||||
void halo_vr_set_scope_raise(float metres) { (void)metres; }
|
||||
void halo_vr_capture_scope(float left, float top, float right, float bottom)
|
||||
{
|
||||
|
||||
@@ -540,12 +540,17 @@ In play, laid out for VR shooters rather than by position:
|
||||
right stick turns (vr.c); click zooms left stick move; click crouches
|
||||
menu pause (start)
|
||||
|
||||
Holding a Warthog's wheel (vr.c), the right trigger is the throttle and the
|
||||
left one the brake (backwards, once stopped): the left stick pushed up or
|
||||
down as far, unless it is pushed further.
|
||||
|
||||
In the menus the buttons are the Xbox's by position: A accepts, B goes back. */
|
||||
|
||||
#include "guest_host.h"
|
||||
#include "halo_xr_abi.h"
|
||||
|
||||
int halo_vr_controllers(struct halo_xr_hand hands[HALO_XR_HAND_COUNT], int *menus);
|
||||
int halo_vr_wheel_held(void);
|
||||
|
||||
static SHORT vr_stick(float value)
|
||||
{
|
||||
@@ -577,6 +582,14 @@ static void vr_gamepad_state(XINPUT_GAMEPAD *pad)
|
||||
pad->bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] = (BYTE)(right->trigger * 255.0f);
|
||||
if ((BYTE)(left->trigger * 255.0f) > pad->bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER])
|
||||
pad->bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] = (BYTE)(left->trigger * 255.0f);
|
||||
if (!menus && halo_vr_wheel_held())
|
||||
{
|
||||
/* at the wheel: the triggers drive, and neither fire nor throw */
|
||||
pad->bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] = 0;
|
||||
pad->bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] = 0;
|
||||
value = vr_stick(right->trigger - left->trigger);
|
||||
if (abs(value) > abs(pad->sThumbLY)) pad->sThumbLY = value;
|
||||
}
|
||||
if (menus)
|
||||
{
|
||||
/* the right stick scrolls too; turning is off in the menus */
|
||||
@@ -592,7 +605,9 @@ static void vr_gamepad_state(XINPUT_GAMEPAD *pad)
|
||||
}
|
||||
merge_button(pad, XINPUT_GAMEPAD_A, (right->buttons & HALO_XR_BUTTON_A) != 0);
|
||||
merge_button(pad, XINPUT_GAMEPAD_X, (left->buttons & HALO_XR_BUTTON_A) != 0);
|
||||
merge_button(pad, XINPUT_GAMEPAD_B, (right->buttons & HALO_XR_BUTTON_SQUEEZE) != 0 || halo_vr_melee());
|
||||
/* (the grips holding a Warthog's wheel are not a blow) */
|
||||
merge_button(pad, XINPUT_GAMEPAD_B,
|
||||
((right->buttons & HALO_XR_BUTTON_SQUEEZE) != 0 && !halo_vr_wheel_held()) || halo_vr_melee());
|
||||
merge_button(pad, XINPUT_GAMEPAD_Y, (left->buttons & HALO_XR_BUTTON_B) != 0);
|
||||
{
|
||||
/* B: a tap is the flashlight, holding it switches grenades; the
|
||||
|
||||
+56
-13
@@ -1033,13 +1033,6 @@ static short hud_player_names_setting(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
/* (the VR port's: in VR the HUD is a screen at a fixed distance before
|
||||
the eyes, so names drawn on it hang there, not over the heads; none
|
||||
until they are drawn into each eye's picture) */
|
||||
if (halo_vr_active())
|
||||
return _player_names_none;
|
||||
#endif
|
||||
return setting;
|
||||
}
|
||||
|
||||
@@ -1134,7 +1127,8 @@ static void hud_draw_player_name(
|
||||
long player_index,
|
||||
boolean ally,
|
||||
boolean indicator,
|
||||
real enemy_range)
|
||||
real enemy_range,
|
||||
boolean vr_apart)
|
||||
{
|
||||
struct player_datum const *player = player_get(player_index);
|
||||
long font_index = hud_get_font_index();
|
||||
@@ -1164,10 +1158,35 @@ static void hud_draw_player_name(
|
||||
/* (where the game draws a teammate's triangle) */
|
||||
head_position.z += 0.30000001f;
|
||||
matrix4x3_transform_point(&render.frustum.world_to_view, &head_position, &view_position);
|
||||
if (!render_camera_view_to_screen(&render.camera, &render.frustum, &view_position, &screen_position))
|
||||
return;
|
||||
x = (short)fast_ftol(screen_position.x) - render.camera.viewport_bounds.x0;
|
||||
y = (short)fast_ftol(screen_position.y) - render.camera.viewport_bounds.y0;
|
||||
#ifdef HALO_ANDROID
|
||||
if (vr_apart)
|
||||
{
|
||||
/* (VR: in a slot of its own, shown over the head: halo_vr.h) */
|
||||
float point[3];
|
||||
short slot_bounds[4];
|
||||
int slot;
|
||||
|
||||
point[0] = head_position.x;
|
||||
point[1] = head_position.y;
|
||||
point[2] = head_position.z + (indicator ? 0.15f : 0.0f);
|
||||
slot = halo_vr_add_name(point);
|
||||
if (slot < 0)
|
||||
return;
|
||||
halo_vr_name_slot(slot, slot_bounds);
|
||||
x = (short)((slot_bounds[0] + slot_bounds[2]) / 2);
|
||||
y = (short)(slot_bounds[3] - 4);
|
||||
/* (an ally's whole at any distance it is drawn at) */
|
||||
view_position.z = -1.0f;
|
||||
indicator = FALSE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!render_camera_view_to_screen(&render.camera, &render.frustum, &view_position, &screen_position))
|
||||
return;
|
||||
x = (short)fast_ftol(screen_position.x) - render.camera.viewport_bounds.x0;
|
||||
y = (short)fast_ftol(screen_position.y) - render.camera.viewport_bounds.y0;
|
||||
}
|
||||
if (indicator)
|
||||
{
|
||||
struct bitmap_data *bitmap = bitmap_group_get_bitmap_from_sequence(
|
||||
@@ -1209,8 +1228,32 @@ static void hud_draw_player_name(
|
||||
return;
|
||||
}
|
||||
|
||||
static void hud_draw_player_names_now(
|
||||
boolean vr_apart);
|
||||
|
||||
static void hud_draw_player_names(
|
||||
void)
|
||||
{
|
||||
#ifdef HALO_ANDROID
|
||||
/* (VR: apart, before the HUD: hud_draw_player_names_vr) */
|
||||
if (halo_vr_active())
|
||||
return;
|
||||
#endif
|
||||
hud_draw_player_names_now(FALSE);
|
||||
}
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
/* VR: the names drawn into their slots, each then shown over its player's
|
||||
head (render.c, before the HUD; halo_vr_names_apart) */
|
||||
void hud_draw_player_names_vr(
|
||||
void)
|
||||
{
|
||||
hud_draw_player_names_now(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void hud_draw_player_names_now(
|
||||
boolean vr_apart)
|
||||
{
|
||||
short setting = hud_player_names_setting();
|
||||
long player_index = local_player_get_player_index(render.local_player_index);
|
||||
@@ -1235,7 +1278,7 @@ static void hud_draw_player_names(
|
||||
continue;
|
||||
if ((ally && setting == _player_names_enemies) || (!ally && setting == _player_names_allies))
|
||||
continue;
|
||||
hud_draw_player_name(iterator.datum_index, ally, ally && indicators, enemy_range);
|
||||
hud_draw_player_name(iterator.datum_index, ally, ally && indicators, enemy_range, vr_apart);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -29,6 +29,11 @@ struct hud_scripted_globals_definition
|
||||
/* ---------- prototypes/HUD.C */
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
#ifdef HALO_ANDROID
|
||||
/* VR: players' names drawn into their slots (halo_vr_names_apart) */
|
||||
void hud_draw_player_names_vr(
|
||||
void);
|
||||
#endif
|
||||
void hud_draw_crosshair(
|
||||
void);
|
||||
#endif
|
||||
|
||||
@@ -667,8 +667,25 @@ static void render_vr_player_frame(
|
||||
long vehicle_index = unit_index == NONE ? NONE : object_get(unit_index)->object.parent_object_index;
|
||||
real_matrix4x3 *nodes = vehicle_index == NONE ? NULL : render_interpolation_object_node_matrices(vehicle_index);
|
||||
|
||||
real_point3d left_hand;
|
||||
real_point3d right_hand;
|
||||
|
||||
if (nodes)
|
||||
halo_vr_set_seat_frame(window->local_player_index, (float)atan2(nodes[0].forward.j, nodes[0].forward.i));
|
||||
if (nodes && render_object_vr_wheel_hands(unit_index, &left_hand, &right_hand))
|
||||
{
|
||||
/* (at a wheel: the hands that hold it) */
|
||||
float left[3] = { left_hand.x - game_position[0], left_hand.y - game_position[1],
|
||||
left_hand.z - game_position[2] };
|
||||
float right[3] = { right_hand.x - game_position[0], right_hand.y - game_position[1],
|
||||
right_hand.z - game_position[2] };
|
||||
|
||||
halo_vr_set_wheel(window->local_player_index, left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
halo_vr_set_wheel(window->local_player_index, NULL, NULL);
|
||||
}
|
||||
}
|
||||
if (halo_vr_multiview())
|
||||
{
|
||||
@@ -853,6 +870,14 @@ static void render_vr_overlay(
|
||||
parameters.suppress_clear = TRUE;
|
||||
parameters.window_index = render.window_index;
|
||||
|
||||
if (!menus_active && halo_vr_names_apart())
|
||||
{
|
||||
/* the players' names, each to be shown over its head */
|
||||
rasterizer_window_begin(¶meters);
|
||||
hud_draw_player_names_vr();
|
||||
rasterizer_window_end();
|
||||
halo_vr_capture_names();
|
||||
}
|
||||
if (!menus_active && halo_vr_crosshair_apart())
|
||||
{
|
||||
/* the weapon's crosshair alone, taken to where the weapon aims */
|
||||
|
||||
@@ -154,6 +154,11 @@ boolean render_object_vr_seated_body(
|
||||
long object_index);
|
||||
boolean render_object_vr_at_controls(
|
||||
long object_index);
|
||||
/* at an open wheel (a Warthog's), where its drawn hands hold it */
|
||||
boolean render_object_vr_wheel_hands(
|
||||
long object_index,
|
||||
real_point3d *left,
|
||||
real_point3d *right);
|
||||
#endif
|
||||
void render_objects(
|
||||
void);
|
||||
|
||||
@@ -509,6 +509,47 @@ boolean render_object_vr_seated_body(
|
||||
vehicle_vr_encloses_riders(object->object.parent_object_index));
|
||||
}
|
||||
|
||||
/* at an open wheel (a Warthog's): where the driver's hands hold it, as the
|
||||
seat's animation has them this frame (vr.c: the player's own hands turn
|
||||
it) */
|
||||
boolean render_object_vr_wheel_hands(
|
||||
long object_index,
|
||||
real_point3d *left,
|
||||
real_point3d *right)
|
||||
{
|
||||
struct object_datum *object;
|
||||
struct model *model;
|
||||
real_matrix4x3 *nodes;
|
||||
short node_index;
|
||||
short left_index = NONE;
|
||||
short right_index = NONE;
|
||||
|
||||
if (!render_object_vr_seated_body(object_index))
|
||||
return FALSE;
|
||||
object = object_get(object_index);
|
||||
if (!TEST_FLAG(_object_mask_vehicle, object_get(object->object.parent_object_index)->object.type))
|
||||
return FALSE;
|
||||
model = model_definition_get(object_definition_get(object->definition_index)->object.model.index);
|
||||
nodes = render_interpolation_object_node_matrices(object_index);
|
||||
if (!nodes)
|
||||
nodes = object_get_node_matrices(object_index);
|
||||
for (node_index = 0; node_index < model->nodes.count; node_index++)
|
||||
{
|
||||
char const *name = TAG_BLOCK_GET_ELEMENT(&model->nodes, node_index, struct model_node)->name;
|
||||
size_t length = strlen(name);
|
||||
|
||||
if (length >= 6 && !strcmp(name + length - 6, "l hand"))
|
||||
left_index = node_index;
|
||||
if (length >= 6 && !strcmp(name + length - 6, "r hand"))
|
||||
right_index = node_index;
|
||||
}
|
||||
if (left_index == NONE || right_index == NONE)
|
||||
return FALSE;
|
||||
*left = nodes[left_index].position;
|
||||
*right = nodes[right_index].position;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* its node matrices with the head's shrunk to nothing, which takes the
|
||||
helmet out of the eyes' way */
|
||||
static real_matrix4x3 *object_vr_headless_node_matrices(
|
||||
|
||||
Reference in new issue
Block a user