// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #ifndef _GLEST_GAME_RENDERER_H_ #define _GLEST_GAME_RENDERER_H_ #ifdef WIN32 #include #include #endif #include "vec.h" #include "math_util.h" #include "model.h" #include "particle.h" #include "pixmap.h" #include "font.h" #include "matrix.h" #include "selection.h" #include "components.h" #include "texture.h" #include "model_manager.h" #include "graphics_factory_gl.h" #include "font_manager.h" #include "camera.h" #include #include "model_renderer.h" #include "model.h" #include "graphics_interface.h" #include "base_renderer.h" #include "simple_threads.h" #include "video_player.h" #ifdef DEBUG_RENDERING_ENABLED # define IF_DEBUG_EDITION(x) x # include "debug_renderer.h" #else # define IF_DEBUG_EDITION(x) #endif #include "leak_dumper.h" enum DebugUILevelType { debugui_fps = 0x01, debugui_unit_titles = 0x02 }; namespace Glest{ namespace Game{ using namespace ::Shared::Graphics; using namespace ::Shared::PlatformCommon; //non shared classes class Config; class Game; class GameCamera; class MainMenu; class Console; class MenuBackground; class ChatManager; class Object; class ConsoleLineInfo; class SurfaceCell; class Program; // ===================================================== // class MeshCallbackTeamColor // ===================================================== class MeshCallbackTeamColor: public MeshCallback { private: const Texture *teamTexture; public: MeshCallbackTeamColor() : MeshCallback() { teamTexture = NULL; } void setTeamTexture(const Texture *teamTexture) {this->teamTexture= teamTexture;} virtual void execute(const Mesh *mesh); static bool noTeamColors; }; // =========================================================== // class Renderer // /// OpenGL renderer, uses the shared library // =========================================================== class VisibleQuadContainerCache { protected: inline void CopyAll(const VisibleQuadContainerCache &obj) { cacheFrame = obj.cacheFrame; visibleObjectList = obj.visibleObjectList; visibleUnitList = obj.visibleUnitList; visibleQuadUnitList = obj.visibleQuadUnitList; visibleQuadUnitBuildList = obj.visibleQuadUnitBuildList; visibleScaledCellList = obj.visibleScaledCellList; visibleScaledCellToScreenPosList = obj.visibleScaledCellToScreenPosList; lastVisibleQuad = obj.lastVisibleQuad; frustumData = obj.frustumData; proj = obj.proj; modl = obj.modl; frustumDataCache = obj.frustumDataCache; } public: inline VisibleQuadContainerCache() { cacheFrame = 0; clearFrustumData(); clearCacheData(); } inline VisibleQuadContainerCache(const VisibleQuadContainerCache &obj) { CopyAll(obj); } inline VisibleQuadContainerCache & operator=(const VisibleQuadContainerCache &obj) { CopyAll(obj); return *this; } inline void clearCacheData() { clearVolatileCacheData(); clearNonVolatileCacheData(); } inline void clearVolatileCacheData() { visibleUnitList.clear(); visibleQuadUnitList.clear(); visibleQuadUnitBuildList.clear(); //inVisibleUnitList.clear(); visibleUnitList.reserve(500); visibleQuadUnitList.reserve(500); visibleQuadUnitBuildList.reserve(100); } inline void clearNonVolatileCacheData() { visibleObjectList.clear(); visibleScaledCellList.clear(); visibleScaledCellToScreenPosList.clear(); visibleObjectList.reserve(500); visibleScaledCellList.reserve(500); } inline void clearFrustumData() { frustumData = vector >(6,vector(4,0)); proj = vector(16,0); modl = vector(16,0); frustumDataCache.clear(); } int cacheFrame; Quad2i lastVisibleQuad; std::vector visibleObjectList; std::vector visibleQuadUnitList; std::vector visibleQuadUnitBuildList; std::vector visibleUnitList; std::vector visibleScaledCellList; std::map visibleScaledCellToScreenPosList; static bool enableFrustumCalcs; vector > frustumData; vector proj; vector modl; map,vector >, vector > > frustumDataCache; }; class VisibleQuadContainerVBOCache { public: // Vertex Buffer Object Names bool hasBuiltVBOs; uint32 m_nVBOVertices; // Vertex VBO Name uint32 m_nVBOFowTexCoords; // Texture Coordinate VBO Name for fog of war texture coords uint32 m_nVBOSurfaceTexCoords; // Texture Coordinate VBO Name for surface texture coords uint32 m_nVBONormals; // Normal VBO Name //uint32 m_nVBOIndexes; // Indexes VBO Name }; enum ConsoleMode { consoleOff, consoleNormal, consoleFull, consoleStoredOnly, consoleStoredAndNormal, consoleCount }; class Renderer : public RendererInterface, public BaseRenderer, // This is for screen saver thread public SimpleTaskCallbackInterface, public VideoLoadingCallbackInterface { public: //progress bar static const int maxProgressBar; static const Vec4f progressBarBack1; static const Vec4f progressBarBack2; static const Vec4f progressBarFront1; static const Vec4f progressBarFront2; //sun and moon static const float sunDist; static const float moonDist; static const float lightAmbFactor; //mouse static const int maxMouse2dAnim; //texture units static const GLenum baseTexUnit; static const GLenum fowTexUnit; static const GLenum shadowTexUnit; //selection static const float selectionCircleRadius; static const float magicCircleRadius; //perspective values static const float perspFov; static const float perspNearPlane; static float perspFarPlane; //default values static const float ambFactor; static const Vec4f defSpecularColor; static const Vec4f defDiffuseColor; static const Vec4f defAmbientColor; static const Vec4f defColor; static const Vec4f fowColor; //light static const float maxLightDist; static bool renderText3DEnabled; public: enum Shadows { sDisabled, sProjected, sShadowMapping, sCount }; private: //config int maxLights; bool photoMode; int shadowTextureSize; int shadowFrameSkip; float shadowIntensity; bool focusArrows; bool textures3D; Shadows shadows; int maxConsoleLines; //game const Game *game; GameCamera *gameCamera; const MainMenu *menu; Program *program; //misc int triangleCount; int pointCount; Quad2i visibleQuad; Quad2i visibleQuadFromCamera; Vec4f nearestLightPos; VisibleQuadContainerCache quadCache; VisibleQuadContainerCache quadCacheSelection; //renderers ModelRenderer *modelRenderer; TextRenderer2D *textRenderer; TextRenderer3D *textRenderer3D; ParticleRenderer *particleRenderer; //texture managers ModelManager *modelManager[rsCount]; TextureManager *textureManager[rsCount]; FontManager *fontManager[rsCount]; ParticleManager *particleManager[rsCount]; //state lists //GLuint list3d; //bool list3dValid; //GLuint list2d; //bool list2dValid; //GLuint list3dMenu; //bool list3dMenuValid; //GLuint *customlist3dMenu; //const MainMenu *mm3d; const MainMenu *custom_mm3d; //shadows GLuint shadowMapHandle; bool shadowMapHandleValid; Matrix4f shadowMapMatrix; int shadowMapFrame; //water float waterAnim; bool allowRenderUnitTitles; //std::vector > renderUnitTitleList; std::vector visibleFrameUnitList; string visibleFrameUnitListCameraKey; bool no2DMouseRendering; bool showDebugUI; int showDebugUILevel; int lastRenderFps; float smoothedRenderFps; bool shadowsOffDueToMinRender; std::vector > deferredParticleSystems; SimpleTaskThread *saveScreenShotThread; Mutex *saveScreenShotThreadAccessor; std::list > saveScreenQueue; std::map worldToScreenPosCache; //bool masterserverMode; std::map mapSurfaceVBOCache; class SurfaceData { public: inline SurfaceData() { uniqueId=0; bufferCount=0; textureHandle=0; } static uint32 nextUniqueId; uint32 uniqueId; int bufferCount; int textureHandle; vector texCoords; vector texCoordsSurface; vector vertices; vector normals; }; //VisibleQuadContainerVBOCache * GetSurfaceVBOs(SurfaceData *cellData); void ReleaseSurfaceVBOs(); std::map > > mapSurfaceData; static bool rendererEnded; class MapRenderer { public: inline MapRenderer(): map(NULL) {} inline ~MapRenderer() { destroy(); } void render(const Map* map,float coordStep,VisibleQuadContainerCache &qCache); void renderVisibleLayers(const Map* map,float coordStep,VisibleQuadContainerCache &qCache); void destroy(); private: void load(float coordStep); void loadVisibleLayers(float coordStep,VisibleQuadContainerCache &qCache); const Map* map; struct Layer { inline explicit Layer(int th): vbo_vertices(0), vbo_normals(0), vbo_fowTexCoords(0), vbo_surfTexCoords(0), vbo_indices(0), indexCount(0), textureHandle(th),textureCRC(0) {} inline explicit Layer(Layer &obj) { *this = obj; } inline Layer & operator=(Layer &obj) { this->vertices = obj.vertices; this->normals = obj.normals; this->fowTexCoords = obj.fowTexCoords; this->surfTexCoords = obj.surfTexCoords; this->indices = obj.indices; this->cellToIndicesMap = obj.cellToIndicesMap; this->rowsToRenderCache = obj.rowsToRenderCache; this->vbo_vertices = obj.vbo_vertices; this->vbo_normals = obj.vbo_normals; this->vbo_fowTexCoords = obj.vbo_fowTexCoords; this->vbo_surfTexCoords = obj.vbo_surfTexCoords; this->vbo_indices = obj.vbo_indices; this->indexCount = obj.indexCount; this->textureHandle = obj.textureHandle; this->texturePath = obj.texturePath; this->textureCRC = obj.textureCRC; return *this; } ~Layer(); void load_vbos(bool vboEnabled); void render(VisibleQuadContainerCache &qCache); void renderVisibleLayer(); std::vector vertices, normals; std::vector fowTexCoords, surfTexCoords; std::vector indices; std::map cellToIndicesMap; std::map > > rowsToRenderCache; GLuint vbo_vertices, vbo_normals, vbo_fowTexCoords, vbo_surfTexCoords, vbo_indices; int indexCount; int textureHandle; string texturePath; uint32 textureCRC; }; typedef std::vector Layers; Layers layers; Quad2i lastVisibleQuad; } mapRenderer; bool ExtractFrustum(VisibleQuadContainerCache &quadCacheItem); //bool PointInFrustum(vector > &frustum, float x, float y, float z ); //bool SphereInFrustum(vector > &frustum, float x, float y, float z, float radius); bool CubeInFrustum(vector > &frustum, float x, float y, float z, float size ); private: Renderer(); ~Renderer(); public: static Renderer &getInstance(); static bool isEnded(); //bool isMasterserverMode() const { return masterserverMode; } void addToDeferredParticleSystemList(std::pair deferredParticleSystem); void manageDeferredParticleSystems(); void reinitAll(); //init void init(); void initGame(const Game *game, GameCamera *gameCamera); void initMenu(const MainMenu *mm); void reset3d(); void reset2d(); void reset3dMenu(); //end void end(); void endScenario(); void endMenu(); void endGame(bool isFinalEnd); //get inline int getTriangleCount() const {return triangleCount;} inline int getPointCount() const {return pointCount;} //misc //void reloadResources(); //engine interface void initTexture(ResourceScope rs, Texture *texture); void endTexture(ResourceScope rs, Texture *texture,bool mustExistInList=false); void endLastTexture(ResourceScope rs, bool mustExistInList=false); Model *newModel(ResourceScope rs,const string &path,bool deletePixMapAfterLoad=false,std::map > > *loadedFileList=NULL, string *sourceLoader=NULL); void endModel(ResourceScope rs, Model *model, bool mustExistInList=false); void endLastModel(ResourceScope rs, bool mustExistInList=false); Texture2D *newTexture2D(ResourceScope rs); Texture3D *newTexture3D(ResourceScope rs); Font2D *newFont(ResourceScope rs); Font3D *newFont3D(ResourceScope rs); void endFont(::Shared::Graphics::Font *font, ResourceScope rs, bool mustExistInList=false); //void resetFontManager(ResourceScope rs); inline TextRenderer2D *getTextRenderer() const {return textRenderer;} inline TextRenderer3D *getTextRenderer3D() const {return textRenderer3D;} void manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs); void cleanupParticleSystems(vector &particleSystems,ResourceScope rs); void cleanupUnitParticleSystems(vector &particleSystems,ResourceScope rs); bool validateParticleSystemStillExists(ParticleSystem * particleSystem,ResourceScope rs) const; void removeParticleSystemsForParticleOwner(ParticleOwner * particleOwner,ResourceScope rs); void updateParticleManager(ResourceScope rs,int renderFps=-1); void renderParticleManager(ResourceScope rs); void swapBuffers(); //lights and camera void setupLighting(); //void setupLightingForRotatedModel(); void loadGameCameraMatrix(); void loadCameraMatrix(const Camera *camera); void computeVisibleQuad(); //basic rendering void renderMouse2d(int mouseX, int mouseY, int anim, float fade= 0.f); void renderMouse3d(); void renderGhostModel(const UnitType *building, const Vec2i pos,CardinalDir facing,Vec4f *forceColor=NULL); void renderBackground(const Texture2D *texture); void renderTextureQuad(int x, int y, int w, int h, const Texture2D *texture, float alpha=1.f,const Vec3f *color=NULL); void renderConsole(const Console *console, ConsoleMode mode=consoleNormal, int overrideMaxConsoleLines=-1); void renderConsoleLine3D(int lineIndex, int xPosition, int yPosition, int lineHeight, Font3D* font, string stringToHightlight, const ConsoleLineInfo *lineInfo); void renderConsoleLine(int lineIndex, int xPosition, int yPosition, int lineHeight, Font2D* font, string stringToHightlight, const ConsoleLineInfo *lineInfo); void renderChatManager(const ChatManager *chatManager); void renderClock(); void renderPerformanceStats(); void renderResourceStatus(); void renderSelectionQuad(); void renderText(const string &text, Font2D *font, float alpha, int x, int y, bool centered= false); void renderText(const string &text, Font2D *font, const Vec3f &color, int x, int y, bool centered= false); void renderText(const string &text, Font2D *font, const Vec4f &color, int x, int y, bool centered=false); void renderTextShadow(const string &text, Font2D *font,const Vec4f &color, int x, int y, bool centered= false); void renderText3D(const string &text, Font3D *font, float alpha, int x, int y, bool centered); void renderText3D(const string &text, Font3D *font, const Vec3f &color, int x, int y, bool centered); void renderText3D(const string &text, Font3D *font, const Vec4f &color, int x, int y, bool centered); void renderTextShadow3D(const string &text, Font3D *font,const Vec4f &color, int x, int y, bool centered=false); void renderProgressBar3D(int size, int x, int y, Font3D *font, int customWidth=-1, string prefixLabel="", bool centeredText=true,int customHeight=-1); Vec2f getCentered3DPos(const string &text, Font3D *font, Vec2f &pos, int w, int h, bool centeredW, bool centeredH); void renderTextBoundingBox3D(const string &text, Font3D *font, const Vec4f &color, int x, int y, int w, int h, bool centeredW, bool centeredH, bool editModeEnabled, int maxEditWidth, int maxEditRenderWidth); void renderTextBoundingBox3D(const string &text, Font3D *font, const Vec3f &color, int x, int y, int w, int h, bool centeredW, bool centeredH, bool editModeEnabled,int maxEditWidth, int maxEditRenderWidth); void renderTextBoundingBox3D(const string &text, Font3D *font, float alpha, int x, int y, int w, int h, bool centeredW, bool centeredH, bool editModeEnabled,int maxEditWidth, int maxEditRenderWidth); void renderTextSurroundingBox(int x, int y, int w, int h,int maxEditWidth, int maxEditRenderWidth); void beginRenderToTexture(Texture2D **renderToTexture); void endRenderToTexture(Texture2D **renderToTexture); void renderFPSWhenEnabled(int lastFps); //components void renderLabel(GraphicLabel *label); void renderLabel(GraphicLabel *label,const Vec3f *color); void renderLabel(GraphicLabel *label,const Vec4f *color); void renderButton(GraphicButton *button,const Vec4f *fontColorOverride=NULL,bool *lightedOverride=NULL); void renderCheckBox(const GraphicCheckBox *box); void renderLine(const GraphicLine *line); void renderScrollBar(const GraphicScrollBar *sb); void renderListBox(GraphicListBox *listBox); void renderComboBox(GraphicComboBox *comboBox); void renderMessageBox(GraphicMessageBox *listBox); void renderPopupMenu(PopupMenu *menu); //complex rendering void renderSurface(const int renderFps); void renderObjects(const int renderFps); void renderWater(); void renderUnits(bool airUnits, const int renderFps); void renderUnitsToBuild(const int renderFps); void renderSelectionEffects(int healthbarMode); void renderHealthBars(int healthbarMode); void renderWaterEffects(); void renderHud(); void renderMinimap(); void renderDisplay(); void renderMenuBackground(const MenuBackground *menuBackground); void renderMapPreview(const MapPreview *map, bool renderAll, int screenX, int screenY,Texture2D **renderToTexture=NULL); void renderMenuBackground(Camera *camera, float fade, Model *mainModel, vector characterModels,const Vec3f characterPosition, float anim); //computing bool ccomputePosition(const Vec2i &screenPos, Vec2i &worldPos,bool exactCoords=false); void computeSelected(Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection, const Vec2i &posDown, const Vec2i &posUp); void selectUsingColorPicking(Selection::UnitContainer &units, const Object *&obj,const bool withObjectSelection,const Vec2i &posDown, const Vec2i &posUp); void selectUsingSelectionBuffer(Selection::UnitContainer &units,const Object *&obj, const bool withObjectSelection,const Vec2i &posDown, const Vec2i &posUp); void selectUsingFrustumSelection(Selection::UnitContainer &units,const Object *&obj, const bool withObjectSelection,const Vec2i &posDown, const Vec2i &posUp); //gl wrap string getGlInfo(); string getGlMoreInfo(); void autoConfig(); //clear void clearBuffers(); void clearZBuffer(); //shadows void renderShadowsToTexture(const int renderFps); //misc void loadConfig(); void saveScreen(const string &path,int w=0, int h=0); inline Quad2i getVisibleQuad() const {return visibleQuad;} inline Quad2i getVisibleQuadFromCamera() const {return visibleQuadFromCamera;} void renderTeamColorPlane(); void renderSpecialHighlightUnits(std::map unitHighlightList); void renderTeamColorCircle(); void renderMorphEffects(); //static static Shadows strToShadows(const string &s); static string shadowsToStr(Shadows shadows); inline const Game * getGame() { return game; } void setAllowRenderUnitTitles(bool value); inline bool getAllowRenderUnitTitles() { return allowRenderUnitTitles; } void renderUnitTitles(Font2D *font, Vec3f color); void renderUnitTitles3D(Font3D *font, Vec3f color); Vec3f computeScreenPosition(const Vec3f &worldPos); void setPhotoMode(bool value) { photoMode = value; } inline bool getNo2DMouseRendering() const { return no2DMouseRendering; } void setNo2DMouseRendering(bool value) { no2DMouseRendering = value; } inline bool getShowDebugUI() const { return showDebugUI; } void setShowDebugUI(bool value) { showDebugUI = value; } inline int getShowDebugUILevel() const { return showDebugUILevel; } void setShowDebugUILevel(int value) { showDebugUILevel=value; } void cycleShowDebugUILevel(); void setLastRenderFps(int value); inline int getLastRenderFps() const { return lastRenderFps;} VisibleQuadContainerCache & getQuadCache(bool updateOnDirtyFrame=true,bool forceNew=false); std::pair posInCellQuadCache(Vec2i pos); //Vec3f getMarkedCellScreenPosQuadCache(Vec2i pos); void updateMarkedCellScreenPosQuadCache(Vec2i pos); void forceQuadCacheUpdate(); void renderVisibleMarkedCells(bool renderTextHint=false,int x=-1, int y=-1); void renderMarkedCellsOnMinimap(); void renderHighlightedCellsOnMinimap(); void removeObjectFromQuadCache(const Object *o); void removeUnitFromQuadCache(const Unit *unit); std::size_t getCurrentPixelByteCount(ResourceScope rs=rsGame) const; unsigned int getSaveScreenQueueSize(); //Texture2D *saveScreenToTexture(int x, int y, int width, int height); void renderProgressBar(int size, int x, int y, Font2D *font,int customWidth=-1, string prefixLabel="", bool centeredText=true); static Texture2D * findTexture(string logoFilename); static Texture2D * preloadTexture(string logoFilename); inline int getCachedSurfaceDataSize() const { return (int)mapSurfaceData.size(); } //void setCustom3dMenuList(GLuint *customlist3dMenu) { this->customlist3dMenu = customlist3dMenu; } //inline GLuint * getCustom3dMenuList() const { return this->customlist3dMenu; } void setCustom3dMenu(const MainMenu *mm) { this->custom_mm3d = mm; } const MainMenu * getCustom3dMenu() { return this->custom_mm3d; } //void init3dListMenu(const MainMenu *mm); void setProgram(Program *program) { this->program = program; } void setupRenderForVideo(); virtual void renderVideoLoading(int progressPercent); private: //private misc float computeSunAngle(float time); float computeMoonAngle(float time); Vec4f computeSunPos(float time); Vec4f computeMoonPos(float time); inline Vec4f computeWaterColor(float waterLevel, float cellHeight) { const float waterFactor= 1.5f; return Vec4f(1.f, 1.f, 1.f, clamp((waterLevel-cellHeight) * waterFactor, 0.f, 1.f)); } void checkExtension(const string &extension, const string &msg); //selection render vector renderObjectsFast(bool renderingShadows = false, bool resourceOnly = false, bool colorPickingSelection = false); vector renderUnitsFast(bool renderingShadows = false, bool colorPickingSelection = false); //gl requirements void checkGlCaps(); void checkGlOptionalCaps(); //gl init void init3dList(); void init2dList(); //misc void loadProjectionMatrix(); void enableProjectiveTexturing(); //private aux drawing void renderSelectionCircle(Vec3f v, int size, float radius, float thickness=0.2f); bool isHealthBarVisible(const Unit *unit,int healthbarMode); void renderHealthBar(Vec3f v, Unit *unit, float height, bool lineBorder, const Texture2D *texture=NULL, const Texture2D *backgroundTexture=NULL); void internalRenderHp(int numberOfBars, int barNumber, float hp, Vec3f posVector, float width, float singleHPheight, Vec3f rightVector, Vec3f upVector); void renderTeamColorEffect(Vec3f &v, int heigth, int size, Vec3f color, const Texture2D *texture); void renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width); //void renderTile(const Vec2i &pos); void renderQuad(int x, int y, int w, int h, const Texture2D *texture); void simpleTask(BaseThread *callingThread,void *userdata); //static static Texture2D::Filter strToTextureFilter(const string &s); void cleanupScreenshotThread(); void render2dMenuSetup(); void render3dSetup(); void render3dMenuSetup(const MainMenu *mm); int renderResource(const Faction *factionForResourceView, bool localFactionResourcesOnly,bool twoResourceLines, const ResourceType *rt, int startRow, int &resourceCountRendered); }; }} //end namespace #endif