1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-04-20 11:02:18 +02:00

fix camera logic (at LEVEL6 start)

This commit is contained in:
XProger 2019-06-23 02:27:45 +03:00
parent 18386a1d35
commit 1b2f3170b2
4 changed files with 136 additions and 83 deletions

View File

@ -36,6 +36,7 @@ struct Camera : ICamera {
int viewIndex;
int viewIndexLast;
Controller* viewTarget;
Controller* viewTargetLast;
Basis fpHead;
int speed;
bool smooth;
@ -97,9 +98,21 @@ struct Camera : ICamera {
return level->rooms[getRoomIndex()].flags.water;
}
vec3 getViewPoint() {
vec3 getViewPoint(bool useBounds = true) {
Box box = owner->getBoundingBox();
vec3 pos = owner->pos;
if (!useBounds) {
if (owner->getEntity().type == TR::Entity::LARA &&
owner->stand != Character::STAND_UNDERWATER &&
owner->stand != Character::STAND_ONWATER)
{
pos.y -= 512.0f;
}
return pos;
}
vec3 center = box.center();
if (centerView) {
@ -107,41 +120,27 @@ struct Camera : ICamera {
pos.z = center.z;
}
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->getEntity().type == TR::Entity::LARA) {
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;
}
} else {
pos.y = center.y;
}
return pos;
}
void setView(int viewIndex, float timer, int speed) {
viewIndexLast = viewIndex;
smooth = speed > 0;
mode = MODE_STATIC;
this->viewIndex = viewIndex;
this->timer = timer;
this->speed = speed * 8;
}
void resetTarget() {
smooth = speed > 0;
mode = MODE_FOLLOW;
viewIndex = -1;
viewTarget = NULL;
timer = -1.0f;
speed = CAM_SPEED_FOLLOW;
}
virtual void doCutscene(const vec3 &pos, float rotation) {
mode = Camera::MODE_CUTSCENE;
level->cutMatrix.identity();
@ -334,6 +333,14 @@ struct Camera : ICamera {
Input::setJoyVibration(cameraIndex, clamp(shake, 0.0f, 1.0f), 0);
}
if (mode == MODE_FOLLOW) {
speed = CAM_SPEED_FOLLOW;
}
if (mode == MODE_COMBAT) {
speed = CAM_SPEED_COMBAT;
}
if (mode == MODE_CUTSCENE) {
ASSERT(level->cameraFramesCount && level->cameraFrames);
@ -437,19 +444,13 @@ struct Camera : ICamera {
targetAngle += angle;
}
if (!firstPerson || viewIndex != -1) {
if (timer > 0.0f) {
timer -= Core::deltaTime;
if (timer <= 0.0f) {
resetTarget();
}
}
bool isStatic = (mode == MODE_STATIC || mode == MODE_HEAVY) && viewTarget;
if (!firstPerson || isStatic) {
TR::Location to;
target.box = TR::NO_BOX;
if (viewIndex > -1) {
if (mode == MODE_STATIC && viewIndex > -1) {
TR::Camera &cam = level->cameras[viewIndex];
to.room = cam.room;
to.pos = vec3(float(cam.x), float(cam.y), float(cam.z));
@ -458,8 +459,7 @@ struct Camera : ICamera {
target.pos = lookAt->getBoundingBox().center();
} else {
target.room = owner->getRoomIndex();
target.pos = owner->pos;
target.pos.y -= 512.0f;
target.pos = getViewPoint(false);
}
} else {
vec3 p = getViewPoint();
@ -486,9 +486,6 @@ struct Camera : ICamera {
move(to);
if (timer <= 0.0f)
resetTarget();
mViewInv = mat4(eye.pos, target.pos, vec3(0, -1, 0));
} else
updateFirstPerson();
@ -502,6 +499,23 @@ struct Camera : ICamera {
updateListener(mViewInv);
smooth = true;
viewIndexLast = viewIndex;
if ((mode == MODE_STATIC || mode == MODE_HEAVY) && timer != 0.0f) {
timer -= Core::deltaTime;
if (timer <= 0.0f) {
timer = -1.0f;
smooth = false;
}
}
if (mode != MODE_HEAVY || timer == -1.0f) {
mode = MODE_FOLLOW;
viewIndex = -1;
viewTargetLast = viewTarget;
viewTarget = NULL;
}
}
virtual void setup(bool calcMatrices) {

View File

@ -1930,6 +1930,53 @@ struct Lara : Character {
return false;
}
void refreshCamera(const TR::Level::FloorInfo &info) {
const TR::FloorData::TriggerCommand *cameraCmdSwitch = NULL;
const TR::FloorData::TriggerCommand *cameraCmdTarget = NULL;
int cmdIndex = 0;
while (cmdIndex < info.trigCmdCount) {
const TR::FloorData::TriggerCommand &cmd = info.trigCmd[cmdIndex++];
switch (cmd.action) {
case TR::Action::CAMERA_SWITCH :
ASSERT(!cameraCmdSwitch);
cameraCmdSwitch = &cmd;
cmdIndex++; // skip camera info cmd
break;
case TR::Action::CAMERA_TARGET :
ASSERT(!cameraCmdTarget);
cameraCmdTarget = &cmd;
break;
default : ;
}
}
if (cameraCmdTarget && camera->mode != Camera::MODE_LOOK && camera->mode != Camera::MODE_COMBAT) {
camera->viewTarget = (Controller*)level->entities[cameraCmdTarget->args].controller;
}
if (cameraCmdSwitch) {
if (cameraCmdSwitch->args == camera->viewIndexLast) {
camera->viewIndex = camera->viewIndexLast;
if (camera->mode == Camera::MODE_LOOK || camera->mode == Camera::MODE_COMBAT || camera->timer < 0) {
camera->timer = -1.0f;
camera->viewTarget = NULL;
} else {
camera->mode = Camera::MODE_STATIC;
}
} else {
camera->viewTarget = NULL;
}
} else {
if (viewTarget && camera->viewTarget != camera->viewTargetLast) {
camera->viewTarget = NULL;
}
}
}
void checkTrigger(Controller *controller, bool heavy) {
TR::Level::FloorInfo info;
getFloorInfo(controller->getRoomIndex(), controller->pos, info);
@ -1941,6 +1988,10 @@ struct Lara : Character {
if (!info.trigCmdCount) return; // has no trigger
if (camera->mode != Camera::MODE_HEAVY) {
refreshCamera(info);
}
TR::Limits::Limit *limit = NULL;
bool switchIsDown = false;
float timer = info.trigInfo.timer == 1 ? EPS : float(info.trigInfo.timer);
@ -2050,9 +2101,6 @@ struct Lara : Character {
bool needFlip = false;
TR::Effect::Type effect = TR::Effect::NONE;
int cameraIndex = -1;
Controller *cameraTarget = NULL;
while (cmdIndex < info.trigCmdCount) {
TR::FloorData::TriggerCommand &cmd = info.trigCmd[cmdIndex++];
@ -2084,20 +2132,22 @@ struct Lara : Character {
}
case TR::Action::CAMERA_SWITCH : {
TR::FloorData::TriggerCommand &cam = info.trigCmd[cmdIndex++];
if (level->cameras[cmd.args].flags.once)
break;
if (info.trigger == TR::Level::Trigger::COMBAT)
break;
if (info.trigger == TR::Level::Trigger::SWITCH && info.trigInfo.timer && !switchIsDown)
break;
if (info.trigger == TR::Level::Trigger::SWITCH || cmd.args != camera->viewIndexLast) {
level->cameras[cmd.args].flags.once |= cam.once;
camera->setView(cmd.args, cam.timer == 1 ? EPS : float(cam.timer), cam.speed);
cameraIndex = cmd.args;
if (!level->cameras[cmd.args].flags.once) {
camera->viewIndex = cmd.args;
if (!(info.trigger == TR::Level::Trigger::COMBAT) &&
!(info.trigger == TR::Level::Trigger::SWITCH && info.trigInfo.timer && !switchIsDown) &&
(info.trigger == TR::Level::Trigger::SWITCH || camera->viewIndex != camera->viewIndexLast))
{
camera->smooth = cam.speed > 0;
camera->mode = heavy ? Camera::MODE_HEAVY : Camera::MODE_STATIC;
camera->timer = cam.timer == 1 ? EPS : float(cam.timer);
camera->speed = cam.speed * 8;
level->cameras[camera->viewIndex].flags.once |= cam.once;
}
}
break;
}
case TR::Action::FLOW :
@ -2131,7 +2181,9 @@ struct Lara : Character {
needFlip = true;
break;
case TR::Action::CAMERA_TARGET :
cameraTarget = (Controller*)level->entities[cmd.args].controller;
if (camera->mode == Camera::MODE_STATIC || camera->mode == Camera::MODE_HEAVY) {
camera->viewTarget = (Controller*)level->entities[cmd.args].controller;
}
break;
case TR::Action::END :
game->loadNextLevel();
@ -2175,12 +2227,6 @@ struct Lara : Character {
}
}
if (cameraTarget && (camera->mode == Camera::MODE_STATIC || cameraIndex == -1))
camera->viewTarget = cameraTarget;
if (!cameraTarget && cameraIndex > -1)
camera->viewIndex = cameraIndex;
if (needFlip) {
game->flipMap();
game->setEffect(this, effect);

View File

@ -3107,8 +3107,7 @@ struct Level : IGame {
Core::pushLights();
UI::begin();
UI::updateAspect(camera->aspect);
UI::begin(camera->aspect);
atlasObjects->bind(sDiffuse);
UI::renderPickups();
@ -3175,8 +3174,7 @@ struct Level : IGame {
inventory->render(1.0);
if (UI::subsStr != STR_EMPTY) {
UI::begin();
UI::updateAspect(float(Core::width) / float(Core::height));
UI::begin(float(Core::width) / float(Core::height));
atlasGlyphs->bind(sDiffuse);
UI::renderSubs();
UI::end();
@ -3191,8 +3189,7 @@ struct Level : IGame {
atlasObjects->bind(sDiffuse);
inventory->render(aspect);
UI::begin();
UI::updateAspect(aspect);
UI::begin(aspect);
atlasGlyphs->bind(sDiffuse);
if (!inventory->video) {
inventory->renderUI();
@ -3207,8 +3204,7 @@ struct Level : IGame {
void render() {
if (isEnded && !inventory->video) {
Core::setTarget(NULL, NULL, RT_CLEAR_COLOR | RT_STORE_COLOR);
UI::begin();
UI::updateAspect(float(Core::width) / float(Core::height));
UI::begin(float(Core::width) / float(Core::height));
atlasGlyphs->bind(sDiffuse);
UI::textOut(vec2(0, 480 - 16), STR_LOADING, UI::aCenter, UI::width);
UI::end();

View File

@ -257,16 +257,16 @@ namespace UI {
uint16 curTile, curClut;
#endif
void updateAspect(float aspect) {
void begin(float aspect) {
ensureLanguage(Core::settings.audio.language);
height = 480.0f;
width = height * aspect;
Core::mModel.identity();
Core::mView.identity();
Core::mProj = GAPI::ortho(0.0f, width, height, 0.0f, -128.0f, 127.0f);
Core::setViewProj(Core::mView, Core::mProj);
Core::active.shader->setParam(uViewProj, Core::mViewProj);
}
void begin() {
ensureLanguage(Core::settings.audio.language);
Core::setDepthTest(false);
Core::setDepthWrite(false);
@ -274,9 +274,6 @@ namespace UI {
Core::setCullMode(cmNone);
game->setupBinding();
Core::mView.identity();
Core::mModel.identity();
game->setShader(Core::passGUI, Shader::DEFAULT);
Core::setMaterial(1, 1, 1, 1);