From 1773dd90c94a331ab7241efc17bccbe602be4aac Mon Sep 17 00:00:00 2001 From: XProger Date: Mon, 23 Jul 2018 05:56:45 +0300 Subject: [PATCH] #3 look --- src/camera.h | 121 +++++++++++++++++++++++------------------------ src/character.h | 15 +++++- src/controller.h | 49 +++++++++++-------- src/lara.h | 45 +++++++++--------- 4 files changed, 123 insertions(+), 107 deletions(-) diff --git a/src/camera.h b/src/camera.h index 5ffb397..4b3bb95 100644 --- a/src/camera.h +++ b/src/camera.h @@ -8,6 +8,7 @@ #define CAM_OFFSET_FOLLOW (1024.0f + 512.0f) #define CAM_OFFSET_COMBAT (2048.0f + 512.0f) +#define CAM_OFFSET_LOOK (512.0f) #define CAM_SPEED_FOLLOW 12 #define CAM_SPEED_COMBAT 8 @@ -19,8 +20,7 @@ struct Camera : ICamera { Frustum *frustum; float fov, aspect, znear, zfar; - vec3 advAngle, targetAngle; - float advTimer; + vec3 lookAngle, targetAngle; mat4 mViewInv; float timer; @@ -34,6 +34,8 @@ struct Camera : ICamera { Camera(IGame *game, Character *owner) : ICamera(), game(game), level(game->getLevel()), frustum(new Frustum()), timer(-1.0f), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL) { this->owner = owner; + lookAngle = vec3(0.0f); + changeView(false); if (level->isCutsceneLevel()) { mode = MODE_CUTSCENE; @@ -50,8 +52,6 @@ struct Camera : ICamera { target.pos.y -= 1024; eye.pos.z -= 100; - advTimer = -1.0f; - speed = CAM_SPEED_FOLLOW; smooth = false; } @@ -92,13 +92,19 @@ struct Camera : ICamera { pos.z = center.z; } - if (mode != MODE_STATIC) - pos.y = box.max.y + (box.min.y - box.max.y) * (3.0f / 4.0f); - else - pos.y = center.y; + if (mode == MODE_LOOK) { + Basis b = owner->getJoint(owner->jointHead); + b.translate(vec3(0, -128, 0)); + pos = b.pos; + } else { + if (mode != MODE_STATIC) + pos.y = box.max.y + (box.min.y - box.max.y) * (3.0f / 4.0f); + else + pos.y = center.y; - if (owner->stand != Character::STAND_UNDERWATER) - pos.y -= 256; + if (owner->stand != Character::STAND_UNDERWATER) + pos.y -= 256; + } return pos; } @@ -282,6 +288,8 @@ struct Camera : ICamera { void move(const TR::Location &to) { float t = (smooth && speed) ? (30.0f / speed * Core::deltaTime) : 1.0f; + if (mode == MODE_LOOK) + t = 20.0f * Core::deltaTime; eye.pos = eye.pos.lerp(to.pos, t); eye.room = to.room; @@ -354,6 +362,41 @@ struct Camera : ICamera { } else { Controller *lookAt = NULL; + if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) { + lookAngle = vec3(0.0f); + } else { + if (mode == MODE_LOOK) { + float d = 3.0f * Core::deltaTime; + + lookAngle.x += Input::joy[cameraIndex].L.y * d; + lookAngle.y += Input::joy[cameraIndex].L.x * d; + + if (Input::state[cameraIndex][cUp]) lookAngle.x -= d; + if (Input::state[cameraIndex][cDown]) lookAngle.x += d; + if (Input::state[cameraIndex][cLeft]) lookAngle.y -= d; + if (Input::state[cameraIndex][cRight]) lookAngle.y += d; + + lookAngle.x = clamp(lookAngle.x, -80 * DEG2RAD, +80 * DEG2RAD); + lookAngle.y = clamp(lookAngle.y, -90 * DEG2RAD, +90 * DEG2RAD); + } else + if (lookAngle.x != 0.0f || lookAngle.y != 0.0f) { + float t = 10.0f * Core::deltaTime; + lookAngle.x = lerp(clampAngle(lookAngle.x), 0.0f, t); + lookAngle.y = lerp(clampAngle(lookAngle.y), 0.0f, t); + if (lookAngle.x < EPS) lookAngle.x = 0.0f; + if (lookAngle.y < EPS) lookAngle.y = 0.0f; + } + } + + targetAngle = owner->angle + lookAngle; + if (!firstPerson && (mode == MODE_FOLLOW || mode == MODE_COMBAT)) + targetAngle += angle; + + targetAngle.x = clampAngle(targetAngle.x); + targetAngle.y = clampAngle(targetAngle.y); + + targetAngle.x = clamp(targetAngle.x, -85 * DEG2RAD, +85 * DEG2RAD); + if (mode != MODE_STATIC) { if (!owner->viewTarget) { if (viewTarget && !viewTarget->flags.invisible) { @@ -370,55 +413,6 @@ struct Camera : ICamera { owner->lookAt(NULL); } - if (Core::settings.detail.stereo == Core::Settings::STEREO_VR) { - advAngle = vec3(0.0f); - } else { - vec3 advAngleOld = advAngle; - - if (Input::down[ikMouseL]) { - vec2 delta = Input::mouse.pos - Input::mouse.start.L; - advAngle.x -= delta.y * 0.01f; - advAngle.y += delta.x * 0.01f; - advAngle.y = clamp(advAngle.y, -PI, PI); - Input::mouse.start.L = Input::mouse.pos; - } - - // TODO: use player index - if (Input::state[cameraIndex][cLook]) { - float d = 2.0f * Core::deltaTime; - - advAngle.x += Input::joy[cameraIndex].L.y * d; - advAngle.y += Input::joy[cameraIndex].L.x * d; - - if (Input::state[cameraIndex][cUp]) advAngle.x -= d; - if (Input::state[cameraIndex][cDown]) advAngle.x += d; - if (Input::state[cameraIndex][cLeft]) advAngle.y += d; - if (Input::state[cameraIndex][cRight]) advAngle.y -= d; - } - - if (advAngleOld == advAngle) { - if (advTimer > 0.0f) { - advTimer = max(0.0f, advTimer - Core::deltaTime); - } - } else - advTimer = -1.0f; - - if (owner->velocity != 0.0f && advTimer < 0.0f && !Input::down[ikMouseL]) - advTimer = -advTimer; - - if (advTimer == 0.0f && advAngle != 0.0f) { - float t = 10.0f * Core::deltaTime; - advAngle.x = lerp(clampAngle(advAngle.x), 0.0f, t); - advAngle.y = lerp(clampAngle(advAngle.y), 0.0f, t); - } - } - - targetAngle = owner->angle + advAngle; - if (!firstPerson && (mode == MODE_FOLLOW || mode == MODE_COMBAT)) - targetAngle += angle; - - targetAngle.x = clamp(targetAngle.x, -85 * DEG2RAD, +85 * DEG2RAD); - if (!firstPerson || viewIndex != -1) { if (timer > 0.0f) { @@ -452,7 +446,11 @@ struct Camera : ICamera { else target.pos.y = p.y; - float offset = (mode == MODE_COMBAT ? CAM_OFFSET_COMBAT : CAM_OFFSET_FOLLOW) * cosf(targetAngle.x); + float offset; + if (mode == MODE_LOOK) + offset = CAM_OFFSET_LOOK; + else + offset = (mode == MODE_COMBAT ? CAM_OFFSET_COMBAT : CAM_OFFSET_FOLLOW) * cosf(targetAngle.x); vec3 dir = vec3(targetAngle.x, targetAngle.y) * offset; to.pos = target.pos - dir; @@ -524,9 +522,6 @@ struct Camera : ICamera { if (firstPerson) smooth = false; - advAngle = vec3(0.0f); - advTimer = 0.0f; - fov = firstPerson ? 90.0f : 65.0f; znear = firstPerson ? 8.0f : 32.0f; zfar = 45.0f * 1024.0f; diff --git a/src/character.h b/src/character.h index 9c67ef4..858270c 100644 --- a/src/character.h +++ b/src/character.h @@ -245,11 +245,22 @@ struct Character : Controller { if (health <= 0.0f) target = NULL; + vec3 t(0.0f); + if (target) { + Box box = target->getBoundingBox(); + t = (box.min + box.max) * 0.5f; + } + + lookAtPos(target ? &t : NULL); + } + + + void lookAtPos(const vec3 *t = NULL) { float speed = 8.0f * Core::deltaTime; quat rot; if (jointChest > -1) { - if (aim(target, jointChest, rangeChest, rot)) { + if (t && aim(*t, jointChest, rangeChest, rot)) { if (fullChestRotation) rotChest = rotChest.slerp(rot, speed); else @@ -260,7 +271,7 @@ struct Character : Controller { } if (jointHead > -1) { - if (aim(target, jointHead, rangeHead, rot)) + if (t && aim(*t, jointHead, rangeHead, rot)) rotHead = rotHead.slerp(rot, speed); else rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed); diff --git a/src/controller.h b/src/controller.h index 9b3aa17..ea52312 100644 --- a/src/controller.h +++ b/src/controller.h @@ -589,37 +589,48 @@ struct Controller { layers[layer].mask = mask; } - bool aim(Controller *target, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) { - if (target) { - Box box = target->getBoundingBox(); - vec3 t = (box.min + box.max) * 0.5f; + bool aim(const vec3 &t, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) { + Basis b = animation.getJoints(getMatrix(), joint); + vec3 delta = (b.inverse() * t).normal(); + if (invertAim) + delta = -delta; - Basis b = animation.getJoints(getMatrix(), joint); - vec3 delta = (b.inverse() * t).normal(); - if (invertAim) - delta = -delta; + float angleY = clampAngle(atan2f(delta.x, delta.z)); + float angleX = clampAngle(asinf(delta.y)); - float angleY = clampAngle(atan2f(delta.x, delta.z)); - float angleX = clampAngle(asinf(delta.y)); + if (angleX > angleRange.x && angleX <= angleRange.y && + angleY > angleRange.z && angleY <= angleRange.w) { - if (angleX > angleRange.x && angleX <= angleRange.y && - angleY > angleRange.z && angleY <= angleRange.w) { + quat ax(vec3(1, 0, 0), -angleX); + quat ay(vec3(0, 1, 0), angleY); - quat ax(vec3(1, 0, 0), -angleX); - quat ay(vec3(0, 1, 0), angleY); + rot = ay * ax; + if (rotAbs) + *rotAbs = b.rot * rot; - rot = ay * ax; - if (rotAbs) - *rotAbs = b.rot * rot; - return true; - } + return true; } if (rotAbs) *rotAbs = rotYXZ(angle); + return false; } + bool aim(Controller *target, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) { + if (target) { + Box box = target->getBoundingBox(); + vec3 t = (box.min + box.max) * 0.5f; + return aim(t, joint, angleRange, rot, rotAbs); + } + + if (rotAbs) + *rotAbs = rotYXZ(angle); + + return false; + } + + bool insideRoom(const vec3 &pos, int roomIndex) const { TR::Room &r = level->rooms[roomIndex]; vec3 min = vec3((float)r.info.x + 1024, (float)r.info.yTop, (float)r.info.z + 1024); diff --git a/src/lara.h b/src/lara.h index 28a0d85..6840d5d 100644 --- a/src/lara.h +++ b/src/lara.h @@ -259,7 +259,6 @@ struct Lara : Character { Camera *camera; float hitTimer; - bool camChanged; // hit key detection to go first person view mode #ifdef _DEBUG //uint16 *dbgBoxes; @@ -439,15 +438,14 @@ struct Lara : Character { camera = new Camera(game, this); hitTimer = 0.0f; - camChanged = false; if (level->extra.laraSkin > -1) level->entities[entity].modelIndex = level->extra.laraSkin + 1; jointChest = 7; jointHead = 14; - rangeChest = vec4(-0.40f, 0.40f, -0.90f, 0.90f) * PI; - rangeHead = vec4(-0.25f, 0.25f, -0.50f, 0.50f) * PI; + rangeChest = vec4(-0.50f, 0.50f, -0.95f, 0.95f) * PI; + rangeHead = vec4(-0.30f, 0.30f, -0.55f, 0.55f) * PI; oxygen = LARA_MAX_OXYGEN; hitDir = -1; @@ -1178,7 +1176,12 @@ struct Lara : Character { updateOverrides(); - Character::lookAt(canLookAt() ? target : NULL); + Controller *lookTarget = canLookAt() ? target : NULL; + if (camera->mode == Camera::MODE_LOOK) { + vec3 p = pos + vec3(camera->targetAngle.x, camera->targetAngle.y) * 8192.0f; + Character::lookAtPos(&p); + } else + Character::lookAt(lookTarget); if (!emptyHands()) { updateTargets(); @@ -1318,7 +1321,7 @@ struct Lara : Character { } if (arms[0].target && arms[1].target && arms[0].target != arms[1].target) { - viewTarget = NULL; //arms[0].target; + viewTarget = (arms[0].target->pos - pos).length2() < (arms[1].target->pos - pos).length2() ? arms[0].target : arms[1].target; } else if (arms[0].target) viewTarget = arms[0].target; else if (arms[1].target) @@ -2597,20 +2600,18 @@ struct Lara : Character { input = Character::getInput(); if (input & DEATH) return input; - if (Input::state[pid][cLook]) input |= LOOK; - if (!(input & LOOK)) { - if (Input::state[pid][cUp]) input |= FORTH; - if (Input::state[pid][cRight]) input |= RIGHT; - if (Input::state[pid][cDown]) input |= BACK; - if (Input::state[pid][cLeft]) input |= LEFT; - } + if (Input::state[pid][cUp]) input |= FORTH; + if (Input::state[pid][cRight]) input |= RIGHT; + if (Input::state[pid][cDown]) input |= BACK; + if (Input::state[pid][cLeft]) input |= LEFT; if (Input::state[pid][cRoll]) input = FORTH | BACK; - //if (Input::state[pid][cStepRight]) input = WALK | RIGHT; - //if (Input::state[pid][cStepLeft]) input = WALK | LEFT; if (Input::state[pid][cJump]) input |= JUMP; if (Input::state[pid][cWalk]) input |= WALK; if (Input::state[pid][cAction]) input |= ACTION; if (Input::state[pid][cWeapon]) input |= WEAPON; + if (Input::state[pid][cLook] && canLookAt()) input = LOOK; + //if (Input::state[pid][cStepRight]) input = WALK | RIGHT; + //if (Input::state[pid][cStepLeft]) input = WALK | LEFT; // scion debug (TODO: remove) if (Input::down[ikP]) { @@ -2791,13 +2792,8 @@ struct Lara : Character { } virtual void update() { - if ((Input::state[camera->cameraIndex][cLook]) && (Input::state[camera->cameraIndex][cAction])) { - if (!camChanged) { - camera->changeView(!camera->firstPerson); - camChanged = true; - } - } else - camChanged = false; + if (Input::state[camera->cameraIndex][cLook] && Input::lastState[camera->cameraIndex] == cAction) + camera->changeView(!camera->firstPerson); if (level->isCutsceneLevel()) { updateAnimation(true); @@ -2839,8 +2835,11 @@ struct Lara : Character { usedKey = TR::Entity::LARA; - if (camera->mode != Camera::MODE_CUTSCENE && camera->mode != Camera::MODE_STATIC) + if (camera->mode != Camera::MODE_CUTSCENE && camera->mode != Camera::MODE_STATIC) { camera->mode = (emptyHands() || health <= 0.0f) ? Camera::MODE_FOLLOW : Camera::MODE_COMBAT; + if (input & LOOK) + camera->mode = Camera::MODE_LOOK; + } if (keyItem) { keyItem->flags.invisible = animation.frameIndex < (state == STATE_USE_KEY ? 70 : 30);