1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-15 17:44:25 +02:00
This commit is contained in:
XProger
2018-07-23 05:56:45 +03:00
parent 852e0eab02
commit 1773dd90c9
4 changed files with 123 additions and 107 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);