mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-15 15:02:34 +02:00
Add map renderer and ingame radar display
This commit is contained in:
parent
9f1162a945
commit
87435a2576
@ -9,6 +9,7 @@
|
||||
#include <render/ViewCamera.hpp>
|
||||
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
#include "MapRenderer.hpp"
|
||||
|
||||
class Model;
|
||||
class ModelFrame;
|
||||
@ -241,6 +242,8 @@ public:
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
MapRenderer map;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
42
rwengine/include/render/MapRenderer.hpp
Normal file
42
rwengine/include/render/MapRenderer.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
class GameWorld;
|
||||
|
||||
#define MAP_BLOCK_SIZE 63
|
||||
|
||||
/**
|
||||
* Utility class for rendering the world map, in the menu and radar.
|
||||
*/
|
||||
class MapRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
struct MapInfo
|
||||
{
|
||||
glm::vec2 viewport;
|
||||
float scale;
|
||||
glm::vec2 center;
|
||||
|
||||
glm::vec2 mapSize;
|
||||
glm::vec2 mapPos;
|
||||
};
|
||||
|
||||
MapRenderer(GameWorld* world, Renderer* renderer);
|
||||
|
||||
glm::vec2 mapToScreen(const glm::vec2& map, const MapInfo& mi);
|
||||
glm::vec2 sizeOnScreen(const glm::vec2& map, const MapInfo& mi);
|
||||
|
||||
void draw(const MapInfo& mi);
|
||||
|
||||
private:
|
||||
GameWorld* world;
|
||||
Renderer* renderer;
|
||||
|
||||
GeometryBuffer rectGeom;
|
||||
DrawBuffer rect;
|
||||
|
||||
Renderer::ShaderProgram* rectProg;
|
||||
|
||||
void drawBlip(const glm::vec2& map, const MapInfo& mi, const std::string& texture);
|
||||
};
|
@ -102,6 +102,7 @@ void GameData::load()
|
||||
_knownFiles.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
|
||||
_knownFiles.insert({"weapons.dff", {false, datpath+"/models/Generic/weapons.dff"}});
|
||||
_knownFiles.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
|
||||
_knownFiles.insert({"hud.txd", {false, datpath+"/models/hud.txd"}});
|
||||
_knownFiles.insert({"english.gxt", {false, datpath+"/TEXT/english.gxt"}});
|
||||
_knownFiles.insert({"ped.ifp", {false, datpath+"/anim/ped.ifp"}});
|
||||
|
||||
@ -113,6 +114,7 @@ void GameData::load()
|
||||
loadDFF("wheels.DFF");
|
||||
loadDFF("weapons.dff");
|
||||
loadTXD("particle.txd");
|
||||
loadTXD("hud.txd");
|
||||
|
||||
loadCarcols(datpath+"/data/carcols.dat");
|
||||
loadWeather(datpath+"/data/timecyc.dat");
|
||||
@ -122,7 +124,6 @@ void GameData::load()
|
||||
loadWeaponDAT(datpath+"/data/weapon.dat");
|
||||
|
||||
loadIFP("ped.ifp");
|
||||
|
||||
}
|
||||
|
||||
void GameData::parseDAT(const std::string& path)
|
||||
|
@ -126,6 +126,7 @@ GLuint createTexture(RW::BSTextureNative& texNative, RW::BinaryStreamSection& ro
|
||||
case RW::BSTextureNative::FORMAT_8888:
|
||||
format = GL_BGRA;
|
||||
//type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
coldata += 8;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case RW::BSTextureNative::FORMAT_888:
|
||||
|
@ -79,7 +79,8 @@ GeometryBuffer ssRectGeom;
|
||||
DrawBuffer ssRectDraw;
|
||||
|
||||
GameRenderer::GameRenderer(GameWorld* engine)
|
||||
: engine(engine), renderer(new OpenGLRenderer), _renderAlpha(0.f)
|
||||
: engine(engine), renderer(new OpenGLRenderer), _renderAlpha(0.f),
|
||||
map(engine, renderer)
|
||||
{
|
||||
engine->logInfo("[DRAW] " + renderer->getIDString());
|
||||
|
||||
|
@ -257,6 +257,6 @@ void main()
|
||||
{
|
||||
vec4 c = texture2D(texture, TexCoords);
|
||||
// Set colour to 0, 0, 0, 1 for textured mode.
|
||||
outColour = colour + vec4(c.rgb, 0.0);
|
||||
outColour = colour + c.rgba;
|
||||
})";
|
||||
}
|
||||
|
122
rwengine/src/render/MapRenderer.cpp
Normal file
122
rwengine/src/render/MapRenderer.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include <render/MapRenderer.hpp>
|
||||
#include <render/GameShaders.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
|
||||
MapRenderer::MapRenderer(GameWorld* world, Renderer* renderer)
|
||||
: world( world ), renderer(renderer)
|
||||
{
|
||||
rectGeom.uploadVertices<VertexP2>({
|
||||
{-1.f, -1.f},
|
||||
{ 1.f, -1.f},
|
||||
{-1.f, 1.f},
|
||||
{ 1.f, 1.f}
|
||||
});
|
||||
rect.addGeometry(&rectGeom);
|
||||
rect.setFaceType(GL_TRIANGLE_STRIP);
|
||||
|
||||
rectProg = renderer->createShader(
|
||||
GameShaders::ScreenSpaceRect::VertexShader,
|
||||
GameShaders::ScreenSpaceRect::FragmentShader
|
||||
);
|
||||
|
||||
renderer->setUniform(rectProg, "colour", glm::vec4(1.f));
|
||||
renderer->setUniform(rectProg, "size", glm::vec2(1.f, 1.f));
|
||||
renderer->setUniform(rectProg, "offset", glm::vec2(1.f, 1.f));
|
||||
}
|
||||
|
||||
#define GAME_MAP_SIZE 4048
|
||||
|
||||
glm::vec2 MapRenderer::mapToScreen(const glm::vec2& map, const MapInfo& mi)
|
||||
{
|
||||
glm::vec2 screenSize = ((map-mi.center) * mi.scale) / mi.viewport;
|
||||
glm::vec2 screenCenter = mi.mapPos / (mi.viewport/2.f) - 1.f;
|
||||
return screenSize + screenCenter;
|
||||
}
|
||||
|
||||
glm::vec2 MapRenderer::sizeOnScreen(const glm::vec2& map, const MapRenderer::MapInfo& mi)
|
||||
{
|
||||
glm::vec2 screenSize = ((map) * mi.scale) / mi.viewport;
|
||||
return screenSize;
|
||||
}
|
||||
|
||||
void MapRenderer::draw(const MapInfo& mi)
|
||||
{
|
||||
const glm::vec2& viewport = mi.viewport;
|
||||
const glm::vec2& offset = -mi.center;
|
||||
|
||||
renderer->useProgram(rectProg);
|
||||
|
||||
glm::vec2 worldSize(GAME_MAP_SIZE);
|
||||
const int mapBlockLine = 8;
|
||||
glm::vec2 tileSize = worldSize / (float)mapBlockLine;
|
||||
glm::vec2 tileScreenSize = sizeOnScreen(tileSize, mi);
|
||||
glm::vec2 basePos = mi.mapPos - (mi.mapSize/2.f);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(basePos.x, basePos.y, mi.mapSize.x, mi.mapSize.y);
|
||||
|
||||
glBindVertexArray( rect.getVAOName() );
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Draw backdrop
|
||||
renderer->setUniform(rectProg, "size", sizeOnScreen(worldSize/2.f, mi));
|
||||
renderer->setUniform(rectProg, "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.f));
|
||||
renderer->setUniform(rectProg, "offset", mapToScreen(glm::vec2(0.f, 0.f), mi));
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// 2048, -2048
|
||||
|
||||
renderer->setUniform(rectProg, "size", tileScreenSize/2.f);
|
||||
renderer->setUniform(rectProg, "colour", glm::vec4(0.0f, 0.0f, 0.0f, 0.f));
|
||||
int initX = -(mapBlockLine/2);
|
||||
int initY = (mapBlockLine/2);
|
||||
for( int m = 0; m < MAP_BLOCK_SIZE; ++m )
|
||||
{
|
||||
std::string num = (m < 10 ? "0" : "");
|
||||
std::string name = "radar" + num + std::to_string(m);
|
||||
auto texture = world->gameData.textures[{name,""}];
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.texName);
|
||||
renderer->setUniformTexture(rectProg, "texture", 0);
|
||||
|
||||
int mX = initX + (m % mapBlockLine);
|
||||
int mY = initY - (m / mapBlockLine);
|
||||
auto tc = glm::vec2(mX, mY) * tileSize + (glm::vec2(tileSize.x,-tileSize.y)/2.f);
|
||||
|
||||
auto screen = mapToScreen(tc, mi);
|
||||
|
||||
renderer->setUniform(rectProg, "offset", screen);
|
||||
|
||||
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
|
||||
}
|
||||
|
||||
// Draw the player blip
|
||||
auto player = world->state.player;
|
||||
if( player )
|
||||
{
|
||||
glm::vec2 plyblip(player->getCharacter()->getPosition());
|
||||
drawBlip(plyblip, mi, "radar_centre");
|
||||
}
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glBindVertexArray( 0 );
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void MapRenderer::drawBlip(const glm::vec2& map, const MapInfo& mi, const std::string& texture)
|
||||
{
|
||||
glm::vec2 screen = mapToScreen(map, mi);
|
||||
|
||||
auto sprite = world->gameData.textures[{texture,""}];
|
||||
glBindTexture(GL_TEXTURE_2D, sprite.texName);
|
||||
|
||||
renderer->setUniform(rectProg, "size", 16.f/mi.viewport);
|
||||
|
||||
renderer->setUniform(rectProg, "offset", screen);
|
||||
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
|
||||
}
|
@ -51,6 +51,13 @@ RWGame::RWGame(const std::string& gamepath)
|
||||
|
||||
/// @TODO language choices.
|
||||
engine->gameData.loadGXT("english.gxt");
|
||||
|
||||
for(int m = 0; m < MAP_BLOCK_SIZE; ++m)
|
||||
{
|
||||
std::string num = (m < 10 ? "0" : "");
|
||||
std::string name = "radar" + num + std::to_string(m);
|
||||
engine->gameData.loadTXD(name + ".txd");
|
||||
}
|
||||
|
||||
StateManager::get().enter(new LoadingState(this));
|
||||
|
||||
|
@ -183,6 +183,28 @@ void IngameState::tick(float dt)
|
||||
}
|
||||
}
|
||||
|
||||
void IngameState::draw(sf::RenderWindow& w)
|
||||
{
|
||||
MapRenderer::MapInfo map;
|
||||
map.scale = 0.75f;
|
||||
map.viewport = glm::vec2(w.getSize().x, w.getSize().y);
|
||||
|
||||
map.mapPos = glm::vec2(map.viewport.x * 0.2f, map.viewport.y - map.viewport.y * 0.2f);
|
||||
float aspect = map.viewport.x / map.viewport.y;
|
||||
map.mapSize = map.viewport * 0.3f;
|
||||
map.mapPos.x /= aspect;
|
||||
map.mapSize.x /= aspect;
|
||||
|
||||
if( getWorld()->state.player )
|
||||
{
|
||||
map.center = glm::vec2(getWorld()->state.player->getCharacter()->getPosition());
|
||||
}
|
||||
getWorld()->renderer.map.draw(map);
|
||||
|
||||
State::draw(w);
|
||||
}
|
||||
|
||||
|
||||
void IngameState::handleEvent(const sf::Event &event)
|
||||
{
|
||||
auto player = getPlayer();
|
||||
|
@ -24,6 +24,7 @@ public:
|
||||
virtual void exit();
|
||||
|
||||
virtual void tick(float dt);
|
||||
virtual void draw(sf::RenderWindow& w);
|
||||
|
||||
virtual void handleEvent(const sf::Event& event);
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "pausestate.hpp"
|
||||
#include "RWGame.hpp"
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
|
||||
PauseState::PauseState(RWGame* game)
|
||||
: State(game)
|
||||
@ -27,6 +29,24 @@ void PauseState::tick(float dt)
|
||||
|
||||
}
|
||||
|
||||
void PauseState::draw(sf::RenderWindow& w)
|
||||
{
|
||||
MapRenderer::MapInfo map;
|
||||
|
||||
map.scale = 0.25f;
|
||||
map.viewport = glm::vec2(w.getSize().x, w.getSize().y);
|
||||
map.mapSize = map.viewport;
|
||||
map.mapPos = map.viewport / 2.f;
|
||||
|
||||
if( getWorld()->state.player )
|
||||
{
|
||||
map.center = glm::vec2(getWorld()->state.player->getCharacter()->getPosition());
|
||||
}
|
||||
getWorld()->renderer.map.draw(map);
|
||||
|
||||
State::draw(w);
|
||||
}
|
||||
|
||||
void PauseState::handleEvent(const sf::Event &e)
|
||||
{
|
||||
switch(e.type) {
|
||||
|
@ -12,6 +12,8 @@ public:
|
||||
virtual void exit();
|
||||
|
||||
virtual void tick(float dt);
|
||||
|
||||
virtual void draw(sf::RenderWindow& w);
|
||||
|
||||
virtual void handleEvent(const sf::Event& event);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user