From 937070b3e03abf34e6f9e3f54d1ae23ec39e3028 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Thu, 7 Apr 2011 04:30:32 -0300 Subject: [PATCH 1/2] move render stuff to graphics --- src/framework/color.h | 5 -- src/framework/font.cpp | 111 ++++++++++++++++--------------------- src/framework/font.h | 8 +-- src/framework/graphics.cpp | 42 +++++++++++--- src/framework/graphics.h | 9 +++ src/framework/rect.h | 2 +- 6 files changed, 94 insertions(+), 83 deletions(-) diff --git a/src/framework/color.h b/src/framework/color.h index 1943bc90..77cf2996 100644 --- a/src/framework/color.h +++ b/src/framework/color.h @@ -32,11 +32,6 @@ typedef uint32 RGBA; class Color { public: - enum { - white = 0xFFFFFFFF, - pink = 0xFF00FFFF - }; - inline Color() : color(0) { } inline Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : color(((r & 0xff)<<24) | ((g & 0xff)<<16) | ((b & 0xff)<<8) | (a & 0xff)) { } inline Color(const Color& other) : color(other.color) { } diff --git a/src/framework/font.cpp b/src/framework/font.cpp index bca01af5..e68fb8c4 100644 --- a/src/framework/font.cpp +++ b/src/framework/font.cpp @@ -27,18 +27,11 @@ #include "textures.h" #include "graphics.h" -#include -#include -#include - Font::Font() : m_lineHeight(14), m_cursorSize(14), - m_color(Color::white), - m_firstGlyph(32), - m_numHorizontalGlyphs(16) + m_color(0xFFFFFFFF) { - bzero(m_glyphWidths, sizeof(m_glyphWidths)); } bool Font::load(const std::string& file) @@ -57,6 +50,10 @@ bool Font::load(const std::string& file) std::istringstream fin(fileContents); std::string textureName; + int numHorizontalGlyphs; + int firstGlyph; + Size glyphSize; + Size textureSize; try { YAML::Parser parser(fin); @@ -67,43 +64,48 @@ bool Font::load(const std::string& file) doc["line height"] >> m_lineHeight; doc["cursor size"] >> m_cursorSize; doc["color"] >> m_color; - doc["first glyph"] >> m_firstGlyph; + doc["first glyph"] >> firstGlyph; + doc["image glyph size"] >> glyphSize; doc["image"] >> textureName; - doc["image glyph size"] >> m_glyphSize; + + m_texture = g_textures.get("fonts/" + textureName); + if(!m_texture) { + error("Failed to load image for font \"%s\"", file.c_str()); + return false; + } + + textureSize = m_texture->getSize(); + numHorizontalGlyphs = textureSize.width() / glyphSize.width(); const YAML::Node& widthsNode = doc["glyph widths"]; for(auto it = widthsNode.begin(); it != widthsNode.end(); ++it) { - int id, width; - it.first() >> id; - it.second() >> width; - m_glyphWidths[id] = width; + int glyph, glyphWidth; + it.first() >> glyph; + it.second() >> glyphWidth; + + // calculate glyph texture coords + m_glyphsTextureCoords[glyph].setRect(((glyph - firstGlyph) % numHorizontalGlyphs) * glyphSize.width(), + ((glyph - firstGlyph) / numHorizontalGlyphs) * glyphSize.height(), + glyphWidth, + glyphSize.height()); + + // store glyph size + m_glyphsSize[glyph].setHeight(glyphSize.height()); + m_glyphsSize[glyph].setWidth(glyphWidth); } } catch (YAML::ParserException& e) { error("Malformed font file \"%s\"", file.c_str()); return false; } - m_texture = g_textures.get("fonts/" + textureName); - m_numHorizontalGlyphs = m_texture->getSize().width() / m_glyphSize.width(); - - if(!m_texture) { - error("Failed to load image for font \"%s\"", file.c_str()); - return false; - } - return true; } void Font::renderText(const Point& pos, const std::string& text) { - // bind font texture - glBindTexture(GL_TEXTURE_2D, m_texture->getTextureId()); - - // set font color - glColor4ubv(m_color.rgbaPtr()); - - // begin render - glBegin(GL_QUADS); + // begin texture rendering + g_graphics.setColor(m_color); + g_graphics._beginTextureRender(m_texture.get()); Point currentPos = pos; const Size& screenSize = g_graphics.getScreenSize(); @@ -112,9 +114,7 @@ void Font::renderText(const Point& pos, const std::string& text) for(int i = 0; i < textLenght; ++i) { int c = (int)text[i]; - // check if is visible - if(currentPos.x >= screenSize.width()) - continue; + // break rendering if the Y pos is below the screen if(currentPos.y >= screenSize.height()) break; @@ -123,45 +123,28 @@ void Font::renderText(const Point& pos, const std::string& text) currentPos.y += m_lineHeight; currentPos.x = pos.x; } - // text eof - else if(c == '\0') { - break; - } - // normal glyph - else if(c >= m_firstGlyph) { - currentPos.x += renderGlyph(currentPos, c); + // render glyph + else { + // render online if is visible on screen + if(currentPos.x < screenSize.width()) + currentPos.x += renderGlyph(currentPos, c); } } - // end font render - glEnd(); + // end texture redering + g_graphics._endTextureRender(); + g_graphics.resetColor(); } int Font::renderGlyph(const Point& pos, int glyph) { - // get glyph width - int glyphWidth = m_glyphWidths[glyph]; - - // calculate glyph coords on texture font - const Size& textureSize = m_texture->getSize(); - int glyphTexCoordX = ((glyph - m_firstGlyph) % m_numHorizontalGlyphs) * m_glyphSize.width(); - int glyphTexCoordY = ((glyph - m_firstGlyph) / m_numHorizontalGlyphs) * m_glyphSize.height(); - float textureRight = (float)(glyphTexCoordX + glyphWidth) / textureSize.width(); - float textureBottom = (float)(glyphTexCoordY + m_glyphSize.height()) / textureSize.height(); - float textureTop = (float)(glyphTexCoordY) / textureSize.height(); - float textureLeft = (float)(glyphTexCoordX) / textureSize.width(); - - // calculate glyph coords on screen - int right = pos.x + glyphWidth; - int bottom = pos.y + m_glyphSize.height(); - int top = pos.y; - int left = pos.x; + // don't render invalid glyphs + if(glyph < 32) + return 0; // render glyph - glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); - glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); - glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); - glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); + Rect screenCoords(pos, m_glyphsSize[glyph]); + g_graphics._drawTexturedRect(screenCoords, m_glyphsTextureCoords[glyph], m_texture->getSize()); - return glyphWidth; + return m_glyphsSize[glyph].width(); } diff --git a/src/framework/font.h b/src/framework/font.h index 81757841..29b2aed3 100644 --- a/src/framework/font.h +++ b/src/framework/font.h @@ -28,6 +28,7 @@ #include "prerequisites.h" #include "color.h" #include "texture.h" +#include "rect.h" class Font { @@ -67,11 +68,8 @@ private: int m_cursorSize; Color m_color; TexturePtr m_texture; - Size m_textureSize; - Size m_glyphSize; - int m_firstGlyph; - int m_glyphWidths[256]; - int m_numHorizontalGlyphs; + Rect m_glyphsTextureCoords[256]; + Size m_glyphsSize[256]; }; #endif // FONT_H diff --git a/src/framework/graphics.cpp b/src/framework/graphics.cpp index 724179d0..689ff52d 100644 --- a/src/framework/graphics.cpp +++ b/src/framework/graphics.cpp @@ -125,7 +125,37 @@ void Graphics::endRender() } + +void Graphics::setColor(const Color& color) +{ + glColor4ubv(color.rgbaPtr()); +} + +void Graphics::resetColor() +{ + glColor4ub(0xFF, 0xFF, 0xFF, 0xFF); +} + +void Graphics::_beginTextureRender(const Texture *texture) +{ + glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); + glBegin(GL_QUADS); +} + +void Graphics::_endTextureRender() +{ + glEnd(); +} + void Graphics::drawTexturedRect(const Rect& screenCoords, const Texture *texture, const Rect& textureCoords) +{ + glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); + glBegin(GL_QUADS); + _drawTexturedRect(screenCoords, textureCoords, texture->getSize()); + glEnd(); +} + +void Graphics::_drawTexturedRect(const Rect& screenCoords, const Rect& textureCoords, const Size& textureSize) { // rect correction for opengl int right = screenCoords.right() + 1; @@ -139,20 +169,16 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, const Texture *texture float textureLeft = 1.0f; if(!textureCoords.isEmpty()) { - const Size& textureSize = texture->getSize(); textureRight = (float)(textureCoords.right() + 1) / textureSize.width(); textureBottom = (float)(textureCoords.bottom() + 1) / textureSize.height(); textureTop = (float)textureCoords.top() / textureSize.height(); textureLeft = (float)textureCoords.left() / textureSize.width(); } - glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); - glBegin(GL_QUADS); - glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); - glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); - glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); - glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); - glEnd(); + glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); + glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); + glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); + glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); } void Graphics::drawColoredRect(const Rect& screenCoords, const Color& color) diff --git a/src/framework/graphics.h b/src/framework/graphics.h index 1030baed..c192b2a6 100644 --- a/src/framework/graphics.h +++ b/src/framework/graphics.h @@ -57,10 +57,19 @@ public: const Size& getScreenSize() const { return m_screenSize; } + void setColor(const Color& color); + void resetColor(); + + // high level rendering void drawTexturedRect(const Rect& screenCoords, const Texture *texture, const Rect& texCoords = Rect()); void drawColoredRect(const Rect& screenCoords, const Color& color); void drawBoundingRect(const Rect& screenCoords, const Color& color, int innerLineWidth); + // lower level rendering + void _beginTextureRender(const Texture *texture); + void _drawTexturedRect(const Rect& screenCoords, const Rect& textureCoords, const Size& textureSize); + void _endTextureRender(); + private: Size m_screenSize; }; diff --git a/src/framework/rect.h b/src/framework/rect.h index 065f92a2..ab78e222 100644 --- a/src/framework/rect.h +++ b/src/framework/rect.h @@ -44,7 +44,7 @@ public: inline TRect(const TPoint& topLeft, const TPoint& bottomRight) : x1(topLeft.x), y1(topLeft.y), x2(bottomRight.x), y2(bottomRight.y) { } inline TRect(const TRect& other) : x1(other.x1), y1(other.y1), x2(other.x2), y2(other.y2) { } inline TRect(T x, T y, const TSize& size) : x1(x), y1(y), x2(x+size.width()-1), y2(y+size.height()-1) { } - inline TRect(const TPoint& topLeft, const TSize& size) : x1(topLeft.x), y1(topLeft.y), x2(x+size.width()-1), y2(y+size.height()-1) { } + inline TRect(const TPoint& topLeft, const TSize& size) : x1(topLeft.x), y1(topLeft.y), x2(x1+size.width()-1), y2(y1+size.height()-1) { } inline bool isNull() const { return x2 == x1 - 1 && y2 == y1 - 1; } inline bool isEmpty() const { return x1 > x2 || y1 > y2; } From f3eaf3f7262bf6ef35cee745d40088669526125a Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Thu, 7 Apr 2011 05:38:29 -0300 Subject: [PATCH 2/2] fps counter --- src/framework/engine.cpp | 48 +++++++++++++++++++++++++++++++--------- src/framework/engine.h | 5 +++++ src/framework/font.cpp | 40 ++++++++++++++++++++------------- src/framework/font.h | 17 ++++++++++---- src/framework/fonts.cpp | 10 +++++++++ src/framework/fonts.h | 3 +++ src/main.cpp | 3 ++- src/menustate.cpp | 9 +------- 8 files changed, 97 insertions(+), 38 deletions(-) diff --git a/src/framework/engine.cpp b/src/framework/engine.cpp index 93839b43..b8bab578 100644 --- a/src/framework/engine.cpp +++ b/src/framework/engine.cpp @@ -30,6 +30,8 @@ #include "configs.h" #include "gamestate.h" +#define MINIMUN_UPDATE_DELAY 50 + Engine g_engine; void Engine::init() @@ -54,31 +56,57 @@ void Engine::terminate() void Engine::run() { - ulong ticks; - static ulong lastFrameTicks; - + int ticks = Platform::getTicks(); + int lastUpdateTicks = ticks; + int lastFpsTicks = ticks; + int updateElapsedTicks = ticks; + int frameCount = 0; + int fps = 0; m_running = true; - lastFrameTicks = Platform::getTicks(); + // before redering do the first update + update(ticks, 0); + lastUpdateTicks = ticks; + + Font *font = g_fonts.getDefault(); + Point fpsPos(10,10); + while(!m_stopping) { // fire platform events Platform::poll(); - // update + // update before redering ticks = Platform::getTicks(); - update(ticks, ticks - lastFrameTicks); - lastFrameTicks = ticks; + updateElapsedTicks = ticks - lastUpdateTicks; + if(updateElapsedTicks >= MINIMUN_UPDATE_DELAY) { + update(ticks, updateElapsedTicks); + lastUpdateTicks = ticks; + } // render only when visible - //if(Platform::isWindowVisible()) { + if(Platform::isWindowVisible()) { + // calculate and fps + if(m_calculateFps && font) { + frameCount++; + if(ticks - lastFpsTicks >= 1000) { + lastFpsTicks = ticks; + fps = frameCount; + frameCount = 0; + } + } + render(); + // render fps + if(m_calculateFps && font) { + font->renderText(fpsPos, format("FPS: %d", fps)); + } + // swap buffers Platform::swapBuffers(); - //} + } } - lastFrameTicks = 0; m_stopping = false; m_running = false; } diff --git a/src/framework/engine.h b/src/framework/engine.h index 14a7a90e..99e9b9a1 100644 --- a/src/framework/engine.h +++ b/src/framework/engine.h @@ -36,6 +36,7 @@ class Engine public: Engine() : m_stopping(false), m_running(false), + m_calculateFps(false), m_currentState(NULL) { } void init(); @@ -60,6 +61,9 @@ public: /// Fired by platform on mouse/keyboard input void onInputEvent(InputEvent *event); + /// Enable FPS counter on screen + void enableFpsCounter(bool enable = true) { m_calculateFps = enable; }; + private: /// Called to render every frame void render(); @@ -68,6 +72,7 @@ private: bool m_stopping; bool m_running; + bool m_calculateFps; GameState *m_currentState; }; diff --git a/src/framework/font.cpp b/src/framework/font.cpp index e68fb8c4..a9c746ba 100644 --- a/src/framework/font.cpp +++ b/src/framework/font.cpp @@ -109,25 +109,27 @@ void Font::renderText(const Point& pos, const std::string& text) Point currentPos = pos; const Size& screenSize = g_graphics.getScreenSize(); + const Size& textureSize = m_texture->getSize(); int textLenght = text.length(); for(int i = 0; i < textLenght; ++i) { - int c = (int)text[i]; + int glyph = (int)text[i]; // break rendering if the Y pos is below the screen if(currentPos.y >= screenSize.height()) break; // new line - if(c == '\n') { + if(glyph == (uchar)'\n') { currentPos.y += m_lineHeight; currentPos.x = pos.x; } - // render glyph - else { - // render online if is visible on screen - if(currentPos.x < screenSize.width()) - currentPos.x += renderGlyph(currentPos, c); + // render only if the glyph is valid and visible + else if(glyph >= 32 && currentPos.x < screenSize.width()) { + g_graphics._drawTexturedRect(Rect(currentPos, m_glyphsSize[glyph]), + m_glyphsTextureCoords[glyph], + textureSize); + currentPos.x += m_glyphsSize[glyph].width(); } } @@ -136,15 +138,23 @@ void Font::renderText(const Point& pos, const std::string& text) g_graphics.resetColor(); } -int Font::renderGlyph(const Point& pos, int glyph) +Size Font::calculateTextSize(const std::string& text) { - // don't render invalid glyphs - if(glyph < 32) - return 0; + int textLenght = text.length(); + Size size; + Point currentPos; - // render glyph - Rect screenCoords(pos, m_glyphsSize[glyph]); - g_graphics._drawTexturedRect(screenCoords, m_glyphsTextureCoords[glyph], m_texture->getSize()); + for(int i = 0; i < textLenght; ++i) { + int glyph = (int)text[i]; - return m_glyphsSize[glyph].width(); + if(glyph == (uchar)'\n') { + currentPos.y += m_lineHeight; + size.expandedTo(currentPos.toSize()); + currentPos.x = 0; + } + else if(glyph > 32) { + currentPos.x += m_glyphsSize[glyph].width(); + } + } + return size; } diff --git a/src/framework/font.h b/src/framework/font.h index 29b2aed3..dc50d42c 100644 --- a/src/framework/font.h +++ b/src/framework/font.h @@ -39,9 +39,21 @@ public: /// Load font from file bool load(const std::string &file); - /// Simple text render + /// Simple text render starting at pos void renderText(const Point& pos, const std::string& text); + /// Render text delimited by screenCoords rect + void renderText(const Rect& screenCoords, const std::string& text); + + /** Advanced text render + * screenCoords is the rect that will be filled on the screen + * startRenderPosition is the postion to start rendering relative to the text rect + */ + void renderText(const Rect& screenCoords, const Point& startRenderPosition, const std::string& text); + + /// Simulate render and calculate text size + Size calculateTextSize(const std::string& text); + /* enum EAlign { ALIGN_TOP = 1 << 0, @@ -60,9 +72,6 @@ public: void renderText(const Rect& screenCoords, EAlign align, const std::string& text); */ - /// Render a text - int renderGlyph(const Point& pos, int glyph); - private: int m_lineHeight; int m_cursorSize; diff --git a/src/framework/fonts.cpp b/src/framework/fonts.cpp index 86c5ebb9..fd0d2213 100644 --- a/src/framework/fonts.cpp +++ b/src/framework/fonts.cpp @@ -51,3 +51,13 @@ Font* Fonts::get(const std::string& fontName) error("Font \"%s\" not found", fontName.c_str()); return NULL; } + +Font *Fonts::getDefault() +{ + Font *font = get("tibia-10px-rounded"); + if(font) { + return font; + } + fatal("Default font not found!"); + return NULL; +} diff --git a/src/framework/fonts.h b/src/framework/fonts.h index c233d21f..119a00c6 100644 --- a/src/framework/fonts.h +++ b/src/framework/fonts.h @@ -39,6 +39,9 @@ public: /// Get a font by name Font *get(const std::string& fontName); + /// Get default font + Font *getDefault(); + /// Terminate all fonts void terminate() { } diff --git a/src/main.cpp b/src/main.cpp index 769b77c2..20298e0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -101,7 +101,7 @@ int main(int argc, const char *argv[]) 640, 480, g_configs.getBoolean("window maximized")); Platform::setWindowTitle("OTClient"); - Platform::setVsync(); + //Platform::setVsync(); // init engine g_engine.init(); @@ -113,6 +113,7 @@ int main(int argc, const char *argv[]) Platform::showWindow(); //Platform::hideMouseCursor(); + g_engine.enableFpsCounter(); // main loop, run everything g_engine.run(); diff --git a/src/menustate.cpp b/src/menustate.cpp index 8c90eb65..63b139e4 100644 --- a/src/menustate.cpp +++ b/src/menustate.cpp @@ -67,14 +67,7 @@ void MenuState::render() Rect texCoords(0, 0, texCoordsSize); texCoords.moveBottomRight(texSize.toPoint()); g_graphics.drawTexturedRect(Rect(0, 0, screenSize), m_background.get(), texCoords); - - Font *font = g_fonts.get("sans-11px-antialised"); - if(font) - font->renderText(Point(10,10), "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac orci id quam condimentum semper."); - - font = g_fonts.get("tibia-10px-rounded"); - if(font) - font->renderText(Point(10,30), "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac orci id quam condimentum semper."); + g_fonts.getDefault()->renderText(Point(10,screenSize.height() - 20), "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac orci id quam condimentum semper."); } void MenuState::update(int ticks, int elapsedTicks)