render improvments using some cache

master
Eduardo Bart 13 years ago
parent 27ccb472d2
commit 4d10b0dd49

@ -28,7 +28,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CXX_WARNS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-unused-variable -Wno-switch")
SET(CMAKE_CXX_FLAGS "-std=c++0x -pipe ${CXX_WARNS}")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -ggdb3 -fno-inline")
SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -rdynamic")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -g -fno-inline")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)

@ -22,7 +22,7 @@ end
local function destroyMainInterface()
if gameUi then
if Game.gameUi then
Game.gameUi:destroy()
Game.gameUi = nil
end

@ -58,10 +58,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/any.hpp>
#ifndef nullptr
#define nullptr NULL
#endif
// global constants
#include "const.h"

@ -37,7 +37,7 @@ public:
virtual void enableBilinearFilter();
/// Get OpenGL texture id
virtual uint getId() const { return m_textureId; }
uint getId() const { return m_textureId; }
/// Copy pixels from OpenGL texture
std::vector<uint8> getPixels();

@ -42,4 +42,8 @@ typedef int8_t int8;
typedef std::function<void()> SimpleCallback;
typedef std::function<bool()> BooleanCallback;
#ifndef nullptr
#define nullptr NULL
#endif
#endif

@ -115,15 +115,15 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
thingAttributes.speed = Fw::getU16(fin);
thingAttributes.group = Otc::ThingGroundGroup;
break;
case 0x01: // All OnTop
case 0x01: // Must be drawn behind creatures foot, e.g.: ground, carpets, borders...
thingAttributes.alwaysOnTop = true;
thingAttributes.alwaysOnTopOrder = 1;
break;
case 0x02: // Can walk trough (open doors, arces, bug pen fence)
case 0x02: // Must be drawn over tile items, e.g.: trees, walls, stairs, rocks, statues...
thingAttributes.alwaysOnTop = true;
thingAttributes.alwaysOnTopOrder = 2;
break;
case 0x03: // Can walk trough (arces)
case 0x03: // Can walk trough and must be drawn over creatures, e.g: open doors, arces, bug pen fence
thingAttributes.alwaysOnTop = true;
thingAttributes.alwaysOnTopOrder = 3;
break;
@ -133,7 +133,7 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
case 0x05: // Stackable
thingAttributes.stackable = true;
break;
case 0x06: // Unknown
case 0x06: // Unknown, some corpses, stairs, even ground ????
break;
case 0x07: // Useable
thingAttributes.useable = true;
@ -167,7 +167,7 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
case 0x0F: // Blocks pathfind algorithms (monsters)
thingAttributes.blockPathFind = true;
break;
case 0x10: // Blocks monster movement (flowers, parcels etc)
case 0x10: // Pickupable
thingAttributes.pickupable = true;
break;
case 0x11: // Hangable objects (wallpaper etc)
@ -186,9 +186,10 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
thingAttributes.lightLevel = Fw::getU16(fin);
thingAttributes.lightColor = Fw::getU16(fin);
break;
case 0x16:
case 0x16: // Unknown, just a few monuments
break;
case 0x17: // Changes floor
case 0x17: // Changes floor, e.g: holes
thingAttributes.changesFloor = true;
break;
case 0x18: // Thing must be drawed with offset
thingAttributes.hasHeight = true;
@ -200,7 +201,7 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
thingAttributes.drawNextOffset = Fw::getU8(fin);
Fw::getU8(fin);
break;
case 0x1A:
case 0x1A: // Unknown, some corpses
//thingAttributes.hasHeight = true;
break;
case 0x1B:
@ -213,12 +214,12 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
if(Fw::getU16(fin) == 1112)
thingAttributes.readable = true;
break;
case 0x1E:
case 0x1E: // Unknown, only grounds
break;
case 0x1F:
case 0x1F: // Unknown, borders that cant walk into?
thingAttributes.lookThrough = true;
break;
case 0x20:
case 0x20: // Unknown
break;
default:
throw std::runtime_error(Fw::mkstr("unknown .dat byte code: 0x", std::hex, (int)opt));

