mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-18 16:32:32 +02:00
Refactor and cleanup camera control.
rwengine + Make renderWorld() take a ViewCamera parameter. + add rotation and getView to ViewCamera + correct directions for vehicle and character movement. rwgame + Remove GenericState + Add State::getCamera() to control the ViewCamera used for rendering + Clean up state camera control + Remove now unused view parameters from main
This commit is contained in:
parent
095073e667
commit
ba7eb63941
@ -66,6 +66,9 @@ struct GameState
|
|||||||
TextDisplayData nextText;
|
TextDisplayData nextText;
|
||||||
std::vector<TextDisplayData> texts;
|
std::vector<TextDisplayData> texts;
|
||||||
|
|
||||||
|
/** The camera near value currently set by the script */
|
||||||
|
float cameraNear;
|
||||||
|
|
||||||
GameState() :
|
GameState() :
|
||||||
maxProgress(1),
|
maxProgress(1),
|
||||||
numMissions(0),
|
numMissions(0),
|
||||||
@ -88,7 +91,8 @@ struct GameState
|
|||||||
minute(0),
|
minute(0),
|
||||||
osTextStyle(0),
|
osTextStyle(0),
|
||||||
osTextStart(0.f),
|
osTextStart(0.f),
|
||||||
osTextTime(0.f)
|
osTextTime(0.f),
|
||||||
|
cameraNear(0.1f)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -134,12 +134,13 @@ private:
|
|||||||
/** Particles in flight */
|
/** Particles in flight */
|
||||||
std::vector<FXParticle> _particles;
|
std::vector<FXParticle> _particles;
|
||||||
|
|
||||||
|
/** Camera values passed to renderWorld() */
|
||||||
|
ViewCamera _camera;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
GameRenderer(GameWorld*);
|
GameRenderer(GameWorld*);
|
||||||
|
|
||||||
ViewCamera camera;
|
|
||||||
|
|
||||||
/** Number of issued draw calls */
|
/** Number of issued draw calls */
|
||||||
size_t rendered;
|
size_t rendered;
|
||||||
/** Number of culling events */
|
/** Number of culling events */
|
||||||
@ -165,14 +166,15 @@ public:
|
|||||||
GLuint debugTex;
|
GLuint debugTex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the world:
|
* Renders the world using the parameters of the passed Camera.
|
||||||
|
* Note: The camera's near and far planes are overriden by weather effects.
|
||||||
*
|
*
|
||||||
* - draws all objects (instances, vehicles etc.)
|
* - draws all objects (instances, vehicles etc.)
|
||||||
* - draws particles
|
* - draws particles
|
||||||
* - draws water surfaces
|
* - draws water surfaces
|
||||||
* - draws the skybox
|
* - draws the skybox
|
||||||
*/
|
*/
|
||||||
void renderWorld(float alpha);
|
void renderWorld(const ViewCamera &camera, float alpha);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief draws a CharacterObject and any item they are holding.
|
* @brief draws a CharacterObject and any item they are holding.
|
||||||
|
@ -9,13 +9,23 @@ public:
|
|||||||
|
|
||||||
ViewFrustum frustum;
|
ViewFrustum frustum;
|
||||||
|
|
||||||
glm::vec3 worldPos;
|
glm::vec3 position;
|
||||||
|
glm::quat rotation;
|
||||||
|
|
||||||
ViewCamera()
|
ViewCamera(const glm::vec3& pos = {}, const glm::quat& rot = {})
|
||||||
: frustum({0.1f, 5000.f, (-45.f / 180.f) * 3.1415f, 1.f})
|
: frustum({0.1f, 5000.f, glm::radians(45.f), 1.f}),
|
||||||
|
position(pos), rotation(rot)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::mat4 getView()
|
||||||
|
{
|
||||||
|
auto up = rotation * glm::vec3(0.f, 0.f, 1.f);
|
||||||
|
return glm::lookAt(position,
|
||||||
|
position + rotation * glm::vec3(1.f, 0.f, 0.f),
|
||||||
|
up);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,8 +19,6 @@ public:
|
|||||||
float fov;
|
float fov;
|
||||||
float aspectRatio;
|
float aspectRatio;
|
||||||
|
|
||||||
glm::mat4 view;
|
|
||||||
|
|
||||||
ViewPlane planes[6];
|
ViewPlane planes[6];
|
||||||
|
|
||||||
ViewFrustum(float near, float far, float fov, float aspect)
|
ViewFrustum(float near, float far, float fov, float aspect)
|
||||||
|
@ -79,10 +79,10 @@ void PlayerController::update(float dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( character->getCurrentVehicle() ) {
|
if( character->getCurrentVehicle() ) {
|
||||||
character->getCurrentVehicle()->setSteeringAngle(_rawDirection.x);
|
character->getCurrentVehicle()->setSteeringAngle(_rawDirection.y);
|
||||||
|
|
||||||
// TODO what is handbraking.
|
// TODO what is handbraking.
|
||||||
character->getCurrentVehicle()->setThrottle(-_rawDirection.y);
|
character->getCurrentVehicle()->setThrottle(_rawDirection.x);
|
||||||
}
|
}
|
||||||
else if( glm::length(direction) > 0.001f ) {
|
else if( glm::length(direction) > 0.001f ) {
|
||||||
character->rotation = cameraRotation * glm::quat(glm::vec3(0.f, 0.f, -atan2(direction.x, direction.y)));
|
character->rotation = cameraRotation * glm::quat(glm::vec3(0.f, 0.f, -atan2(direction.x, direction.y)));
|
||||||
|
@ -310,10 +310,13 @@ float mix(uint8_t a, uint8_t b, float num)
|
|||||||
if(errc != GL_NO_ERROR) std::cout << __LINE__ << ": " << errc << std::endl;\
|
if(errc != GL_NO_ERROR) std::cout << __LINE__ << ": " << errc << std::endl;\
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::renderWorld(float alpha)
|
void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
|
||||||
{
|
{
|
||||||
_renderAlpha = alpha;
|
_renderAlpha = alpha;
|
||||||
|
|
||||||
|
// Store the input camera,
|
||||||
|
_camera = camera;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( vao );
|
||||||
|
|
||||||
float tod = engine->state.hour + engine->state.minute/60.f;
|
float tod = engine->state.hour + engine->state.minute/60.f;
|
||||||
@ -334,12 +337,14 @@ void GameRenderer::renderWorld(float alpha)
|
|||||||
cos(theta),
|
cos(theta),
|
||||||
};
|
};
|
||||||
sunDirection = glm::normalize(sunDirection);
|
sunDirection = glm::normalize(sunDirection);
|
||||||
camera.frustum.far = weather.farClipping;
|
|
||||||
|
_camera.frustum.near = engine->state.cameraNear;
|
||||||
|
_camera.frustum.far = weather.farClipping;
|
||||||
|
|
||||||
glUseProgram(worldProgram);
|
glUseProgram(worldProgram);
|
||||||
|
|
||||||
auto view = camera.frustum.view;
|
auto view = _camera.getView();
|
||||||
auto proj = camera.frustum.projection();
|
auto proj = _camera.frustum.projection();
|
||||||
|
|
||||||
uploadUBO<SceneUniformData>(
|
uploadUBO<SceneUniformData>(
|
||||||
uboScene,
|
uboScene,
|
||||||
@ -349,7 +354,7 @@ void GameRenderer::renderWorld(float alpha)
|
|||||||
glm::vec4{ambient, 0.0f},
|
glm::vec4{ambient, 0.0f},
|
||||||
glm::vec4{dynamic, 0.0f},
|
glm::vec4{dynamic, 0.0f},
|
||||||
glm::vec4(skyBottom, 1.f),
|
glm::vec4(skyBottom, 1.f),
|
||||||
glm::vec4(camera.worldPos, 0.f),
|
glm::vec4(camera.position, 0.f),
|
||||||
weather.fogStart,
|
weather.fogStart,
|
||||||
camera.frustum.far
|
camera.frustum.far
|
||||||
});
|
});
|
||||||
@ -357,7 +362,7 @@ void GameRenderer::renderWorld(float alpha)
|
|||||||
glClearColor(skyBottom.r, skyBottom.g, skyBottom.b, 1.f);
|
glClearColor(skyBottom.r, skyBottom.g, skyBottom.b, 1.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
camera.frustum.update(proj * view);
|
_camera.frustum.update(proj * view);
|
||||||
|
|
||||||
rendered = culled = geoms = frames = 0;
|
rendered = culled = geoms = frames = 0;
|
||||||
|
|
||||||
@ -416,7 +421,7 @@ void GameRenderer::renderWorld(float alpha)
|
|||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, waterTex.texName);
|
glBindTexture(GL_TEXTURE_2D, waterTex.texName);
|
||||||
|
|
||||||
auto camposFlat = glm::vec2(camera.worldPos);
|
auto camposFlat = glm::vec2(camera.position);
|
||||||
|
|
||||||
glBindVertexArray( waterHQDraw.getVAOName() );
|
glBindVertexArray( waterHQDraw.getVAOName() );
|
||||||
|
|
||||||
@ -655,7 +660,7 @@ void GameRenderer::renderInstance(InstanceObject *instance)
|
|||||||
for (size_t g = 0; g < instance->model->model->geometries.size(); g++)
|
for (size_t g = 0; g < instance->model->model->geometries.size(); g++)
|
||||||
{
|
{
|
||||||
RW::BSGeometryBounds& bounds = instance->model->model->geometries[g]->geometryBounds;
|
RW::BSGeometryBounds& bounds = instance->model->model->geometries[g]->geometryBounds;
|
||||||
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - camera.worldPos) - bounds.radius);
|
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - _camera.position) - bounds.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
Model* model = nullptr;
|
Model* model = nullptr;
|
||||||
@ -784,7 +789,7 @@ void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene)
|
|||||||
for (size_t g = 0; g < cutscene->model->model->geometries.size(); g++)
|
for (size_t g = 0; g < cutscene->model->model->geometries.size(); g++)
|
||||||
{
|
{
|
||||||
RW::BSGeometryBounds& bounds = cutscene->model->model->geometries[g]->geometryBounds;
|
RW::BSGeometryBounds& bounds = cutscene->model->model->geometries[g]->geometryBounds;
|
||||||
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - camera.worldPos) - bounds.radius);
|
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - _camera.position) - bounds.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cutscene->getParentActor() ) {
|
if( cutscene->getParentActor() ) {
|
||||||
@ -832,7 +837,7 @@ void GameRenderer::renderWheel(Model* model, const glm::mat4 &matrix, const std:
|
|||||||
|
|
||||||
for( auto& g : firstLod->getGeometries() ) {
|
for( auto& g : firstLod->getGeometries() ) {
|
||||||
RW::BSGeometryBounds& bounds = model->geometries[g]->geometryBounds;
|
RW::BSGeometryBounds& bounds = model->geometries[g]->geometryBounds;
|
||||||
if(! camera.frustum.intersects(bounds.center + glm::vec3(matrix[3]), bounds.radius)) {
|
if(! _camera.frustum.intersects(bounds.center + glm::vec3(matrix[3]), bounds.radius)) {
|
||||||
culled++;
|
culled++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -896,8 +901,8 @@ void GameRenderer::renderParticles()
|
|||||||
glUseProgram( particleProgram );
|
glUseProgram( particleProgram );
|
||||||
glBindVertexArray( particleDraw.getVAOName() );
|
glBindVertexArray( particleDraw.getVAOName() );
|
||||||
|
|
||||||
auto cpos = camera.worldPos;
|
auto cpos = _camera.position;
|
||||||
auto cfwd = glm::normalize(glm::inverse(glm::mat3(camera.frustum.view)) * glm::vec3(0.f, 1.f, 0.f));
|
auto cfwd = glm::normalize(glm::inverse(_camera.rotation) * glm::vec3(0.f, 1.f, 0.f));
|
||||||
|
|
||||||
std::sort( _particles.begin(), _particles.end(),
|
std::sort( _particles.begin(), _particles.end(),
|
||||||
[&](const FXParticle& a, const FXParticle& b) {
|
[&](const FXParticle& a, const FXParticle& b) {
|
||||||
@ -980,7 +985,7 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
|||||||
/// @todo fix culling animating objects?
|
/// @todo fix culling animating objects?
|
||||||
|
|
||||||
glm::vec3 boundpos = bounds.center + glm::vec3(matrix[3]);
|
glm::vec3 boundpos = bounds.center + glm::vec3(matrix[3]);
|
||||||
if( (!object || !object->animator) && ! camera.frustum.intersects(boundpos, bounds.radius)) {
|
if( (!object || !object->animator) && ! _camera.frustum.intersects(boundpos, bounds.radius)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +608,7 @@ VM_OPCODE_DEF( 0x0408 )
|
|||||||
|
|
||||||
VM_OPCODE_DEF( 0x041D )
|
VM_OPCODE_DEF( 0x041D )
|
||||||
{
|
{
|
||||||
m->getWorld()->renderer.camera.frustum.near = p->at(0).real;
|
m->getWorld()->state.cameraNear = p->at(0).real;
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_OPCODE_DEF( 0x042C )
|
VM_OPCODE_DEF( 0x042C )
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
add_executable(rwgame
|
add_executable(rwgame
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
|
State.cpp
|
||||||
|
|
||||||
loadingstate.cpp
|
loadingstate.cpp
|
||||||
ingamestate.cpp
|
ingamestate.cpp
|
||||||
pausestate.cpp
|
pausestate.cpp
|
||||||
|
9
rwgame/State.cpp
Normal file
9
rwgame/State.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "State.hpp"
|
||||||
|
|
||||||
|
// This serves as the "initial" camera position.
|
||||||
|
ViewCamera defaultView({-250.f, -550.f, 75.f}, glm::angleAxis(glm::radians(5.f), glm::vec3(0.f, 1.f, 0.f)));
|
||||||
|
|
||||||
|
const ViewCamera& State::getCamera()
|
||||||
|
{
|
||||||
|
return defaultView;
|
||||||
|
}
|
@ -3,7 +3,9 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <SFML/Graphics/RenderWindow.hpp>
|
#include <SFML/Graphics/RenderWindow.hpp>
|
||||||
|
#include <render/ViewCamera.hpp>
|
||||||
#include "MenuSystem.hpp"
|
#include "MenuSystem.hpp"
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
@ -76,32 +78,8 @@ struct State
|
|||||||
default: break;
|
default: break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct GenericState : public State
|
virtual const ViewCamera& getCamera();
|
||||||
{
|
|
||||||
typedef std::function<void (State*)> StateChange;
|
|
||||||
typedef std::function<void (State*, float)> Tick;
|
|
||||||
typedef std::function<void (State*, const sf::Event&)> Event;
|
|
||||||
|
|
||||||
StateChange enter_lambda;
|
|
||||||
Tick tick_lambda;
|
|
||||||
StateChange exit_lambda;
|
|
||||||
Event event_lambda;
|
|
||||||
|
|
||||||
GenericState(StateChange start, Tick think, StateChange end, Event event)
|
|
||||||
: enter_lambda(start), tick_lambda(think),
|
|
||||||
exit_lambda(end), event_lambda(event) {}
|
|
||||||
|
|
||||||
virtual void enter() { enter_lambda(this); }
|
|
||||||
virtual void exit() { exit_lambda(this); }
|
|
||||||
|
|
||||||
virtual void tick(float dt) { tick_lambda(this, dt); }
|
|
||||||
|
|
||||||
virtual void handleEvent(const sf::Event& event) {
|
|
||||||
event_lambda(this, event);
|
|
||||||
State::handleEvent(event);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StateManager
|
struct StateManager
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include "debugstate.hpp"
|
#include "debugstate.hpp"
|
||||||
#include "game.hpp"
|
#include "game.hpp"
|
||||||
|
#include <ai/PlayerController.hpp>
|
||||||
#include <objects/CharacterObject.hpp>
|
#include <objects/CharacterObject.hpp>
|
||||||
#include <objects/VehicleObject.hpp>
|
#include <objects/VehicleObject.hpp>
|
||||||
|
|
||||||
DebugState::DebugState()
|
DebugState::DebugState(const glm::vec3& vp, const glm::quat& vd)
|
||||||
: _freeLook( false ), _sonicMode( false )
|
: _freeLook( false ), _sonicMode( false )
|
||||||
{
|
{
|
||||||
Menu *m = new Menu(getFont());
|
Menu *m = new Menu(getFont());
|
||||||
@ -18,7 +19,7 @@ DebugState::DebugState()
|
|||||||
spawnVehicle(it->first);
|
spawnVehicle(it->first);
|
||||||
}, entryHeight));
|
}, entryHeight));
|
||||||
m->addEntry(Menu::lambda("Open All Doors/Flaps", [this] {
|
m->addEntry(Menu::lambda("Open All Doors/Flaps", [this] {
|
||||||
auto pc = getPlayerCharacter();
|
auto pc = getWorld()->state.player->getCharacter();
|
||||||
auto pv = pc->getCurrentVehicle();
|
auto pv = pc->getCurrentVehicle();
|
||||||
if( pv ) {
|
if( pv ) {
|
||||||
for(auto& it : pv->_hingedObjects) {
|
for(auto& it : pv->_hingedObjects) {
|
||||||
@ -51,12 +52,12 @@ DebugState::DebugState()
|
|||||||
}
|
}
|
||||||
this->enterMenu(m);
|
this->enterMenu(m);
|
||||||
|
|
||||||
|
_debugCam.position = vp;
|
||||||
|
_debugCam.rotation = vd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugState::enter()
|
void DebugState::enter()
|
||||||
{
|
{
|
||||||
_debugPos = getViewPosition();
|
|
||||||
_debugAngles = getViewAngles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugState::exit()
|
void DebugState::exit()
|
||||||
@ -102,21 +103,19 @@ void DebugState::tick(float dt)
|
|||||||
sf::Vector2i deltaMouse = mousePos - screenCenter;
|
sf::Vector2i deltaMouse = mousePos - screenCenter;
|
||||||
sf::Mouse::setPosition(screenCenter, getWindow());
|
sf::Mouse::setPosition(screenCenter, getWindow());
|
||||||
|
|
||||||
_debugAngles.x += deltaMouse.x / 100.0;
|
_debugLook.x -= deltaMouse.x / 100.0f;
|
||||||
_debugAngles.y += deltaMouse.y / 100.0;
|
_debugLook.y += deltaMouse.y / 100.0f;
|
||||||
|
|
||||||
if (_debugAngles.y > qpi)
|
if (_debugLook.y > qpi)
|
||||||
_debugAngles.y = qpi;
|
_debugLook.y = qpi;
|
||||||
else if (_debugAngles.y < -qpi)
|
else if (_debugLook.y < -qpi)
|
||||||
_debugAngles.y = -qpi;
|
_debugLook.y = -qpi;
|
||||||
|
|
||||||
glm::quat vR = glm::normalize(glm::angleAxis(_debugAngles.x, glm::vec3{0.f, 0.f, 1.f}));
|
_debugCam.rotation = glm::angleAxis(_debugLook.x, glm::vec3(0.f, 0.f, 1.f))
|
||||||
vR = vR * glm::angleAxis(_debugAngles.y, glm::vec3(1.f, 0.f, 0.f));
|
* glm::angleAxis(_debugLook.y, glm::vec3(0.f, 1.f, 0.f));
|
||||||
|
|
||||||
_debugPos += vR * _movement * dt * (_sonicMode ? 100.f : 10.f);
|
_debugCam.position += _debugCam.rotation * _movement * dt * (_sonicMode ? 100.f : 10.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
setViewParameters( _debugPos, _debugAngles );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugState::handleEvent(const sf::Event &e)
|
void DebugState::handleEvent(const sf::Event &e)
|
||||||
@ -129,17 +128,17 @@ void DebugState::handleEvent(const sf::Event &e)
|
|||||||
StateManager::get().exit();
|
StateManager::get().exit();
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::W:
|
case sf::Keyboard::W:
|
||||||
_movement.y =-1.f;
|
|
||||||
break;
|
|
||||||
case sf::Keyboard::S:
|
|
||||||
_movement.y = 1.f;
|
|
||||||
break;
|
|
||||||
case sf::Keyboard::A:
|
|
||||||
_movement.x = 1.f;
|
_movement.x = 1.f;
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::D:
|
case sf::Keyboard::S:
|
||||||
_movement.x =-1.f;
|
_movement.x =-1.f;
|
||||||
break;
|
break;
|
||||||
|
case sf::Keyboard::A:
|
||||||
|
_movement.y = 1.f;
|
||||||
|
break;
|
||||||
|
case sf::Keyboard::D:
|
||||||
|
_movement.y =-1.f;
|
||||||
|
break;
|
||||||
case sf::Keyboard::F:
|
case sf::Keyboard::F:
|
||||||
_freeLook = !_freeLook;
|
_freeLook = !_freeLook;
|
||||||
break;
|
break;
|
||||||
@ -152,11 +151,11 @@ void DebugState::handleEvent(const sf::Event &e)
|
|||||||
switch(e.key.code) {
|
switch(e.key.code) {
|
||||||
case sf::Keyboard::W:
|
case sf::Keyboard::W:
|
||||||
case sf::Keyboard::S:
|
case sf::Keyboard::S:
|
||||||
_movement.y = 0.f;
|
_movement.x = 0.f;
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::A:
|
case sf::Keyboard::A:
|
||||||
case sf::Keyboard::D:
|
case sf::Keyboard::D:
|
||||||
_movement.x = 0.f;
|
_movement.y = 0.f;
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::LShift:
|
case sf::Keyboard::LShift:
|
||||||
_sonicMode = false;
|
_sonicMode = false;
|
||||||
@ -170,7 +169,7 @@ void DebugState::handleEvent(const sf::Event &e)
|
|||||||
|
|
||||||
void DebugState::spawnVehicle(unsigned int id)
|
void DebugState::spawnVehicle(unsigned int id)
|
||||||
{
|
{
|
||||||
auto ch = getPlayerCharacter();
|
auto ch = getWorld()->state.player->getCharacter();
|
||||||
if(! ch) return;
|
if(! ch) return;
|
||||||
|
|
||||||
glm::vec3 fwd = ch->rotation * glm::vec3(0.f, 1.f, 0.f);
|
glm::vec3 fwd = ch->rotation * glm::vec3(0.f, 1.f, 0.f);
|
||||||
@ -181,3 +180,8 @@ void DebugState::spawnVehicle(unsigned int id)
|
|||||||
getWorld()->createVehicle(id, spawnpos, glm::quat());
|
getWorld()->createVehicle(id, spawnpos, glm::quat());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ViewCamera &DebugState::getCamera()
|
||||||
|
{
|
||||||
|
return _debugCam;
|
||||||
|
}
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
class DebugState : public State
|
class DebugState : public State
|
||||||
{
|
{
|
||||||
glm::vec3 _debugPos;
|
ViewCamera _debugCam;
|
||||||
glm::vec3 _movement;
|
glm::vec3 _movement;
|
||||||
glm::vec2 _debugAngles;
|
glm::vec2 _debugLook;
|
||||||
bool _freeLook;
|
bool _freeLook;
|
||||||
bool _sonicMode;
|
bool _sonicMode;
|
||||||
public:
|
public:
|
||||||
DebugState();
|
DebugState(const glm::vec3& vp = {}, const glm::quat& vd = {});
|
||||||
|
|
||||||
virtual void enter();
|
virtual void enter();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
@ -21,6 +21,8 @@ public:
|
|||||||
virtual void handleEvent(const sf::Event& event);
|
virtual void handleEvent(const sf::Event& event);
|
||||||
|
|
||||||
void spawnVehicle(unsigned int id);
|
void spawnVehicle(unsigned int id);
|
||||||
|
|
||||||
|
const ViewCamera& getCamera();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DEBUGSTATE_HPP
|
#endif // DEBUGSTATE_HPP
|
||||||
|
@ -18,19 +18,9 @@ bool hitWorldRay(const glm::vec3& start, const glm::vec3& direction,
|
|||||||
sf::Window& getWindow();
|
sf::Window& getWindow();
|
||||||
|
|
||||||
GameWorld* getWorld();
|
GameWorld* getWorld();
|
||||||
CharacterObject* getPlayerCharacter();
|
|
||||||
void setPlayerCharacter(CharacterObject* playerCharacter);
|
|
||||||
|
|
||||||
sf::Font& getFont();
|
sf::Font& getFont();
|
||||||
|
|
||||||
/**
|
|
||||||
Set view parameters.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void setViewParameters(const glm::vec3& center, const glm::vec2 &angles);
|
|
||||||
glm::vec3& getViewPosition();
|
|
||||||
glm::vec2& getViewAngles();
|
|
||||||
|
|
||||||
void skipTime(float time);
|
void skipTime(float time);
|
||||||
|
|
||||||
#endif // GAME_HPP
|
#endif // GAME_HPP
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "game.hpp"
|
#include "game.hpp"
|
||||||
#include "pausestate.hpp"
|
#include "pausestate.hpp"
|
||||||
#include "debugstate.hpp"
|
#include "debugstate.hpp"
|
||||||
|
|
||||||
|
#include <ai/PlayerController.hpp>
|
||||||
#include <objects/CharacterObject.hpp>
|
#include <objects/CharacterObject.hpp>
|
||||||
#include <objects/VehicleObject.hpp>
|
#include <objects/VehicleObject.hpp>
|
||||||
#include <objects/ItemPickup.hpp>
|
#include <objects/ItemPickup.hpp>
|
||||||
@ -9,7 +11,6 @@
|
|||||||
#include <items/WeaponItem.hpp>
|
#include <items/WeaponItem.hpp>
|
||||||
|
|
||||||
IngameState::IngameState(bool test)
|
IngameState::IngameState(bool test)
|
||||||
: _player(nullptr), _playerCharacter(nullptr)
|
|
||||||
{
|
{
|
||||||
if( test ) {
|
if( test ) {
|
||||||
startTest();
|
startTest();
|
||||||
@ -21,10 +22,10 @@ IngameState::IngameState(bool test)
|
|||||||
|
|
||||||
void IngameState::startTest()
|
void IngameState::startTest()
|
||||||
{
|
{
|
||||||
_playerCharacter = getWorld()->createPedestrian(1, {-1000.f, -990.f, 13.f});
|
auto playerChar = getWorld()->createPedestrian(1, {-1000.f, -990.f, 13.f});
|
||||||
_player = new PlayerController(_playerCharacter);
|
auto player = new PlayerController(playerChar);
|
||||||
|
|
||||||
setPlayerCharacter( _playerCharacter );
|
getWorld()->state.player = player;
|
||||||
|
|
||||||
/*auto bat = new WeaponItem(getWorld()->gameData.weaponData["ak47"]);
|
/*auto bat = new WeaponItem(getWorld()->gameData.weaponData["ak47"]);
|
||||||
_playerCharacter->addToInventory(bat);
|
_playerCharacter->addToInventory(bat);
|
||||||
@ -60,13 +61,11 @@ void IngameState::startTest()
|
|||||||
carPos -= glm::vec3( 2.f + v->info->handling.dimensions.x, 0.f, 0.f);
|
carPos -= glm::vec3( 2.f + v->info->handling.dimensions.x, 0.f, 0.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getWorld()->renderer.camera.frustum.fov = -2.f * glm::quarter_pi<float>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IngameState::spawnPlayerVehicle()
|
void IngameState::spawnPlayerVehicle()
|
||||||
{
|
{
|
||||||
if(! _player) return;
|
if(! getWorld()->state.player ) return;
|
||||||
glm::vec3 hit, normal;
|
glm::vec3 hit, normal;
|
||||||
if(hitWorldRay(hit, normal)) {
|
if(hitWorldRay(hit, normal)) {
|
||||||
|
|
||||||
@ -80,7 +79,8 @@ void IngameState::spawnPlayerVehicle()
|
|||||||
auto spawnpos = hit + normal;
|
auto spawnpos = hit + normal;
|
||||||
auto vehicle = getWorld()->createVehicle(it->first, spawnpos,
|
auto vehicle = getWorld()->createVehicle(it->first, spawnpos,
|
||||||
glm::quat(glm::vec3(0.f, 0.f, -_lookAngles.x * PiOver180)));
|
glm::quat(glm::vec3(0.f, 0.f, -_lookAngles.x * PiOver180)));
|
||||||
_playerCharacter->enterVehicle(vehicle, 0);
|
|
||||||
|
getWorld()->state.player->getCharacter()->enterVehicle(vehicle, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ void IngameState::updateView()
|
|||||||
float localX = -_lookAngles.x;
|
float localX = -_lookAngles.x;
|
||||||
|
|
||||||
float viewDistance = 2.f;
|
float viewDistance = 2.f;
|
||||||
if( _playerCharacter->getCurrentVehicle() ) {
|
/*if( _playerCharacter->getCurrentVehicle() ) {
|
||||||
auto model = _playerCharacter->getCurrentVehicle()->model;
|
auto model = _playerCharacter->getCurrentVehicle()->model;
|
||||||
for(auto& g : model->model->geometries) {
|
for(auto& g : model->model->geometries) {
|
||||||
viewDistance = std::max(
|
viewDistance = std::max(
|
||||||
@ -150,9 +150,12 @@ void IngameState::updateView()
|
|||||||
viewFraction = allrr.m_hitFractions[i] * 0.9f;
|
viewFraction = allrr.m_hitFractions[i] * 0.9f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
setViewParameters( (viewPos + glm::vec3(0.f, 0.f, 0.75f)) + localview * viewFraction, {localX, _lookAngles.y} );
|
PlayerController *IngameState::getPlayer()
|
||||||
|
{
|
||||||
|
return getWorld()->state.player;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IngameState::enter()
|
void IngameState::enter()
|
||||||
@ -167,18 +170,58 @@ void IngameState::exit()
|
|||||||
|
|
||||||
void IngameState::tick(float dt)
|
void IngameState::tick(float dt)
|
||||||
{
|
{
|
||||||
if( getWorld()->state.player ) {
|
auto player = getPlayer();
|
||||||
_player = getWorld()->state.player;
|
if( player )
|
||||||
_playerCharacter = _player->getCharacter();
|
{
|
||||||
}
|
float qpi = glm::half_pi<float>();
|
||||||
|
|
||||||
if( _player ) {
|
sf::Vector2i screenCenter{sf::Vector2i{getWindow().getSize()} / 2};
|
||||||
updateView();
|
sf::Vector2i mousePos = sf::Mouse::getPosition(getWindow());
|
||||||
|
sf::Vector2i deltaMouse = mousePos - screenCenter;
|
||||||
|
sf::Mouse::setPosition(screenCenter, getWindow());
|
||||||
|
|
||||||
|
_lookAngles.x += deltaMouse.x / 100.0;
|
||||||
|
_lookAngles.y += deltaMouse.y / 100.0;
|
||||||
|
|
||||||
|
if (_lookAngles.y > qpi)
|
||||||
|
_lookAngles.y = qpi;
|
||||||
|
else if (_lookAngles.y < -qpi)
|
||||||
|
_lookAngles.y = -qpi;
|
||||||
|
|
||||||
|
auto angle = glm::angleAxis(-_lookAngles.x, glm::vec3(0.f, 0.f, 1.f));
|
||||||
|
|
||||||
|
player->updateMovementDirection(angle * _movement, _movement);
|
||||||
|
|
||||||
|
auto position = player->getCharacter()->getPosition();
|
||||||
|
|
||||||
|
float viewDistance = 2.5f;
|
||||||
|
|
||||||
|
auto vehicle = player->getCharacter()->getCurrentVehicle();
|
||||||
|
if( vehicle ) {
|
||||||
|
auto model = vehicle->model;
|
||||||
|
for(auto& g : model->model->geometries) {
|
||||||
|
viewDistance = std::max(
|
||||||
|
(glm::length(g->geometryBounds.center) + g->geometryBounds.radius) * 2.0f,
|
||||||
|
viewDistance);
|
||||||
|
}
|
||||||
|
position = player->getCharacter()->getCurrentVehicle()->getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move back from the character
|
||||||
|
position += angle * glm::vec3(-viewDistance, 0.f, 1.f);
|
||||||
|
|
||||||
|
// Tilt the final look angle down a tad.
|
||||||
|
angle *= glm::angleAxis(glm::radians(5.f), glm::vec3(0.f, 1.f, 0.f));
|
||||||
|
|
||||||
|
_look.position = position;
|
||||||
|
_look.rotation = angle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IngameState::handleEvent(const sf::Event &event)
|
void IngameState::handleEvent(const sf::Event &event)
|
||||||
{
|
{
|
||||||
|
auto player = getPlayer();
|
||||||
|
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case sf::Event::KeyPressed:
|
case sf::Event::KeyPressed:
|
||||||
switch(event.key.code) {
|
switch(event.key.code) {
|
||||||
@ -186,35 +229,35 @@ void IngameState::handleEvent(const sf::Event &event)
|
|||||||
StateManager::get().enter(new PauseState);
|
StateManager::get().enter(new PauseState);
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::M:
|
case sf::Keyboard::M:
|
||||||
StateManager::get().enter(new DebugState);
|
StateManager::get().enter(new DebugState(_look.position, _look.rotation));
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::Space:
|
case sf::Keyboard::Space:
|
||||||
if(_playerCharacter) {
|
if( player ) {
|
||||||
_playerCharacter->jump();
|
player->getCharacter()->jump();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::W:
|
case sf::Keyboard::W:
|
||||||
_movement.y =-1.f;
|
|
||||||
break;
|
|
||||||
case sf::Keyboard::S:
|
|
||||||
_movement.y = 1.f;
|
|
||||||
break;
|
|
||||||
case sf::Keyboard::A:
|
|
||||||
_movement.x = 1.f;
|
_movement.x = 1.f;
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::D:
|
case sf::Keyboard::S:
|
||||||
_movement.x =-1.f;
|
_movement.x =-1.f;
|
||||||
break;
|
break;
|
||||||
|
case sf::Keyboard::A:
|
||||||
|
_movement.y = 1.f;
|
||||||
|
break;
|
||||||
|
case sf::Keyboard::D:
|
||||||
|
_movement.y =-1.f;
|
||||||
|
break;
|
||||||
case sf::Keyboard::LShift:
|
case sf::Keyboard::LShift:
|
||||||
_player->setRunning(true);
|
player->setRunning(true);
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::F:
|
case sf::Keyboard::F:
|
||||||
if(_playerCharacter) {
|
if( player ) {
|
||||||
if(_playerCharacter->getCurrentVehicle()) {
|
if( player->getCharacter()->getCurrentVehicle()) {
|
||||||
_player->exitVehicle();
|
player->exitVehicle();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_player->enterNearestVehicle();
|
player->enterNearestVehicle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -225,14 +268,14 @@ void IngameState::handleEvent(const sf::Event &event)
|
|||||||
switch(event.key.code) {
|
switch(event.key.code) {
|
||||||
case sf::Keyboard::W:
|
case sf::Keyboard::W:
|
||||||
case sf::Keyboard::S:
|
case sf::Keyboard::S:
|
||||||
_movement.y = 0.f;
|
_movement.x = 0.f;
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::A:
|
case sf::Keyboard::A:
|
||||||
case sf::Keyboard::D:
|
case sf::Keyboard::D:
|
||||||
_movement.x = 0.f;
|
_movement.y = 0.f;
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::LShift:
|
case sf::Keyboard::LShift:
|
||||||
_player->setRunning(false);
|
player->setRunning(false);
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::F12:
|
case sf::Keyboard::F12:
|
||||||
skipTime(10.f);
|
skipTime(10.f);
|
||||||
@ -243,7 +286,7 @@ void IngameState::handleEvent(const sf::Event &event)
|
|||||||
case sf::Event::MouseButtonPressed:
|
case sf::Event::MouseButtonPressed:
|
||||||
switch(event.mouseButton.button) {
|
switch(event.mouseButton.button) {
|
||||||
case sf::Mouse::Left:
|
case sf::Mouse::Left:
|
||||||
_player->useItem(true, true);
|
player->useItem(true, true);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -251,15 +294,20 @@ void IngameState::handleEvent(const sf::Event &event)
|
|||||||
case sf::Event::MouseButtonReleased:
|
case sf::Event::MouseButtonReleased:
|
||||||
switch(event.mouseButton.button) {
|
switch(event.mouseButton.button) {
|
||||||
case sf::Mouse::Left:
|
case sf::Mouse::Left:
|
||||||
_player->useItem(false, true);
|
player->useItem(false, true);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case sf::Event::MouseWheelMoved:
|
case sf::Event::MouseWheelMoved:
|
||||||
_playerCharacter->cycleInventory(event.mouseWheel.delta > 0);
|
player->getCharacter()->cycleInventory(event.mouseWheel.delta > 0);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
State::handleEvent(event);
|
State::handleEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ViewCamera &IngameState::getCamera()
|
||||||
|
{
|
||||||
|
return _look;
|
||||||
|
}
|
||||||
|
@ -3,13 +3,11 @@
|
|||||||
|
|
||||||
#include "State.hpp"
|
#include "State.hpp"
|
||||||
|
|
||||||
#include <ai/PlayerController.hpp>
|
class PlayerController;
|
||||||
|
|
||||||
class IngameState : public State
|
class IngameState : public State
|
||||||
{
|
{
|
||||||
PlayerController* _player;
|
ViewCamera _look;
|
||||||
CharacterObject* _playerCharacter;
|
|
||||||
|
|
||||||
glm::vec2 _lookAngles;
|
glm::vec2 _lookAngles;
|
||||||
glm::vec3 _movement;
|
glm::vec3 _movement;
|
||||||
public:
|
public:
|
||||||
@ -20,12 +18,17 @@ public:
|
|||||||
|
|
||||||
void updateView();
|
void updateView();
|
||||||
|
|
||||||
|
/** shortcut for getWorld()->state.player->getCharacter() */
|
||||||
|
PlayerController* getPlayer();
|
||||||
|
|
||||||
virtual void enter();
|
virtual void enter();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
|
||||||
virtual void tick(float dt);
|
virtual void tick(float dt);
|
||||||
|
|
||||||
virtual void handleEvent(const sf::Event& event);
|
virtual void handleEvent(const sf::Event& event);
|
||||||
|
|
||||||
|
const ViewCamera& getCamera();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INGAMESTATE_HPP
|
#endif // INGAMESTATE_HPP
|
||||||
|
127
rwgame/main.cpp
127
rwgame/main.cpp
@ -8,7 +8,7 @@
|
|||||||
#include <objects/VehicleObject.hpp>
|
#include <objects/VehicleObject.hpp>
|
||||||
#include <objects/CharacterObject.hpp>
|
#include <objects/CharacterObject.hpp>
|
||||||
#include <objects/InstanceObject.hpp>
|
#include <objects/InstanceObject.hpp>
|
||||||
#include <ai/CharacterController.hpp>
|
#include <ai/PlayerController.hpp>
|
||||||
|
|
||||||
#include <script/ScriptMachine.hpp>
|
#include <script/ScriptMachine.hpp>
|
||||||
|
|
||||||
@ -36,38 +36,18 @@ constexpr int WIDTH = 800,
|
|||||||
sf::RenderWindow window;
|
sf::RenderWindow window;
|
||||||
|
|
||||||
GameWorld* gta = nullptr;
|
GameWorld* gta = nullptr;
|
||||||
CharacterObject* player = nullptr;
|
|
||||||
|
|
||||||
DebugDraw* debugDrawer = nullptr;
|
DebugDraw* debugDrawer = nullptr;
|
||||||
|
|
||||||
bool inFocus = true;
|
bool inFocus = true;
|
||||||
int debugMode = 0;
|
int debugMode = 0;
|
||||||
|
|
||||||
float accum = 0.f;
|
float accum = 0.f;
|
||||||
|
|
||||||
|
// Camera poisitions to interpolate between ticks.
|
||||||
|
ViewCamera lastCam, nextCam;
|
||||||
|
|
||||||
sf::Font font;
|
sf::Font font;
|
||||||
|
|
||||||
glm::vec3 viewPosition { -260.f, -151.5f, 9.f }, lastViewPosition;
|
|
||||||
glm::vec2 viewAngles { -0.3f, 0.05f }, lastViewAngles;
|
|
||||||
|
|
||||||
void setViewParameters(const glm::vec3 ¢er, const glm::vec2 &angles)
|
|
||||||
{
|
|
||||||
lastViewPosition = viewPosition;
|
|
||||||
lastViewAngles = viewAngles;
|
|
||||||
viewPosition = center;
|
|
||||||
viewAngles = angles;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3& getViewPosition()
|
|
||||||
{
|
|
||||||
return viewPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec2& getViewAngles()
|
|
||||||
{
|
|
||||||
return viewAngles;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Window& getWindow()
|
sf::Window& getWindow()
|
||||||
{
|
{
|
||||||
return window;
|
return window;
|
||||||
@ -83,16 +63,6 @@ sf::Font& getFont()
|
|||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPlayerCharacter(CharacterObject *playerCharacter)
|
|
||||||
{
|
|
||||||
player = playerCharacter;
|
|
||||||
}
|
|
||||||
|
|
||||||
CharacterObject* getPlayerCharacter()
|
|
||||||
{
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
void skipTime(float time)
|
void skipTime(float time)
|
||||||
{
|
{
|
||||||
accum += time;
|
accum += time;
|
||||||
@ -100,13 +70,11 @@ void skipTime(float time)
|
|||||||
|
|
||||||
bool hitWorldRay(glm::vec3 &hit, glm::vec3 &normal, GameObject** object)
|
bool hitWorldRay(glm::vec3 &hit, glm::vec3 &normal, GameObject** object)
|
||||||
{
|
{
|
||||||
glm::mat4 view;
|
const ViewCamera& vc = StateManager::get().states.back()->getCamera();
|
||||||
view = glm::rotate(view, -90.f, glm::vec3(1, 0, 0));
|
btVector3 from(vc.position.x, vc.position.y, vc.position.z);
|
||||||
view = glm::rotate(view, viewAngles.y, glm::vec3(1, 0, 0));
|
glm::vec3 tmp = vc.rotation * glm::vec3(1000.f, 0.f, 0.f);
|
||||||
view = glm::rotate(view, viewAngles.x, glm::vec3(0, 0, 1));
|
btVector3 to(from.x() + tmp.x, from.y() + tmp.y, from.x() + tmp.z);
|
||||||
glm::vec3 dir = glm::inverse(glm::mat3(view)) * glm::vec3(0.f, 0.f, 1.f) * -50.f;
|
|
||||||
auto from = btVector3(viewPosition.x, viewPosition.y, viewPosition.z);
|
|
||||||
auto to = btVector3(viewPosition.x+dir.x, viewPosition.y+dir.y, viewPosition.z+dir.z);
|
|
||||||
btCollisionWorld::ClosestRayResultCallback ray(from, to);
|
btCollisionWorld::ClosestRayResultCallback ray(from, to);
|
||||||
gta->dynamicsWorld->rayTest(from, to, ray);
|
gta->dynamicsWorld->rayTest(from, to, ray);
|
||||||
if( ray.hasHit() )
|
if( ray.hasHit() )
|
||||||
@ -221,7 +189,7 @@ void init(std::string gtapath)
|
|||||||
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||||
gta->dynamicsWorld->setDebugDrawer(debugDrawer);
|
gta->dynamicsWorld->setDebugDrawer(debugDrawer);
|
||||||
|
|
||||||
setViewParameters( { -260.f, -151.5f, 9.f }, { -0.3f, 0.05f } );
|
//setViewParameters( { -260.f, -151.5f, 9.f }, { -0.3f, 0.05f } );
|
||||||
|
|
||||||
std::cout << "Loaded "
|
std::cout << "Loaded "
|
||||||
<< gta->gameData.models.size() << " models, "
|
<< gta->gameData.models.size() << " models, "
|
||||||
@ -270,24 +238,17 @@ void update(float dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// render() needs two cameras to smoothly interpolate between ticks.
|
||||||
|
lastCam = nextCam;
|
||||||
|
nextCam = StateManager::get().states.back()->getCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(float alpha)
|
void render(float alpha)
|
||||||
{
|
{
|
||||||
float qpi = glm::half_pi<float>();
|
ViewCamera viewCam;
|
||||||
|
if( gta->state.currentCutscene != nullptr && gta->state.cutsceneStartTime >= 0.f )
|
||||||
glm::mat4 view;
|
{
|
||||||
/// @todo this probably doesn't belong in main.cpp
|
|
||||||
if( gta->state.currentCutscene == nullptr || gta->state.cutsceneStartTime <= 0.f ) {
|
|
||||||
view = glm::translate(view, glm::mix(lastViewPosition, viewPosition, alpha));
|
|
||||||
auto va = glm::mix(lastViewAngles, viewAngles, alpha);
|
|
||||||
view = glm::rotate(view, va.x, glm::vec3(0, 0, 1));
|
|
||||||
view = glm::rotate(view, va.y - qpi, glm::vec3(1, 0, 0));
|
|
||||||
view = glm::inverse(view);
|
|
||||||
|
|
||||||
gta->renderer.camera.worldPos = viewPosition;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto cutscene = gta->state.currentCutscene;
|
auto cutscene = gta->state.currentCutscene;
|
||||||
float cutsceneTime = std::min(gta->gameTime - gta->state.cutsceneStartTime,
|
float cutsceneTime = std::min(gta->gameTime - gta->state.cutsceneStartTime,
|
||||||
cutscene->tracks.duration);
|
cutscene->tracks.duration);
|
||||||
@ -295,33 +256,47 @@ void render(float alpha)
|
|||||||
glm::vec3 cameraPos = cutscene->tracks.getPositionAt(cutsceneTime),
|
glm::vec3 cameraPos = cutscene->tracks.getPositionAt(cutsceneTime),
|
||||||
targetPos = cutscene->tracks.getTargetAt(cutsceneTime);
|
targetPos = cutscene->tracks.getTargetAt(cutsceneTime);
|
||||||
float zoom = cutscene->tracks.getZoomAt(cutsceneTime);
|
float zoom = cutscene->tracks.getZoomAt(cutsceneTime);
|
||||||
gta->renderer.camera.frustum.fov = glm::radians(-zoom);
|
viewCam.frustum.fov = glm::radians(zoom);
|
||||||
float tilt = cutscene->tracks.getRotationAt(cutsceneTime);
|
float tilt = cutscene->tracks.getRotationAt(cutsceneTime);
|
||||||
|
|
||||||
auto d = glm::normalize(targetPos-cameraPos);
|
auto direction = glm::normalize(targetPos - cameraPos);
|
||||||
auto qtilt = glm::rotate(glm::quat(), glm::radians(tilt), d);
|
auto right = glm::normalize(glm::cross(glm::vec3(0.f, 0.f, 1.f), direction));
|
||||||
|
auto up = glm::normalize(glm::cross(direction, right));
|
||||||
|
|
||||||
|
glm::mat3 m;
|
||||||
|
m[0][0] = direction.x;
|
||||||
|
m[0][1] = right.x;
|
||||||
|
m[0][2] = up.x;
|
||||||
|
|
||||||
|
m[1][0] = direction.y;
|
||||||
|
m[1][1] = right.y;
|
||||||
|
m[1][2] = up.y;
|
||||||
|
|
||||||
|
m[2][0] = direction.z;
|
||||||
|
m[2][1] = right.z;
|
||||||
|
m[2][2] = up.z;
|
||||||
|
|
||||||
|
auto qtilt = glm::angleAxis(glm::radians(tilt), direction);
|
||||||
|
|
||||||
cameraPos += cutscene->meta.sceneOffset;
|
cameraPos += cutscene->meta.sceneOffset;
|
||||||
targetPos += cutscene->meta.sceneOffset;
|
targetPos += cutscene->meta.sceneOffset;
|
||||||
|
|
||||||
// Update the internal values
|
viewCam.position = cameraPos;
|
||||||
lastViewPosition = viewPosition = cameraPos;
|
viewCam.rotation = glm::inverse(glm::quat_cast(m)) * qtilt;
|
||||||
|
}
|
||||||
view = glm::lookAt(cameraPos, targetPos, qtilt * glm::vec3(0.f, 0.f, -1.f));
|
else
|
||||||
|
{
|
||||||
gta->renderer.camera.worldPos = cameraPos;
|
// There's no cutscene playing - use the camera returned by the State.
|
||||||
|
viewCam.position = glm::mix(lastCam.position, nextCam.position, alpha);
|
||||||
|
viewCam.rotation = glm::slerp(lastCam.rotation, nextCam.rotation, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
gta->renderer.camera.frustum.view = view;
|
viewCam.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
|
||||||
|
|
||||||
// Update aspect ratio..
|
|
||||||
gta->renderer.camera.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
|
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
|
||||||
//glEnable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
gta->renderer.renderWorld(alpha);
|
gta->renderer.renderWorld(viewCam, alpha);
|
||||||
|
|
||||||
switch( debugMode ) {
|
switch( debugMode ) {
|
||||||
case 0: break;
|
case 0: break;
|
||||||
@ -357,12 +332,12 @@ void render(float alpha)
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::setfill('0') << "Time: " << std::setw(2) << gta->getHour()
|
ss << std::setfill('0') << "Time: " << std::setw(2) << gta->getHour()
|
||||||
<< ":" << std::setw(2) << gta->getMinute() << " (" << gta->gameTime << "s)\n";
|
<< ":" << std::setw(2) << gta->getMinute() << " (" << gta->gameTime << "s)\n";
|
||||||
ss << "View: " << viewPosition.x << " " << viewPosition.y << " " << viewPosition.z << "\n";
|
ss << "View: " << viewCam.position.x << " " << viewCam.position.y << " " << viewCam.position.z << "\n";
|
||||||
ss << "Drawn " << gta->renderer.rendered << " / " << gta->renderer.culled << " Culled " << " " << gta->renderer.frames << " " << gta->renderer.geoms << "\n";
|
ss << "Drawn " << gta->renderer.rendered << " / " << gta->renderer.culled << " Culled " << " " << gta->renderer.frames << " " << gta->renderer.geoms << "\n";
|
||||||
if( player ) {
|
if( gta->state.player ) {
|
||||||
ss << "Activity: ";
|
ss << "Activity: ";
|
||||||
if( player->controller->getCurrentActivity() ) {
|
if( gta->state.player->getCurrentActivity() ) {
|
||||||
ss << player->controller->getCurrentActivity()->name();
|
ss << gta->state.player->getCurrentActivity()->name();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ss << "Idle";
|
ss << "Idle";
|
||||||
|
@ -67,11 +67,6 @@ void ViewerWidget::paintGL()
|
|||||||
|
|
||||||
auto& r = gworld->renderer;
|
auto& r = gworld->renderer;
|
||||||
|
|
||||||
r.camera.frustum.far = 500.f;
|
|
||||||
r.camera.frustum.near = 0.1f;
|
|
||||||
r.camera.frustum.fov = 90.f;
|
|
||||||
r.camera.frustum.aspectRatio = width()/(height()*1.f);
|
|
||||||
|
|
||||||
if(dummyObject && dummyObject->animator) {
|
if(dummyObject && dummyObject->animator) {
|
||||||
dummyObject->animator->tick(1.f/60.f);
|
dummyObject->animator->tick(1.f/60.f);
|
||||||
}
|
}
|
||||||
@ -91,12 +86,19 @@ void ViewerWidget::paintGL()
|
|||||||
|
|
||||||
glUseProgram(r.worldProgram);
|
glUseProgram(r.worldProgram);
|
||||||
|
|
||||||
glm::mat4 proj = r.camera.frustum.projection();
|
ViewCamera vc;
|
||||||
|
|
||||||
|
vc.frustum.far = 500.f;
|
||||||
|
vc.frustum.near = 0.1f;
|
||||||
|
vc.frustum.fov = 90.f;
|
||||||
|
vc.frustum.aspectRatio = width()/(height()*1.f);
|
||||||
|
|
||||||
|
glm::mat4 proj = vc.frustum.projection();
|
||||||
glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y), cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y));
|
glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y), cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y));
|
||||||
glm::mat4 view = glm::lookAt(eye * viewDistance, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f));
|
glm::mat4 view = glm::lookAt(eye * viewDistance, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f));
|
||||||
|
|
||||||
r.uploadUBO<SceneUniformData>(r.uboScene,
|
r.uploadUBO<SceneUniformData>(r.uboScene,
|
||||||
{ proj, view, glm::vec4(1.f), glm::vec4(1.f), glm::vec4(1.f), glm::vec4(0.f), 90.f, r.camera.frustum.far });
|
{ proj, view, glm::vec4(1.f), glm::vec4(1.f), glm::vec4(1.f), glm::vec4(0.f), 90.f, vc.frustum.far });
|
||||||
|
|
||||||
if( dummyObject->model->model ) {
|
if( dummyObject->model->model ) {
|
||||||
gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject);
|
gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject);
|
||||||
|
@ -8,8 +8,8 @@ BOOST_AUTO_TEST_CASE(frustum_test_visible)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
ViewFrustum f(0.1f, 100.f, glm::half_pi<float>(), 1.f);
|
ViewFrustum f(0.1f, 100.f, glm::half_pi<float>(), 1.f);
|
||||||
f.view = glm::lookAt(glm::vec3{0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 0.f, 1.f});
|
|
||||||
f.update(f.projection() * f.view);
|
f.update(f.projection());
|
||||||
|
|
||||||
BOOST_CHECK( f.intersects({10.f, 0.f, 0.f}, 1.f ) );
|
BOOST_CHECK( f.intersects({10.f, 0.f, 0.f}, 1.f ) );
|
||||||
BOOST_CHECK(!f.intersects({-10.f, 0.f, 0.f}, 1.f ) );
|
BOOST_CHECK(!f.intersects({-10.f, 0.f, 0.f}, 1.f ) );
|
||||||
|
@ -4,56 +4,4 @@
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(StateUnitTests)
|
BOOST_AUTO_TEST_SUITE(StateUnitTests)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(state_test_generic)
|
|
||||||
{
|
|
||||||
bool entered = false;
|
|
||||||
bool exited = false;
|
|
||||||
bool ticked = false;
|
|
||||||
|
|
||||||
GenericState ls(
|
|
||||||
[&](State*) { entered = true; },
|
|
||||||
[&](State*, float) { ticked = true; },
|
|
||||||
[&](State*) { exited = true; },
|
|
||||||
[](State*, const sf::Event&){}
|
|
||||||
);
|
|
||||||
|
|
||||||
ls.enter();
|
|
||||||
|
|
||||||
BOOST_CHECK( entered );
|
|
||||||
|
|
||||||
ls.tick(1.f);
|
|
||||||
|
|
||||||
BOOST_CHECK( ticked );
|
|
||||||
|
|
||||||
ls.exit();
|
|
||||||
|
|
||||||
BOOST_CHECK( exited );
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(state_test_switch)
|
|
||||||
{
|
|
||||||
bool entered = false;
|
|
||||||
bool exited = false;
|
|
||||||
bool ticked = false;
|
|
||||||
|
|
||||||
GenericState ls(
|
|
||||||
[&](State*) { entered = true; },
|
|
||||||
[&](State*, float) { ticked = true; },
|
|
||||||
[&](State*) { exited = true; },
|
|
||||||
[](State*, const sf::Event&){}
|
|
||||||
);
|
|
||||||
|
|
||||||
StateManager::get().enter(&ls);
|
|
||||||
|
|
||||||
BOOST_CHECK( entered );
|
|
||||||
|
|
||||||
StateManager::get().tick(1.f);
|
|
||||||
|
|
||||||
BOOST_CHECK( ticked );
|
|
||||||
|
|
||||||
StateManager::get().exit();
|
|
||||||
|
|
||||||
BOOST_CHECK( exited );
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
Loading…
Reference in New Issue
Block a user