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

View File

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

View File

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

View File

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