@ -37,100 +37,139 @@ void Map::draw(const Rect& rect)
g_graphics.bindColor(Fw::white);
m_framebuffer->bind();
LocalPlayerPtr player = g_game.getLocalPlayer();
int walkOffsetX = player->getWalkOffsetX();
int walkOffsetY = player->getWalkOffsetY();
// player is above 7
int drawFloorStop = 0;
if(m_centralPosition.z <= 7) {
// player pos it 8-6. check if we can draw upper floors.
// if there is a window on north, east, south or west
//Position direction[4] = {Position(0, -1, 0), Position(1, 0, 0), Position(0, 1, 0), Position(-1, 0, 0)};
for(int d = 0; d < 4; ++d) {
/*if(const TilePtr& tile = m_tiles[playerPos+direction[d]]) {
const ThingAttributes& thingAttributes = thing->getAttributes();
if(thingAttributes.lookThrough) {
drawFloorStop = playerPos.z - 1;
break;
}
}*/
}
// if we have something covering us, dont show floors above.
for(int jz = 6; jz >= 0; --jz) {
Position coverPos = Position(m_centralPosition.x+(7-jz)-1, m_centralPosition.y+(7-jz)-1, jz);
if(const TilePtr& tile = m_tiles[coverPos]) {
if(tile->getStackSize(3) > 0 && jz < m_centralPosition.z) {
drawFloorStop = jz;
break;
}
}
}
for(int iz = 7; iz > 0; --iz) {
if(iz == drawFloorStop)
break;
// +1 in draws cause 64x64 items may affect view.
for(int step = 0; step < 2; ++step) {
for(int ix = -8+(m_centralPosition.z-iz); ix < + 8+7; ++ix) {
for(int iy = -6+(m_centralPosition.z-iz); iy < + 6+7; ++iy) {
Position itemPos = Position(m_centralPosition.x + ix, m_centralPosition.y + iy, iz);
if(const TilePtr& tile = m_tiles[itemPos])
tile->draw((ix + 7 - (m_centralPosition.z-iz))*32 - walkOffsetX, (iy + 5 - (m_centralPosition.z-iz))*32 - walkOffsetY, step);
}
}
LocalPlayerPtr localPlayer = g_game.getLocalPlayer();
int walkOffsetX = localPlayer->getWalkOffsetX();
int walkOffsetY = localPlayer->getWalkOffsetY();
for(int z = NUM_Z_TILES - 1; z >= 0; --z) {
if(m_visibleTiles.size() == 0)
continue;
int zdif = m_centralPosition.z - z;
for(int step = 0; step < 2; ++step) {
for(const TilePtr& tile : m_visibleTiles[z]) {
int x = (7 + (tile->getPosition().x - m_centralPosition.x) - zdif) * NUM_TILE_PIXELS;
int y = (5 + (tile->getPosition().y - m_centralPosition.y) - zdif) * NUM_TILE_PIXELS;
tile->draw(x - walkOffsetX, y - walkOffsetY, step);
}
}
}
// debug draws
g_graphics.bindColor(Fw::red);
g_graphics.drawBoundingRect(Rect(7*32, 5*32, 32, 32));
m_framebuffer->unbind();
g_graphics.bindColor(Fw::white);
m_framebuffer->draw(rect);
// calculate stretch factor
float horizontalStretchFactor = (rect.width() - rect.x()) / (float)(15*32);
float verticalStretchFactor = (rect.height() - rect.y()) / (float)(11*32);
float horizontalStretchFactor = rect.width() / (float)(NUM_VISIBLE_X_TILES * NUM_TILE_PIXELS);
float verticalStretchFactor = rect.height() / (float)(NUM_VISIBLE_Y_TILES * NUM_TILE_PIXELS);
// draw player names and health bars
for(int ix = -7; ix <= 7; ++ix) {
for(int iy = -5; iy <= 5; ++iy) {
Position itemPos = Position(m_centralPosition.x + ix, m_centralPosition.y + iy, m_centralPosition.z);
if(const TilePtr& tile = m_tiles[itemPos]) {
for(int x = 0; x < NUM_VISIBLE_Y_TILES; ++x) {
for(int y = 0; y <= NUM_VISIBLE_X_TILES; ++y) {
Position tilePos = Position(m_centralPosition.x + (x - 7), m_centralPosition.y + (y - 5), m_centralPosition.z);
if(const TilePtr& tile = m_tiles[tilePos]) {
auto& creatures = tile->getCreatures();
if(creatures.size() == 0)
continue;
for(auto it = creatures.rbegin(), end = creatures.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
const CreaturePtr& creature = thing->asCreature();
CreaturePtr creature = (*it)->asCreature();
int x = (ix + 7)*32 + 10 - tile->getDrawNextOffset();
int y = (iy + 5)*32 - 10 - tile->getDrawNextOffset();
int x = (7 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawNextOffset();
int y = (5 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawNextOffset();
if(creature != player) {
if(creature != localPlayer) {
x += creature->getWalkOffsetX() - walkOffsetX;
y += creature->getWalkOffsetY() - walkOffsetY;
}
creature->drawInformation(rect.x() + x*horizontalStretchFactor, rect.y() + y*verticalStretchFactor, isCovered(tilePos, m_zstart));
}
}
}
}
}
void Map::update()
{
m_zstart = getMaxVisibleFloor();
for(int z = 0; z < NUM_Z_TILES; ++z) {
auto& floorTiles = m_visibleTiles[z];
floorTiles.clear();
if(z < m_zstart)
continue;
for(int y = 0; y < NUM_Y_TILES; ++y) {
for(int x = 0; x < NUM_X_TILES; ++x) {
Position tilePos(m_centralPosition.x + (x - 8), m_centralPosition.y + (y - 6), m_centralPosition.z);
tilePos.coveredUp(m_centralPosition.z - z);
if(const TilePtr& tile = m_tiles[tilePos]) {
// skip tiles that are behind another tile
if(z > m_zstart && isCompletlyCovered(tilePos, m_zstart))
continue;
floorTiles.push_back(tile);
}
}
}
}
}
int Map::getMaxVisibleFloor()
{
Position tilePos = m_centralPosition;
tilePos.up();
TilePtr tile = m_tiles[tilePos];
if(tile)
return m_centralPosition.z;
tilePos = Position(m_centralPosition);
while(tilePos.z >= 0) {
tilePos.coveredUp();
tile = m_tiles[tilePos];
if(tile)
return tilePos.z + 1;
}
return 0;
}
// TODO: create isCovered function.
bool useGray = (drawFloorStop != m_centralPosition.z-1);
bool Map::isCovered(const Position& pos, int maxFloor)
{
Position tilePos = pos;
tilePos.coveredUp();
while(tilePos.z >= maxFloor) {
TilePtr tile = m_tiles[tilePos];
if(tile)
return true;
tilePos.coveredUp();
}
return false;
}
creature->drawInformation(x*horizontalStretchFactor, y*verticalStretchFactor, useGray);
bool Map::isCompletlyCovered(const Position& pos, int maxFloor)
{
Position tilePos = pos;
tilePos.coveredUp();
while(tilePos.z >= maxFloor) {
bool covered = true;
for(int x=0;x<2;++x) {
for(int y=0;y<2;++y) {
TilePtr tile = m_tiles[tilePos + Position(-x, -y, 0)];
if(!tile || !tile->isOpaque()) {
covered = false;
break;
}
}
}
if(covered)
return true;
tilePos.coveredUp();
}
return false;
}
void Map::addThing(ThingPtr thing, int stackpos)
@ -140,7 +179,8 @@ void Map::addThing(ThingPtr thing, int stackpos)
TilePtr& tile = m_tiles[thing->getPosition()];
if(!tile) {
tile = TilePtr(new Tile());
tile = TilePtr(new Tile(thing->getPosition()));
update();
}
tile->addThing(thing, stackpos);
@ -196,3 +236,9 @@ void Map::removeCreatureById(uint32 id)
{
m_creatures.erase(id);
}
void Map::setCentralPosition(const Position& centralPosition)
{
m_centralPosition = centralPosition;
update();
}

@ -28,8 +28,22 @@
class Map
{
enum {
NUM_X_TILES = 19,
NUM_Y_TILES = 15,
NUM_Z_TILES = 15,
NUM_VISIBLE_X_TILES = 15,
NUM_VISIBLE_Y_TILES = 11,
NUM_TILE_PIXELS = 32
};
public:
void draw(const Rect& rect);
void update();
int getMaxVisibleFloor();
bool isCovered(const Position& pos, int maxFloor);
bool isCompletlyCovered(const Position& pos, int maxFloor);
void addThing(ThingPtr thing, int stackpos = -1);
ThingPtr getThing(const Position& pos, int stackpos);
@ -42,7 +56,7 @@ public:
void setLight(const Light& light) { m_light = light; }
Light getLight() { return m_light; }
void setCentralPosition(const Position& centralPosition) { m_centralPosition = centralPosition; }
void setCentralPosition(const Position& centralPosition);
Position getCentralPosition() { return m_centralPosition; }
CreaturePtr getCreatureById(uint32 id);
@ -51,6 +65,8 @@ public:
private:
std::unordered_map<Position, TilePtr, PositionHasher> m_tiles;
std::map<uint32, CreaturePtr> m_creatures;
std::array<std::vector<TilePtr>, NUM_Z_TILES> m_visibleTiles;
int m_zstart;
Light m_light;
Position m_centralPosition;

@ -50,6 +50,7 @@ struct ThingAttributes
isHangable = false;
miniMapColor = 0;
hasMiniMapColor = false;
changesFloor = false;
subParam07 = 0;
subParam08 = 0;
width = 0;
@ -64,7 +65,7 @@ struct ThingAttributes
}
bool stackable, alwaysOnTop, useable, readable, moveable, blockSolid, blockProjectile, blockPathFind, pickupable,
isHangable, isHorizontal, isVertical, rotable, hasHeight, lookThrough, hasMiniMapColor;
isHangable, isHorizontal, isVertical, rotable, hasHeight, lookThrough, hasMiniMapColor, changesFloor;
uint8 alwaysOnTopOrder, width, height, blendframes, xdiv, ydiv, zdiv, animcount, drawOffset, drawNextOffset;
uint16 speed, subParam07, subParam08, lightLevel, lightColor, miniMapColor;

@ -28,9 +28,10 @@
#include "localplayer.h"
#include <framework/graphics/fontmanager.h>
Tile::Tile()
Tile::Tile(const Position& position)
{
m_drawNextOffset = 0;
m_position = position;
}
void Tile::draw(int x, int y, int step)
@ -67,14 +68,17 @@ void Tile::draw(int x, int y, int step)
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
m_drawNextOffset += thingAttributes.drawNextOffset;
}
}
else if(step == 1) {
for(auto it = m_creatures.rbegin(), end = m_creatures.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
}
for(auto it = m_effects.rbegin(), end = m_effects.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
}
for(auto it = m_itemsTop.rbegin(), end = m_itemsTop.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
const ThingAttributes& thingAttributes = thing->getAttributes();
@ -83,11 +87,8 @@ void Tile::draw(int x, int y, int step)
thing->draw(x, y);
}
}
for(auto it = m_effects.rbegin(), end = m_effects.rend(); it != end; ++it) {
const ThingPtr& thing = *it;
thing->draw(x - m_drawNextOffset, y - m_drawNextOffset);
}
}
else if(step == 1) {
}
}
@ -240,3 +241,10 @@ int Tile::getStackSize(int stop)
ret += m_itemsBottom.size();
return ret;
}
bool Tile::isOpaque()
{
if(m_ground && !m_ground->getAttributes().changesFloor)
return true;
return false;
}

@ -29,7 +29,7 @@
class Tile : public LuaObject
{
public:
Tile();
Tile(const Position& position);
void draw(int x, int y, int step);
@ -47,12 +47,17 @@ public:
const ThingList& getCreatures() { return m_creatures; }
int getDrawNextOffset() { return m_drawNextOffset; }
const Position& getPosition() { return m_position; }
bool isOpaque();
private:
ThingPtr m_ground;
ThingList m_itemsBottom;
ThingList m_creatures;
ThingList m_itemsTop;
ThingList m_effects;
Position m_position;
int m_drawNextOffset;
};

@ -37,6 +37,8 @@
#include <otclient/net/protocolgame.h>
#include <otclient/core/game.h>
#include <otclient/core/map.h>
#include "core/datmanager.h"
#include "core/item.h"
OTClient g_client;
@ -229,6 +231,28 @@ void OTClient::render()
{
// everything is rendered by UI components
g_ui.render();
// utility for viewing dat items
/*
int count = 0;
auto maxSize = g_graphics.getScreenSize();
ItemPtr item(new Item);
int x = 32;
int y = 32;
for(int i=100;i<11803;++i) {
if(g_dat.getItemAttributes(i).group == Otc::ThingGroundGroup && !g_dat.getItemAttributes(i).changesFloor) {
item->setId(i);
item->draw(x, y);
x += 64;
if(x > g_graphics.getScreenSize().width()) {
x = 32;
y += 64;
if(y > maxSize.height())
break;
}
}
}
*/
}
void OTClient::loadConfigurations()

@ -66,6 +66,16 @@ public:
bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; }
bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; }
bool isInRange(const Position& pos, int xdif, int ydif, int zdif = 1) {
return std::abs(x-pos.x) <= xdif && std::abs(y-pos.y) <= ydif && std::abs(pos.z-z) <= zdif;
}
void up(int n = 1) { z-=n; }
void down(int n = 1) { z+=n; }
void coveredUp(int n = 1) { x+=n; y+=n; z-=n; }
void coveredDown(int n = 1) { x-=n; y-=n; z+=n; }
int x;
int y;
int z;
@ -77,15 +87,13 @@ struct PositionHasher : std::unary_function<Position, std::size_t> {
}
};
template<class T>
std::ostream& operator<<(std::ostream& out, const Position& pos)
inline std::ostream& operator<<(std::ostream& out, const Position& pos)
{
out << pos.x << " " << pos.y << " " << pos.z;
return out;
}
template<class T>
std::istream& operator>>(std::istream& in, Position& pos)
inline std::istream& operator>>(std::istream& in, Position& pos)
{
in >> pos.x >> pos.y >> pos.z;
return in;

Loading…
Cancel
Save