1
0
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:
Daniel Evans 2015-01-25 17:54:31 +00:00
parent 9f1162a945
commit 87435a2576
12 changed files with 225 additions and 3 deletions

View File

@ -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

View 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);
};

View File

@ -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)

View File

@ -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:

View File

@ -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());

View File

@ -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;
})";
}

View 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 );
}

View File

@ -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));

View File

@ -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();

View File

@ -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);

View File

@ -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) {

View File

@ -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);
};