refactor: Update visiblity per frame in a centralized fashion

This commit is contained in:
Vsevolod Kremianskii 2020-10-28 13:00:47 +07:00
parent bd41f7c9a2
commit 139b5656e2
6 changed files with 76 additions and 50 deletions

View file

@ -22,6 +22,7 @@
#include <boost/format.hpp>
#include "glm/gtx/intersect.hpp"
#include "glm/gtx/norm.hpp"
#include "../../render/models.h"
#include "../../render/walkmeshes.h"
@ -451,18 +452,21 @@ bool Area::getElevationAt(const glm::vec2 &position, Room *&room, float &z) cons
}
void Area::update(const UpdateContext &updateCtx) {
Object::update(updateCtx);
_actionExecutor.executeActions(*this, updateCtx.deltaTime);
for (auto &room : _rooms) {
room.second->update(updateCtx.deltaTime);
}
for (auto &object : _objects) {
object->update(updateCtx);
_actionExecutor.executeActions(*object, updateCtx.deltaTime);
}
doDestroyObjects();
float dt = updateCtx.deltaTime;
Object::update(dt);
_actionExecutor.executeActions(*this, dt);
for (auto &room : _rooms) {
room.second->update(dt);
}
updateVisibility(updateCtx);
for (auto &object : _objects) {
object->update(dt);
_actionExecutor.executeActions(*object, dt);
}
_objectSelector.update();
_game->sceneGraph().prepare();
}
@ -617,7 +621,6 @@ void Area::onPartyLeaderMoved() {
if (!partyLeader) return;
update3rdPersonCameraTarget();
updateRoomVisibility();
_objectSelector.selectNearest();
updateTriggers(*partyLeader);
}
@ -636,24 +639,52 @@ void Area::update3rdPersonCameraTarget() {
_thirdPersonCamera->setTargetPosition(position);
}
void Area::updateRoomVisibility() {
void Area::updateVisibility(const UpdateContext &ctx) {
shared_ptr<Creature> partyLeader(_game->party().leader());
if (!partyLeader) return;
Room *leaderRoom = partyLeader ? partyLeader->room() : nullptr;
bool allVisible = !leaderRoom || _cameraType == CameraType::FirstPerson;
Room *leaderRoom = partyLeader->room();
if (!leaderRoom) return;
for (auto &room : _rooms) {
room.second->setVisible(false);
}
leaderRoom->setVisible(true);
auto adjRooms = _visibility->equal_range(leaderRoom->name());
for (auto adjRoom = adjRooms.first; adjRoom != adjRooms.second; adjRoom++) {
auto room = _rooms.find(adjRoom->second);
if (room != _rooms.end()) {
room->second->setVisible(true);
if (allVisible) {
for (auto &room : _rooms) {
room.second->setVisible(true);
}
} else {
auto adjRoomNames = _visibility->equal_range(leaderRoom->name());
for (auto &room : _rooms) {
bool visible = !leaderRoom || room.second.get() == leaderRoom;
if (!visible) {
for (auto adjRoom = adjRoomNames.first; adjRoom != adjRoomNames.second; adjRoom++) {
if (adjRoom->second == room.first) {
visible = true;
break;
}
}
}
room.second->setVisible(visible);
}
}
glm::vec4 viewport(-1.0f, -1.0f, 1.0f, 1.0f);
for (auto &object : _objects) {
if (!object->visible()) continue;
shared_ptr<ModelSceneNode> model(object->model());
if (!model) continue;
glm::vec3 position(object->position());
float drawDistance = object->drawDistance();
float fadeDistance = object->fadeDistance();
glm::vec3 screenCoords = glm::project(position, ctx.view, ctx.projection, viewport);
float distanceToCamera = glm::distance2(position, ctx.cameraPosition);
bool onScreen = distanceToCamera < drawDistance && screenCoords.z < 1.0f;
float alpha = 1.0f;
if (drawDistance != fadeDistance && distanceToCamera > fadeDistance) {
alpha = 1.0f - (distanceToCamera - fadeDistance) / (drawDistance - fadeDistance);
}
model->setOnScreen(onScreen);
model->setAlpha(alpha);
}
}

View file

@ -61,6 +61,7 @@ public:
Area(uint32_t id, Game *game);
void load(const std::string &name, const resource::GffStruct &are, const resource::GffStruct &git);
bool handle(const SDL_Event &event);
void update(const UpdateContext &updateCtx);
@ -144,8 +145,8 @@ private:
void doDestroyObject(uint32_t objectId);
void doDestroyObjects();
void landObject(SpatialObject &object);
void updateRoomVisibility();
void updateTriggers(const Creature &creature);
void updateVisibility(const UpdateContext &ctx);
bool findCameraObstacle(const glm::vec3 &origin, const glm::vec3 &dest, glm::vec3 &intersection) const;
bool findCreatureObstacle(const Creature &creature, const glm::vec3 &dest) const;

View file

@ -23,8 +23,6 @@
using namespace std;
using namespace reone::render;
using namespace reone::resource;
using namespace reone::script;
namespace reone {
@ -34,7 +32,7 @@ namespace game {
Object::Object(uint32_t id, ObjectType type) : _id(id), _type(type) {
}
void Object::update(const UpdateContext &ctx) {
void Object::update(float dt) {
_actionQueue.update();
}

View file

@ -22,7 +22,6 @@
#include <unordered_map>
#include "../actionqueue.h"
#include "../types.h"
#include "types.h"
@ -34,7 +33,7 @@ class Object {
public:
virtual ~Object() = default;
virtual void update(const UpdateContext &ctx);
virtual void update(float dt);
void runUserDefinedEvent(int eventNumber);

View file

@ -18,7 +18,6 @@
#include "spatial.h"
#include "glm/gtx/euler_angles.hpp"
#include "glm/gtx/norm.hpp"
#include "../room.h"
@ -66,23 +65,11 @@ void SpatialObject::moveItemsTo(SpatialObject &other) {
_items.clear();
}
void SpatialObject::update(const UpdateContext &ctx) {
Object::update(ctx);
if (!_model) return;
glm::vec4 viewport(-1.0f, -1.0f, 1.0f, 1.0f);
glm::vec3 screenCoords = glm::project(_position, ctx.view, ctx.projection, viewport);
float distanceToCamera = glm::distance2(_position, ctx.cameraPosition);
bool onScreen = distanceToCamera < _drawDistance && screenCoords.z < 1.0f;
float alpha = 1.0f;
if (_drawDistance != _fadeDistance && distanceToCamera > _fadeDistance) {
alpha = 1.0f - (distanceToCamera - _fadeDistance) / (_drawDistance - _fadeDistance);
void SpatialObject::update(float dt) {
Object::update(dt);
if (_model) {
_model->update(dt);
}
_model->setOnScreen(onScreen);
_model->setAlpha(alpha);
_model->update(ctx.deltaTime);
}
void SpatialObject::playAnimation(const string &name, int flags, float speed) {
@ -131,6 +118,14 @@ glm::vec3 SpatialObject::selectablePosition() const {
return _model->getCenterOfAABB();
}
float SpatialObject::drawDistance() const {
return _drawDistance;
}
float SpatialObject::fadeDistance() const {
return _fadeDistance;
}
void SpatialObject::setRoom(Room *room) {
if (_room) {
_room->removeTenant(this);

View file

@ -40,7 +40,7 @@ class Room;
class SpatialObject : public Object {
public:
void update(const UpdateContext &ctx) override;
void update(float dt) override;
virtual void playAnimation(const std::string &name, int flags = 0, float speed = 1.0f);
@ -62,6 +62,8 @@ public:
std::shared_ptr<render::Walkmesh> walkmesh() const;
const std::vector<std::shared_ptr<Item>> &items() const;
virtual glm::vec3 selectablePosition() const;
float drawDistance() const;
float fadeDistance() const;
void setRoom(Room *room);
void setPosition(const glm::vec3 &position);