From 61bfb22f27f5216f989c023a5e39fad7e356d2d6 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 3 Aug 2012 23:23:13 +0200 Subject: Basic font rendering - added basic font rendering - minor refactoring & fixes --- src/graphics/core/device.h | 9 +- src/graphics/engine/engine.cpp | 148 +++++++----- src/graphics/engine/engine.h | 31 ++- src/graphics/engine/text.cpp | 477 ++++++++++++++++++++++++++++++++++++++- src/graphics/engine/text.h | 267 ++++++++++++++++++---- src/graphics/opengl/gldevice.cpp | 39 ++-- src/graphics/opengl/gldevice.h | 5 +- 7 files changed, 837 insertions(+), 139 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index c10b853..3ab86dd 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -32,6 +32,7 @@ class CImage; +struct ImageData; namespace Gfx { @@ -279,8 +280,6 @@ public: //! Destroys the device, releasing every acquired resource virtual void Destroy() = 0; - //! Returns whether the device has been initialized - virtual bool GetWasInit() = 0; //! Returns the last encountered error virtual std::string GetError() = 0; @@ -317,6 +316,8 @@ public: //! Creates a texture from image; the image can be safely removed after that virtual Gfx::Texture CreateTexture(CImage *image, const Gfx::TextureCreateParams ¶ms) = 0; + //! Creates a texture from raw image data; image data can be freed after that + virtual Gfx::Texture CreateTexture(ImageData *data, const Gfx::TextureCreateParams ¶ms) = 0; //! Deletes a given texture, freeing it from video memory virtual void DestroyTexture(const Gfx::Texture &texture) = 0; //! Deletes all textures created so far @@ -324,8 +325,10 @@ public: //! Returns the maximum number of multitexture stages virtual int GetMaxTextureCount() = 0; - //! Sets the (multi)texture at given index + //! Sets the texture at given texture stage virtual void SetTexture(int index, const Gfx::Texture &texture) = 0; + //! Sets the texture image by ID at given texture stage + virtual void SetTexture(int index, unsigned int textureId) = 0; //! Returns the (multi)texture at given index virtual Gfx::Texture GetTexture(int index) = 0; //! Enables/disables the given texture stage diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index e544ee3..345a15c 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -25,6 +25,8 @@ #include "common/key.h" #include "common/logger.h" #include "graphics/core/device.h" +#include "graphics/engine/lightman.h" +#include "graphics/engine/text.h" #include "math/geometry.h" // Initial size of various vectors @@ -44,23 +46,21 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) { m_iMan = iMan; m_app = app; - m_device = NULL; - - m_wasInit = false; + m_device = nullptr; m_iMan = iMan; m_iMan->AddInstance(CLASS_ENGINE, this); m_app = app; - m_lightMan = NULL; - m_text = NULL; - m_particle = NULL; - m_water = NULL; - m_cloud = NULL; - m_lightning = NULL; - m_planet = NULL; - m_sound = NULL; - m_terrain = NULL; + m_lightMan = nullptr; + m_text = nullptr; + m_particle = nullptr; + m_water = nullptr; + m_cloud = nullptr; + m_lightning = nullptr; + m_planet = nullptr; + m_sound = nullptr; + m_terrain = nullptr; m_focus = 0.75f; m_baseTime = 0; @@ -178,95 +178,93 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) Gfx::CEngine::~CEngine() { - m_iMan = NULL; - m_app = NULL; - m_device = NULL; + m_iMan = nullptr; + m_app = nullptr; + m_device = nullptr; - m_sound = NULL; - m_terrain = NULL; + m_sound = nullptr; + m_terrain = nullptr; } -bool Gfx::CEngine::GetWasInit() +std::string Gfx::CEngine::GetError() { - return m_wasInit; + return m_error; } -std::string Gfx::CEngine::GetError() +void Gfx::CEngine::SetDevice(Gfx::CDevice *device) { - return m_error; + m_device = device; +} + +Gfx::CDevice* Gfx::CEngine::GetDevice() +{ + return m_device; } bool Gfx::CEngine::Create() { - m_wasInit = true; + m_size = m_lastSize = m_app->GetVideoConfig().size; - /*m_lightMan = new Gfx::CLight(m_iMan, this); + m_lightMan = new Gfx::CLightManager(m_iMan, this); m_text = new Gfx::CText(m_iMan, this); + /* TODO: m_particle = new Gfx::CParticle(m_iMan, this); m_water = new Gfx::CWater(m_iMan, this); m_cloud = new Gfx::CCloud(m_iMan, this); m_lightning = new Gfx::CLightning(m_iMan, this); m_planet = new Gfx::CPlanet(m_iMan, this);*/ + m_text->SetDevice(m_device); + if (! m_text->Create()) + { + m_error = std::string("Error creating CText: ") + m_text->GetError(); + return false; + } + + m_matWorldInterface.LoadIdentity(); m_matViewInterface.LoadIdentity(); Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + + Gfx::TextureCreateParams params; + params.format = Gfx::TEX_IMG_RGB; + params.minFilter = Gfx::TEX_MIN_FILTER_NEAREST; + params.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; + params.mipmap = false; + m_miceTexture = CreateTexture("mouse.png", params); + return true; } void Gfx::CEngine::Destroy() { - // TODO + m_text->Destroy(); - /*delete m_lightMan; - m_lightMan = NULL; + delete m_lightMan; + m_lightMan = nullptr; delete m_text; - m_text = NULL; + m_text = nullptr; + /* TODO: delete m_particle; - m_particle = NULL; + m_particle = nullptr; delete m_water; - m_water = NULL; + m_water = nullptr; delete m_cloud; - m_cloud = NULL; + m_cloud = nullptr; delete m_lightning; - m_lightning = NULL; + m_lightning = nullptr; delete m_planet; - m_planet = NULL;*/ - - m_wasInit = false; -} - -void Gfx::CEngine::SetDevice(Gfx::CDevice *device) -{ - m_device = device; -} - -Gfx::CDevice* Gfx::CEngine::GetDevice() -{ - return m_device; -} - -bool Gfx::CEngine::AfterDeviceSetInit() -{ - m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); - - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); - - Gfx::TextureCreateParams params; - params.format = Gfx::TEX_IMG_RGB; - params.minFilter = Gfx::TEX_MIN_FILTER_NEAREST; - params.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; - params.mipmap = false; - m_miceTexture = CreateTexture("mouse.png", params); - - return true; + m_planet = nullptr;*/ } void Gfx::CEngine::ResetAfterDeviceChanged() @@ -274,7 +272,6 @@ void Gfx::CEngine::ResetAfterDeviceChanged() // TODO } - Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) { CImage img; @@ -610,9 +607,38 @@ bool Gfx::CEngine::DrawInterface() DrawMouse(); + m_text->DrawString("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, 0); + return true; } +/** Conversion of the position of the mouse from window coords to interface coords: + - x: 0=left, 1=right + - y: 0=down, 1=up */ +Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) +{ + return Math::Point( static_cast(pos.x) / static_cast(m_size.w), + 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); +} + +Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +{ + return Math::IntPoint(static_cast(pos.x * m_size.w), + static_cast((1.0f - pos.y) * m_size.h)); +} + +Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +{ + return Math::Size( static_cast(size.w) / static_cast(m_size.w), + static_cast(size.h) / static_cast(m_size.h) ); +} + +Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +{ + return Math::IntSize(static_cast(size.w * m_size.w), + static_cast(size.h * m_size.h)); +} + void Gfx::CEngine::DrawMouse() { if (! m_mouseVisible) diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 25c5e5d..79844c6 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -29,6 +29,7 @@ #include "math/intsize.h" #include "math/matrix.h" #include "math/point.h" +#include "math/size.h" #include "math/vector.h" @@ -514,23 +515,18 @@ public: CEngine(CInstanceManager *iMan, CApplication *app); ~CEngine(); - //! Returns whether the device was initialized - bool GetWasInit(); //! Returns the last error encountered std::string GetError(); - //! Performs the first initialization, before a device was set - bool Create(); - //! Frees all resources before exit - void Destroy(); - //! Sets the device to be used void SetDevice(Gfx::CDevice *device); //! Returns the current device Gfx::CDevice* GetDevice(); - //! Performs initialization after a device was created and set - bool AfterDeviceSetInit(); + //! Performs the initialization; must be called after device was set + bool Create(); + //! Frees all resources before exit + void Destroy(); //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) void ResetAfterDeviceChanged(); @@ -544,6 +540,17 @@ public: bool Render(); + //! Converts window coords to interface coords + Math::Point WindowToInterfaceCoords(Math::IntPoint pos); + //! Converts interface coords to window coords + Math::IntPoint InterfaceToWindowCoords(Math::Point pos); + + //! Converts window size to interface size + Math::Size WindowToInterfaceSize(Math::IntSize size); + //! Converts interface size to window size + Math::IntSize InterfaceToWindowSize(Math::Size size); + + bool WriteProfile(); void SetPause(bool pause); @@ -769,7 +776,8 @@ public: Math::Vector GetLookatPt(); float GetEyeDirH(); float GetEyeDirV(); - Math::Point GetDim(); + Math::IntPoint GetViewportSize(); + Math::IntPoint GetLastViewportSize(); void UpdateMatProj(); void ApplyChange(); @@ -903,8 +911,9 @@ protected: bool m_render; bool m_movieLock; - //! Current size of window + //! Current size of viewport Math::IntSize m_size; + //! Previous size of viewport Math::IntSize m_lastSize; std::vector m_objectTree; diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index 2a9543c..eea9fdb 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -19,5 +19,480 @@ #include "graphics/engine/text.h" +#include "app/app.h" +#include "common/image.h" +#include "common/iman.h" +#include "common/logger.h" +#include "common/stringutils.h" +#include "math/func.h" -// TODO implementation +#include +#include + + +namespace Gfx +{ + +/** + \struct CachedFont + \brief Base TTF font with UTF-8 char cache */ +struct CachedFont +{ + TTF_Font* font; + std::map cache; + + CachedFont() : font(nullptr) {} +}; + +}; + + + +Gfx::CText::CText(CInstanceManager *iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_TEXT, this); + + m_device = nullptr; + m_engine = engine; + + m_defaultSize = 12.0f; + m_fontPath = "fonts"; + + m_lastFontType = Gfx::FONT_COLOBOT; + m_lastFontSize = 0; + m_lastCachedFont = nullptr; +} + +Gfx::CText::~CText() +{ + m_iMan->DeleteInstance(CLASS_TEXT, this); + + m_iMan = nullptr; + m_device = nullptr; + m_engine = nullptr; +} + +bool Gfx::CText::Create() +{ + if (TTF_Init() != 0) + { + m_error = std::string("TTF_Init error: ") + std::string(TTF_GetError()); + return false; + } + + m_fonts[Gfx::FONT_COLOBOT] = new MultisizeFont("dvu_sans.ttf"); + m_fonts[Gfx::FONT_COLOBOT_BOLD] = new MultisizeFont("dvu_sans_bold.ttf"); + m_fonts[Gfx::FONT_COLOBOT_ITALIC] = new MultisizeFont("dvu_sans_italic.ttf"); + + m_fonts[Gfx::FONT_COURIER] = new MultisizeFont("dvu_sans_mono.ttf"); + m_fonts[Gfx::FONT_COURIER_BOLD] = new MultisizeFont("dvu_sans_mono_bold.ttf"); + + for (auto it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + Gfx::FontType type = (*it).first; + CachedFont* cf = GetOrOpenFont(type, m_defaultSize); + if (cf == nullptr || cf->font == nullptr) + return false; + } + + return true; +} + +void Gfx::CText::Destroy() +{ + for (auto it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + MultisizeFont* mf = (*it).second; + + for (auto jt = mf->fonts.begin(); jt != mf->fonts.end(); ++jt) + { + CachedFont* cf = (*jt).second; + + TTF_CloseFont(cf->font); + + cf->font = nullptr; + delete cf; + } + + mf->fonts.clear(); + delete mf; + } + + m_fonts.clear(); + + m_lastCachedFont = nullptr; + + TTF_Quit(); +} + +void Gfx::CText::SetDevice(Gfx::CDevice* device) +{ + m_device = device; +} + +std::string Gfx::CText::GetError() +{ + return m_error; +} + +void Gfx::CText::FlushCache() +{ + for (auto it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + MultisizeFont *mf = (*it).second; + for (auto jt = mf->fonts.begin(); jt != mf->fonts.end(); ++jt) + { + CachedFont *f = (*jt).second; + f->cache.clear(); + } + } +} + +void Gfx::CText::DrawText(const std::string &text, const std::vector &format, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol) +{ + // TODO +} + +void Gfx::CText::DrawText(const std::string &text, Gfx::FontType font, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol) +{ + // TODO +} + +void Gfx::CText::SizeText(const std::string &text, const std::vector &format, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end) +{ + // TODO +} + +void Gfx::CText::SizeText(const std::string &text, Gfx::FontType font, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end) +{ + // TODO +} + +float Gfx::CText::GetAscent(Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetDescent(Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetHeight(Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + + +float Gfx::CText::GetStringWidth(const std::string &text, + const std::vector &format, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetCharWidth(int character, Gfx::FontType font, float size, float offset) +{ + // TODO + return 0.0f; +} + + +int Gfx::CText::Justify(const std::string &text, const std::vector &format, + float size, float width) +{ + // TODO + return 0; +} + +int Gfx::CText::Justify(const std::string &text, Gfx::FontType font, float size, float width) +{ + // TODO + return 0; +} + +int Gfx::CText::Detect(const std::string &text, const std::vector &format, + float size, float offset) +{ + // TODO + return 0; +} + +int Gfx::CText::Detect(const std::string &text, Gfx::FontType font, float size, float offset) +{ + // TODO + return 0; +} + +void Gfx::CText::DrawString(const std::string &text, const std::vector &format, + float size, Math::Point pos, float width, int eol) +{ + // TODO +} + +void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, + float size, Math::Point pos, float width, int eol) +{ + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureEnabled(0, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + + unsigned int index = 0; + Math::Point screenPos = pos; + while (index < text.length()) + { + UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + DrawChar(ch, font, size, screenPos); + } +} + +void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) +{ + // TODO !!! + /* + float h, u1, u2, v1, v2, dp; + int icon; + + int icon = -1; + switch (color) + { + case Gfx::FONT_COLOR_LINK: + icon = 9; + break; + case Gfx::FONT_COLOR_TOKEN: + icon = 4; + break; + case Gfx::FONT_COLOR_TYPE: + icon = 5; + break; + } + icon = -1; + if ( color == COLOR_LINK ) icon = 9; // blue + if ( color == COLOR_TOKEN ) icon = 4; // orange + if ( color == COLOR_TYPE ) icon = 5; // green + if ( color == COLOR_CONST ) icon = 8; // red + if ( color == COLOR_REM ) icon = 6; // magenta + if ( color == COLOR_KEY ) icon = 10; // gray + + if ( icon == -1 ) return; + + if ( color == COLOR_LINK ) + { + m_engine->SetState(D3DSTATENORMAL); + } + + Math::IntSize vsize = m_engine->GetViewportSize(); + if (vsize.h <= 768.0f) // 1024x768 or less? + h = 1.01f / dim.y; // 1 pixel + else // more than 1024x768? + h = 2.0f / dim.y; // 2 pixels + + Math::Point p1, p2; + p1.x = pos.x; + p2.x = pos.x + width; + + if (color == Gfx::FONT_COLOR_LINK) + { + p1.y = pos.y; + p2.y = pos.y + h; // just emphasized + } + else + { + p1.y = pos.y; + p2.y = pos.y + (16.0f/256.0f)*(size/20.0f); + } + + u1 = (16.0f/256.0f)*(icon%16); + v1 = (240.0f/256.0f); + u2 = (16.0f/256.0f)+u1; + v2 = (16.0f/256.0f)+v1; + + dp = 0.5f/256.0f; + u1 += dp; + v1 += dp; + u2 -= dp; + v2 -= dp; + + Math::Vector n(0.0f, 0.0f, -1.0f); // normal + + Gfx::Vertex quad[] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)), + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); + + if (color == Gfx::FONT_COLOR_LINK) + m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE);*/ +} + +void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos) +{ + CachedFont* cf = GetOrOpenFont(font, size); + + if (cf == nullptr) + return; + + auto it = cf->cache.find(character); + CharTexture tex; + if (it != cf->cache.end()) + { + tex = (*it).second; + } + else + { + char str[] = { character.c1, character.c2, character.c3, '\0' }; + tex = CreateCharTexture(str, cf); + + if (tex.id == 0) // invalid + return; + + cf->cache[character] = tex; + } + + Math::Vector n(0.0f, 0.0f, -1.0f); // normal + + Gfx::Vertex quad[4] = + { + Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h, 0.0f), + n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), + n, Math::Point(0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h, 0.0f), + n, Math::Point(1.0f, 0.0f)), + Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), + n, Math::Point(1.0f, 1.0f)) + }; + + m_device->SetTexture(0, tex.id); + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + + pos.x += tex.charSize.w; +} + +Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) +{ + // TODO: sizing + int pointSize = static_cast(size); + + if (m_lastCachedFont != nullptr) + { + if (m_lastFontType == font && m_lastFontSize == pointSize) + return m_lastCachedFont; + } + + auto it = m_fonts.find(font); + if (it == m_fonts.end()) + { + m_error = std::string("Invalid font type ") + StrUtils::ToString(static_cast(font)); + return nullptr; + } + + MultisizeFont* mf = (*it).second; + + auto jt = mf->fonts.find(pointSize); + if (jt != mf->fonts.end()) + { + m_lastCachedFont = (*jt).second; + m_lastFontType = font; + m_lastFontSize = pointSize; + return m_lastCachedFont; + } + + std::string path = CApplication::GetInstance().GetDataFilePath(m_fontPath, mf->fileName); + + m_lastCachedFont = new CachedFont(); + m_lastCachedFont->font = TTF_OpenFont(path.c_str(), pointSize); + if (m_lastCachedFont->font == nullptr) + m_error = std::string("TTF_OpenFont error ") + std::string(TTF_GetError()); + + mf->fonts[pointSize] = m_lastCachedFont; + + return m_lastCachedFont; +} + +Gfx::CharTexture Gfx::CText::CreateCharTexture(const char* str, Gfx::CachedFont* font) +{ + CharTexture texture; + + SDL_Surface* textSurface = nullptr; + SDL_Color white = {255, 255, 255, 0}; + textSurface = TTF_RenderUTF8_Blended(font->font, str, white); + + if (textSurface == nullptr) + { + m_error = "TTF_Render error"; + return texture; + } + + int w = Math::NextPowerOfTwo(textSurface->w); + int h = Math::NextPowerOfTwo(textSurface->h); + + textSurface->flags = textSurface->flags & (~SDL_SRCALPHA); + SDL_Surface* textureSurface = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, + 0x000000ff, 0xff000000); + SDL_BlitSurface(textSurface, NULL, textureSurface, NULL); + + ImageData data; + data.surface = textureSurface; + + Gfx::TextureCreateParams createParams; + createParams.format = Gfx::TEX_IMG_RGBA; + createParams.minFilter = Gfx::TEX_MIN_FILTER_NEAREST; + createParams.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; + createParams.mipmap = false; + + Gfx::Texture tex = m_device->CreateTexture(&data, createParams); + + data.surface = nullptr; + + SDL_FreeSurface(textSurface); + SDL_FreeSurface(textureSurface); + + if (! tex.valid) + { + m_error = "Texture create error"; + return texture; + } + + texture.id = tex.id; + texture.texSize = m_engine->WindowToInterfaceSize(Math::IntSize(textureSurface->w, textureSurface->h)); + texture.charSize = m_engine->WindowToInterfaceSize(Math::IntSize(textSurface->w, textSurface->h)); + + return texture; +} diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index c2de220..19d9882 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -19,95 +19,268 @@ #pragma once -#include "graphics/engine/engine.h" -#include "graphics/core/device.h" #include "math/point.h" +#include "math/size.h" +#include +#include class CInstanceManager; - namespace Gfx { -const float SMALLFONT = 10.0f; -const float BIGFONT = 15.0f; +class CEngine; +class CDevice; + +//! Standard small font size +const float FONT_SIZE_SMALL = 10.0f; +//! Standard big font size +const float FONT_SIZE_BIG = 15.0f; + +/** + \enum TextAlignType + \brief Type of text alignment */ +enum JustifyType +{ + TEXT_ALIGN_RIGHT, + TEXT_ALIGN_LEFT, + TEXT_ALIGN_CENTER +}; -const float NORMSTRETCH = 0.8f; +/* Font meta char constants */ +//! Type used for font character metainfo +typedef short FontMetaChar; +/** + \enum FontType + \brief Type of font + Bitmask in lower 4 bits (mask 0x00f) */ enum FontType { - FONT_COLOBOT = 0, - FONT_COURIER = 1, - FONT_BUTTON = 2, + //! Flag for bold font subtype + FONT_BOLD = 0x04, + //! Flag for italic font subtype + FONT_ITALIC = 0x08, + + //! Default colobot font used for interface + FONT_COLOBOT = 0x00, + //! Alias for bold colobot font + FONT_COLOBOT_BOLD = FONT_COLOBOT | FONT_BOLD, + //! Alias for italic colobot font + FONT_COLOBOT_ITALIC = FONT_COLOBOT | FONT_ITALIC, + + //! Courier (monospace) font used mainly in code editor (only regular & bold) + FONT_COURIER = 0x01, + //! Alias for bold courier font + FONT_COURIER_BOLD = FONT_COURIER | FONT_BOLD, + + // 0x02 left for possible another font + + //! Pseudo-font loaded from textures for buttons, icons, etc. + FONT_BUTTON = 0x03, }; +/** + \enum FontTitle + \brief Size of font title + + Bitmask in 2 bits left shifted 4 (mask 0x030) */ enum FontTitle { - TITLE_BIG = 0x04, - TITLE_NORM = 0x08, - TITLE_LITTLE = 0x0c, + FONT_TITLE_BIG = 0x01 << 4, + FONT_TITLE_NORM = 0x02 << 4, + FONT_TITLE_LITTLE = 0x03 << 4, }; +/** + \enum FontColor + \brief Font color type (?) + + Bitmask in 3 bits left shifted 6 (mask 0x1c0) */ enum FontColor { - COLOR_LINK = 0x10, - COLOR_TOKEN = 0x20, - COLOR_TYPE = 0x30, - COLOR_CONST = 0x40, - COLOR_REM = 0x50, - COLOR_KEY = 0x60, - COLOR_TABLE = 0x70, + FONT_COLOR_LINK = 0x01 << 6, + FONT_COLOR_TOKEN = 0x02 << 6, + FONT_COLOR_TYPE = 0x03 << 6, + FONT_COLOR_CONST = 0x04 << 6, + FONT_COLOR_REM = 0x05 << 6, + FONT_COLOR_KEY = 0x06 << 6, + FONT_COLOR_TABLE = 0x07 << 6, }; -const short FONT_MASK = 0x03; -const short TITLE_MASK = 0x0c; -const short COLOR_MASK = 0x70; -const short IMAGE_MASK = 0x80; +/** + \enum FontMask + \brief Masks in FontMetaChar for different attributes */ +enum FontMask +{ + //! Mask for FontType + FONT_MASK_FONT = 0x00f, + //! Mask for FontTitle + FONT_MASK_TITLE = 0x030, + //! Mask for FontColor + FONT_MASK_COLOR = 0x1c0, + //! Mask for image bit + FONT_MASK_IMAGE = 0x200 +}; + + +/** + \struct UTF8Char + \brief UTF-8 character in font cache + + Only 3-byte chars are supported */ +struct UTF8Char +{ + char c1, c2, c3; + + explicit UTF8Char(char ch1 = '\0', char ch2 = '\0', char ch3 = '\0') + : c1(ch1), c2(ch2), c3(ch3) {} + + inline bool operator<(const UTF8Char &other) const + { + if (c1 < other.c1) + return true; + else if (c1 > other.c1) + return false; + if (c2 < other.c2) + return true; + else if (c2 > other.c2) + return false; + return c3 < other.c3; + } + + inline bool operator==(const UTF8Char &other) const + { + return c1 == other.c1 && c2 == other.c2 && c3 == other.c3; + } +}; -class CText { +/** + \struct CharTexture + \brief Texture of font character */ +struct CharTexture +{ + unsigned int id; + Math::Size texSize; + Math::Size charSize; + + CharTexture() : id(0) {} +}; + +// Definition is private - in text.cpp +struct CachedFont; + +/** + \struct MultisizeFont + \brief Font with multiple possible sizes */ +struct MultisizeFont +{ + std::string fileName; + std::map fonts; + + MultisizeFont(const std::string &fn) + : fileName(fn) {} +}; + +/** + \class CText + \brief Text rendering engine + + ... */ +class CText +{ public: CText(CInstanceManager *iMan, Gfx::CEngine* engine); ~CText(); + //! Sets the device to be used void SetDevice(Gfx::CDevice *device); - void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol); - void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol); - void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol); - void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol); - void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end); - void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end); - void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end); - void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end); + //! Returns the last encountered error + std::string GetError(); - float RetAscent(float size, FontType font); - float RetDescent(float size, FontType font); - float RetHeight(float size, FontType font); + //! Initializes the font engine; must be called after SetDevice() + bool Create(); + //! Frees resources before exit + void Destroy(); - float RetStringWidth(char *string, char *format, int len, float size, float stretch); - float RetStringWidth(char *string, int len, float size, float stretch, FontType font); - float RetCharWidth(int character, float offset, float size, float stretch, FontType font); + //! Flushes cached textures + void FlushCache(); - int Justif(char *string, char *format, int len, float width, float size, float stretch); - int Justif(char *string, int len, float width, float size, float stretch, FontType font); - int Detect(char *string, char *format, int len, float offset, float size, float stretch); - int Detect(char *string, int len, float offset, float size, float stretch, FontType font); + //! Draws text (multi-format) + void DrawText(const std::string &text, const std::vector &format, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol); + //! Draws text (one font) + void DrawText(const std::string &text, Gfx::FontType font, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol); -protected: - void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol); - void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol); - void DrawColor(Math::Point pos, float size, float width, int color); - void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font); + //! Calculates dimensions for text (multi-format) + void SizeText(const std::string &text, const std::vector &format, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end); + //! Calculates dimensions for text (one font) + void SizeText(const std::string &text, Gfx::FontType font, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end); + + //! Returns the ascent font metric + float GetAscent(Gfx::FontType font, float size); + //! Returns the descent font metric + float GetDescent(Gfx::FontType font, float size); + //! Returns the height font metric + float GetHeight(Gfx::FontType font, float size); + + //! Returns width of string (multi-format) + float GetStringWidth(const std::string &text, + const std::vector &format, float size); + //! Returns width of string (single font) + float GetStringWidth(const std::string &text, Gfx::FontType font, float size); + //! Returns width of single character + float GetCharWidth(int character, Gfx::FontType font, float size, float offset); + + //! Justifies a line of text (multi-format) + int Justify(const std::string &text, const std::vector &format, + float size, float width); + //! Justifies a line of text (one font) + int Justify(const std::string &text, Gfx::FontType font, float size, float width); + + //! Returns the most suitable position to a given offset (multi-format) + int Detect(const std::string &text, const std::vector &format, + float size, float offset); + //! Returns the most suitable position to a given offset (one font) + int Detect(const std::string &text, Gfx::FontType font, float size, float offset); + +public: // for testing! + Gfx::CachedFont* GetOrOpenFont(Gfx::FontType type, float size); + Gfx::CharTexture CreateCharTexture(const char* utf8Char, Gfx::CachedFont* font); + + void DrawString(const std::string &text, const std::vector &format, + float size, Math::Point pos, float width, int eol); + void DrawString(const std::string &text, Gfx::FontType font, + float size, Math::Point pos, float width, int eol); + void DrawColor(int color, float size, Math::Point pos, float width); + void DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos); protected: CInstanceManager* m_iMan; Gfx::CEngine* m_engine; Gfx::CDevice* m_device; + std::string m_error; + float m_defaultSize; + std::string m_fontPath; + + std::map m_fonts; + + Gfx::FontType m_lastFontType; + int m_lastFontSize; + Gfx::CachedFont* m_lastCachedFont; }; }; // namespace Gfx diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 3a255f4..cef372f 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -64,7 +64,6 @@ void Gfx::GLDeviceConfig::LoadDefault() Gfx::CGLDevice::CGLDevice(const Gfx::GLDeviceConfig &config) { m_config = config; - m_wasInit = false; m_lighting = false; m_texturing = false; } @@ -74,11 +73,6 @@ Gfx::CGLDevice::~CGLDevice() { } -bool Gfx::CGLDevice::GetWasInit() -{ - return m_wasInit; -} - std::string Gfx::CGLDevice::GetError() { return m_error; @@ -110,8 +104,6 @@ bool Gfx::CGLDevice::Create() /* NOTE: when not using GLEW, extension testing is not performed, as it is assumed that glext.h is up-to-date and the OpenGL shared library has the required functions present. */ - m_wasInit = true; - // This is mostly done in all modern hardware by default // DirectX doesn't even allow the option to turn off perspective correction anymore // So turn it on permanently @@ -158,8 +150,6 @@ void Gfx::CGLDevice::Destroy() m_currentTextures.clear(); m_texturesEnabled.clear(); m_textureStageParams.clear(); - - m_wasInit = false; } void Gfx::CGLDevice::ConfigChanged(const Gfx::GLDeviceConfig& newConfig) @@ -385,15 +375,20 @@ bool Gfx::CGLDevice::GetLightEnabled(int index) This struct must not be deleted in other way than through DeleteTexture() */ Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCreateParams ¶ms) { - Gfx::Texture result; - ImageData *data = image->GetData(); if (data == NULL) { m_error = "Invalid texture data"; - return result; // invalid texture + return Gfx::Texture(); // invalid texture } + return CreateTexture(data, params); +} + +Gfx::Texture Gfx::CGLDevice::CreateTexture(ImageData *data, const Gfx::TextureCreateParams ¶ms) +{ + Gfx::Texture result; + result.valid = true; result.size.w = data->surface->w; result.size.h = data->surface->h; @@ -531,6 +526,24 @@ void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture) glDisable(GL_TEXTURE_2D); } +void Gfx::CGLDevice::SetTexture(int index, unsigned int textureId) +{ + assert(index >= 0); + assert(index < static_cast( m_currentTextures.size() )); + + // Enable the given texture stage + glActiveTexture(GL_TEXTURE0 + index); + glEnable(GL_TEXTURE_2D); + + m_currentTextures[index].id = textureId; + + glBindTexture(GL_TEXTURE_2D, textureId); + + // Disable the stage if it is set so + if ( (! m_texturing) || (! m_texturesEnabled[index]) ) + glDisable(GL_TEXTURE_2D); +} + /** Returns the previously assigned texture or invalid texture if the given stage is not enabled. */ Gfx::Texture Gfx::CGLDevice::GetTexture(int index) diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 1864000..a41c41c 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -73,7 +73,6 @@ public: CGLDevice(const Gfx::GLDeviceConfig &config); virtual ~CGLDevice(); - virtual bool GetWasInit(); virtual std::string GetError(); virtual bool Create(); @@ -100,11 +99,13 @@ public: virtual bool GetLightEnabled(int index); virtual Gfx::Texture CreateTexture(CImage *image, const Gfx::TextureCreateParams ¶ms); + virtual Gfx::Texture CreateTexture(ImageData *data, const Gfx::TextureCreateParams ¶ms); virtual void DestroyTexture(const Gfx::Texture &texture); virtual void DestroyAllTextures(); virtual int GetMaxTextureCount(); virtual void SetTexture(int index, const Gfx::Texture &texture); + virtual void SetTexture(int index, unsigned int textureId); virtual Gfx::Texture GetTexture(int index); virtual void SetTextureEnabled(int index, bool enabled); virtual bool GetTextureEnabled(int index); @@ -163,8 +164,6 @@ private: private: //! Current config Gfx::GLDeviceConfig m_config; - //! Was initialized? - bool m_wasInit; //! Last encountered error std::string m_error; -- cgit v1.2.3-1-g7c22 From f7e78b21e9655604ba6fba1d068a9bf7f00b85a5 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Mon, 6 Aug 2012 20:20:50 +0200 Subject: Font rendering - implemented rest of CText interface excluding some minor features --- src/graphics/engine/engine.cpp | 37 ++- src/graphics/engine/engine.h | 8 +- src/graphics/engine/text.cpp | 516 ++++++++++++++++++++++++++++++++--------- src/graphics/engine/text.h | 67 +++--- 4 files changed, 492 insertions(+), 136 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 345a15c..c5d2a1d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -447,6 +447,19 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color) m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ } + else if (state & Gfx::ENG_RSTATE_TEXT) + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + } else // normal ? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); @@ -607,11 +620,33 @@ bool Gfx::CEngine::DrawInterface() DrawMouse(); - m_text->DrawString("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, 0); + std::vector format; + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COLOBOT_BOLD | Gfx::FONT_HIGHLIGHT_CONST); + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COLOBOT_ITALIC | Gfx::FONT_HIGHLIGHT_KEY); + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COURIER | Gfx::FONT_HIGHLIGHT_LINK); + for (int i = 0; i < 5; ++i) + format.push_back(Gfx::FONT_COURIER_BOLD | Gfx::FONT_HIGHLIGHT_REM); + + m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); + float h = m_text->GetHeight(Gfx::FONT_COLOBOT, 15.0f); + m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", format, 13.0f, Math::Point(0.25f, 0.2f - h), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); return true; } +Math::IntSize Gfx::CEngine::GetWindowSize() +{ + return m_size; +} + +Math::IntSize Gfx::CEngine::GetLastWindowSize() +{ + return m_lastSize; +} + /** Conversion of the position of the mouse from window coords to interface coords: - x: 0=left, 1=right - y: 0=down, 1=up */ diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 79844c6..3f7f4f2 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -408,7 +408,9 @@ enum EngineRenderState //! The transparent color (black = no) ENG_RSTATE_TCOLOR_BLACK = (1<<16), //! The transparent color (white = no) - ENG_RSTATE_TCOLOR_WHITE = (1<<17) + ENG_RSTATE_TCOLOR_WHITE = (1<<17), + //! Mode for rendering text + ENG_RSTATE_TEXT = (1<<18) }; @@ -776,8 +778,8 @@ public: Math::Vector GetLookatPt(); float GetEyeDirH(); float GetEyeDirV(); - Math::IntPoint GetViewportSize(); - Math::IntPoint GetLastViewportSize(); + Math::IntSize GetWindowSize(); + Math::IntSize GetLastWindowSize(); void UpdateMatProj(); void ApplyChange(); diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index eea9fdb..77515ad 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -150,118 +150,421 @@ void Gfx::CText::FlushCache() } void Gfx::CText::DrawText(const std::string &text, const std::vector &format, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol) + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol) { - // TODO + float sw = 0.0f; + + if (align == Gfx::TEXT_ALIGN_CENTER) + { + sw = GetStringWidth(text, format, size); + if (sw > width) sw = width; + pos.x -= sw / 2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + sw = GetStringWidth(text, format, size); + if (sw > width) sw = width; + pos.x -= sw; + } + + DrawString(text, format, size, pos, width, eol); } void Gfx::CText::DrawText(const std::string &text, Gfx::FontType font, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol) + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol) { - // TODO + float sw = 0.0f; + + if (align == Gfx::TEXT_ALIGN_CENTER) + { + sw = GetStringWidth(text, font, size); + if (sw > width) sw = width; + pos.x -= sw / 2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + sw = GetStringWidth(text, font, size); + if (sw > width) sw = width; + pos.x -= sw; + } + + DrawString(text, font, size, pos, width, eol); } void Gfx::CText::SizeText(const std::string &text, const std::vector &format, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end) { - // TODO + start = end = pos; + + float sw = GetStringWidth(text, format, size); + end.x += sw; + if (align == Gfx::TEXT_ALIGN_CENTER) + { + start.x -= sw/2.0f; + end.x -= sw/2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + start.x -= sw; + end.x -= sw; + } + + start.y -= GetDescent(Gfx::FONT_COLOBOT, size); + end.y += GetAscent(Gfx::FONT_COLOBOT, size); } void Gfx::CText::SizeText(const std::string &text, Gfx::FontType font, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end) { - // TODO + start = end = pos; + + float sw = GetStringWidth(text, font, size); + end.x += sw; + if (align == Gfx::TEXT_ALIGN_CENTER) + { + start.x -= sw/2.0f; + end.x -= sw/2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + start.x -= sw; + end.x -= sw; + } + + start.y -= GetDescent(font, size); + end.y += GetAscent(font, size); } float Gfx::CText::GetAscent(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontAscent(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetDescent(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontDescent(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetHeight(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontHeight(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetStringWidth(const std::string &text, const std::vector &format, float size) { - // TODO - return 0.0f; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float width = 0.0f; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + width += GetCharWidth(ch, font, size, width); + + index += len; + fmtIndex++; + } + + return width; } float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + // TODO: special chars? + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.w, &wndSize.h); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.w; } -float Gfx::CText::GetCharWidth(int character, Gfx::FontType font, float size, float offset) +float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset) { - // TODO - return 0.0f; + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) return 0.0f; + + // TODO: special chars? + // TODO: tab sizing + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + + Gfx::CharTexture tex; + auto it = cf->cache.find(ch); + if (it != cf->cache.end()) + tex = (*it).second; + else + tex = CreateCharTexture(ch, cf); + + return tex.charSize.w; } int Gfx::CText::Justify(const std::string &text, const std::vector &format, float size, float width) { - // TODO - return 0; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float pos = 0.0f; + int cut = 0; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + if (font != Gfx::FONT_BUTTON) + { + if (ch.c1 == '\n') + return index+1; + if (ch.c1 == ' ') + cut = index+1; + } + + pos += GetCharWidth(ch, font, size, pos); + if (pos > width) + { + if (cut == 0) return index; + else return cut; + } + + index += len; + fmtIndex++; + } + + return index; } int Gfx::CText::Justify(const std::string &text, Gfx::FontType font, float size, float width) { - // TODO - return 0; + assert(font != Gfx::FONT_BUTTON); + + float pos = 0.0f; + int cut = 0; + unsigned int index = 0; + while (index < text.length()) + { + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + if (ch.c1 == '\n') + return index+1; + + if (ch.c1 == ' ' ) + cut = index+1; + + pos += GetCharWidth(ch, font, size, pos); + if (pos > width) + { + if (cut == 0) return index; + else return cut; + } + } + + return index; } int Gfx::CText::Detect(const std::string &text, const std::vector &format, float size, float offset) { - // TODO - return 0; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float pos = 0.0f; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) continue; + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + if (ch.c1 == '\n') + return index; + + float width = GetCharWidth(ch, font, size, pos); + if (offset <= pos + width/2.0f) + return index; + + pos += width; + index += len; + fmtIndex++; + } + + return index; } int Gfx::CText::Detect(const std::string &text, Gfx::FontType font, float size, float offset) { - // TODO - return 0; + assert(font != Gfx::FONT_BUTTON); + + float pos = 0.0f; + unsigned int index = 0; + while (index < text.length()) + { + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + if (ch.c1 == '\n') + return index; + + float width = GetCharWidth(ch, font, size, pos); + if (offset <= pos + width/2.0f) + return index; + + pos += width; + } + + return index; } void Gfx::CText::DrawString(const std::string &text, const std::vector &format, float size, Math::Point pos, float width, int eol) { - // TODO + assert(StrUtils::Utf8StringLength(text) == format.size()); + + m_engine->SetState(Gfx::ENG_RSTATE_TEXT); + + Gfx::FontType font = Gfx::FONT_COLOBOT; + float start = pos.x; + + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) continue; + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + float offset = pos.x - start; + float cw = GetCharWidth(ch, font, size, offset); + if (offset + cw > width) // exceeds the maximum width? + { + // TODO: special end-of-line char + break; + } + + Gfx::FontHighlight hl = static_cast(format[fmtIndex] & Gfx::FONT_MASK_HIGHLIGHT); + if (hl != Gfx::FONT_HIGHLIGHT_NONE) + { + Math::Size charSize; + charSize.w = GetCharWidth(ch, font, size, offset); + charSize.h = GetHeight(font, size); + DrawHighlight(hl, pos, charSize); + } + + DrawChar(ch, font, size, pos); + + index += len; + fmtIndex++; + } + + // TODO: eol } void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol) { - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); - m_device->SetTextureEnabled(0, true); + assert(font != Gfx::FONT_BUTTON); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + m_engine->SetState(Gfx::ENG_RSTATE_TEXT); unsigned int index = 0; - Math::Point screenPos = pos; while (index < text.length()) { - UTF8Char ch; + Gfx::UTF8Char ch; int len = StrUtils::Utf8CharSizeAt(text, index); if (len >= 1) @@ -273,56 +576,64 @@ void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, index += len; - DrawChar(ch, font, size, screenPos); + DrawChar(ch, font, size, pos); } } -void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) +void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size) { - // TODO !!! - /* - float h, u1, u2, v1, v2, dp; - int icon; + // Gradient colors + Gfx::Color grad[4]; + + // TODO: switch to alpha factors - int icon = -1; - switch (color) + switch (hl) { - case Gfx::FONT_COLOR_LINK: - icon = 9; + case Gfx::FONT_HIGHLIGHT_LINK: + grad[0] = grad[1] = grad[2] = grad[3] = Gfx::Color(0.0f, 0.0f, 1.0f, 0.5f); break; - case Gfx::FONT_COLOR_TOKEN: - icon = 4; + + case Gfx::FONT_HIGHLIGHT_TOKEN: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 220.0f / 256.0f, 188.0f / 256.0f, 0.5f); break; - case Gfx::FONT_COLOR_TYPE: - icon = 5; + + case Gfx::FONT_HIGHLIGHT_TYPE: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(169.0f / 256.0f, 234.0f / 256.0f, 169.0f / 256.0f, 0.5f); break; - } - icon = -1; - if ( color == COLOR_LINK ) icon = 9; // blue - if ( color == COLOR_TOKEN ) icon = 4; // orange - if ( color == COLOR_TYPE ) icon = 5; // green - if ( color == COLOR_CONST ) icon = 8; // red - if ( color == COLOR_REM ) icon = 6; // magenta - if ( color == COLOR_KEY ) icon = 10; // gray - if ( icon == -1 ) return; + case Gfx::FONT_HIGHLIGHT_CONST: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 176.0f / 256.0f, 169.0f / 256.0f, 0.5f); + break; - if ( color == COLOR_LINK ) - { - m_engine->SetState(D3DSTATENORMAL); + case Gfx::FONT_HIGHLIGHT_REM: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 169.0f / 256.0f, 248.0f / 256.0f, 0.5f); + break; + + case Gfx::FONT_HIGHLIGHT_KEY: + grad[0] = grad[1] = grad[2] = grad[3] = + Gfx::Color(192.0f / 256.0f, 192.0f / 256.0f, 192.0f / 256.0f, 0.5f); + break; + + default: + return; } - Math::IntSize vsize = m_engine->GetViewportSize(); - if (vsize.h <= 768.0f) // 1024x768 or less? - h = 1.01f / dim.y; // 1 pixel - else // more than 1024x768? - h = 2.0f / dim.y; // 2 pixels + Math::IntSize vsize = m_engine->GetWindowSize(); + float h = 0.0f; + if (vsize.h <= 768.0f) // 1024x768 or less? + h = 1.01f / vsize.h; // 1 pixel + else // more than 1024x768? + h = 2.0f / vsize.h; // 2 pixels Math::Point p1, p2; p1.x = pos.x; - p2.x = pos.x + width; + p2.x = pos.x + size.w; - if (color == Gfx::FONT_COLOR_LINK) + if (hl == Gfx::FONT_HIGHLIGHT_LINK) { p1.y = pos.y; p2.y = pos.y + h; // just emphasized @@ -330,45 +641,38 @@ void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) else { p1.y = pos.y; - p2.y = pos.y + (16.0f/256.0f)*(size/20.0f); + p2.y = pos.y + size.h; } - u1 = (16.0f/256.0f)*(icon%16); - v1 = (240.0f/256.0f); - u2 = (16.0f/256.0f)+u1; - v2 = (16.0f/256.0f)+v1; - - dp = 0.5f/256.0f; - u1 += dp; - v1 += dp; - u2 -= dp; - v2 -= dp; + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - Math::Vector n(0.0f, 0.0f, -1.0f); // normal - - Gfx::Vertex quad[] = + Gfx::VertexCol quad[] = { - Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), - Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), - Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)), + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), grad[3]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), grad[0]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), grad[1]) }; m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); m_engine->AddStatisticTriangle(2); - if (color == Gfx::FONT_COLOR_LINK) - m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE);*/ + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); } -void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos) +void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos) { + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) return; + + // TODO: special chars? + CachedFont* cf = GetOrOpenFont(font, size); if (cf == nullptr) return; - auto it = cf->cache.find(character); + auto it = cf->cache.find(ch); CharTexture tex; if (it != cf->cache.end()) { @@ -376,31 +680,32 @@ void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Ma } else { - char str[] = { character.c1, character.c2, character.c3, '\0' }; - tex = CreateCharTexture(str, cf); + tex = CreateCharTexture(ch, cf); if (tex.id == 0) // invalid return; - cf->cache[character] = tex; + cf->cache[ch] = tex; } + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + + Math::Point p1(pos.x, pos.y + tex.charSize.h - tex.texSize.h); + Math::Point p2(pos.x + tex.texSize.w, pos.y + tex.charSize.h); + Math::Vector n(0.0f, 0.0f, -1.0f); // normal Gfx::Vertex quad[4] = { - Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h, 0.0f), - n, Math::Point(0.0f, 0.0f)), - Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), - n, Math::Point(0.0f, 1.0f)), - Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h, 0.0f), - n, Math::Point(1.0f, 0.0f)), - Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), - n, Math::Point(1.0f, 1.0f)) + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(1.0f, 0.0f)) }; m_device->SetTexture(0, tex.id); m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); pos.x += tex.charSize.w; } @@ -446,12 +751,13 @@ Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) return m_lastCachedFont; } -Gfx::CharTexture Gfx::CText::CreateCharTexture(const char* str, Gfx::CachedFont* font) +Gfx::CharTexture Gfx::CText::CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont* font) { CharTexture texture; SDL_Surface* textSurface = nullptr; SDL_Color white = {255, 255, 255, 0}; + char str[] = { ch.c1, ch.c2, ch.c3, '\0' }; textSurface = TTF_RenderUTF8_Blended(font->font, str, white); if (textSurface == nullptr) diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 19d9882..6209c39 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -38,9 +38,9 @@ const float FONT_SIZE_SMALL = 10.0f; const float FONT_SIZE_BIG = 15.0f; /** - \enum TextAlignType + \enum TextAlign \brief Type of text alignment */ -enum JustifyType +enum TextAlign { TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT, @@ -86,6 +86,8 @@ enum FontType \enum FontTitle \brief Size of font title + Used internally by CEdit + Bitmask in 2 bits left shifted 4 (mask 0x030) */ enum FontTitle { @@ -95,19 +97,20 @@ enum FontTitle }; /** - \enum FontColor - \brief Font color type (?) + \enum FontHighlight + \brief Type of color highlight for text Bitmask in 3 bits left shifted 6 (mask 0x1c0) */ -enum FontColor +enum FontHighlight { - FONT_COLOR_LINK = 0x01 << 6, - FONT_COLOR_TOKEN = 0x02 << 6, - FONT_COLOR_TYPE = 0x03 << 6, - FONT_COLOR_CONST = 0x04 << 6, - FONT_COLOR_REM = 0x05 << 6, - FONT_COLOR_KEY = 0x06 << 6, - FONT_COLOR_TABLE = 0x07 << 6, + FONT_HIGHLIGHT_NONE = 0x00 << 6, + FONT_HIGHLIGHT_LINK = 0x01 << 6, + FONT_HIGHLIGHT_TOKEN = 0x02 << 6, + FONT_HIGHLIGHT_TYPE = 0x03 << 6, + FONT_HIGHLIGHT_CONST = 0x04 << 6, + FONT_HIGHLIGHT_REM = 0x05 << 6, + FONT_HIGHLIGHT_KEY = 0x06 << 6, + FONT_HIGHLIGHT_TABLE = 0x07 << 6, }; /** @@ -119,9 +122,9 @@ enum FontMask FONT_MASK_FONT = 0x00f, //! Mask for FontTitle FONT_MASK_TITLE = 0x030, - //! Mask for FontColor - FONT_MASK_COLOR = 0x1c0, - //! Mask for image bit + //! Mask for FontHighlight + FONT_MASK_HIGHLIGHT = 0x1c0, + //! Mask for image bit (TODO: not used?) FONT_MASK_IMAGE = 0x200 }; @@ -190,7 +193,17 @@ struct MultisizeFont \class CText \brief Text rendering engine - ... */ + CText is responsible for drawing text in 2D interface. Font rendering is done using + textures generated by SDL_ttf from TTF font files. + + All functions rendering text are divided into two types: + - single font - function takes a single Gfx::FontType argument that (along with size) + determines the font to be used for all characters, + - multi-font - function takes the text as one argument and a std::vector of FontMetaChar + with per-character formatting information (font, highlights and some other info used by CEdit) + + All font rendering is done in UTF-8. +*/ class CText { public: @@ -213,20 +226,20 @@ public: //! Draws text (multi-format) void DrawText(const std::string &text, const std::vector &format, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol); + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol); //! Draws text (one font) void DrawText(const std::string &text, Gfx::FontType font, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol); + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol); //! Calculates dimensions for text (multi-format) void SizeText(const std::string &text, const std::vector &format, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end); //! Calculates dimensions for text (one font) void SizeText(const std::string &text, Gfx::FontType font, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end); //! Returns the ascent font metric @@ -242,7 +255,7 @@ public: //! Returns width of string (single font) float GetStringWidth(const std::string &text, Gfx::FontType font, float size); //! Returns width of single character - float GetCharWidth(int character, Gfx::FontType font, float size, float offset); + float GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset); //! Justifies a line of text (multi-format) int Justify(const std::string &text, const std::vector &format, @@ -256,16 +269,16 @@ public: //! Returns the most suitable position to a given offset (one font) int Detect(const std::string &text, Gfx::FontType font, float size, float offset); -public: // for testing! +protected: Gfx::CachedFont* GetOrOpenFont(Gfx::FontType type, float size); - Gfx::CharTexture CreateCharTexture(const char* utf8Char, Gfx::CachedFont* font); + Gfx::CharTexture CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont* font); void DrawString(const std::string &text, const std::vector &format, float size, Math::Point pos, float width, int eol); void DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol); - void DrawColor(int color, float size, Math::Point pos, float width); - void DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos); + void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size); + void DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos); protected: CInstanceManager* m_iMan; -- cgit v1.2.3-1-g7c22 From 878eec8eea26deedf3b1346df71bff391424c325 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Wed, 8 Aug 2012 21:32:44 +0200 Subject: CTerrain implementation Added rewritten CTerrain implementation Compiles OK, but functions are missing from other classes Also needs testing --- src/graphics/engine/cloud.h | 4 +- src/graphics/engine/engine.cpp | 5 + src/graphics/engine/engine.h | 3 +- src/graphics/engine/particle.h | 6 +- src/graphics/engine/terrain.cpp | 1802 ++++++++++++++++++++++++++++++++++++++- src/graphics/engine/terrain.h | 258 ++++-- src/graphics/engine/water.h | 14 +- 7 files changed, 1988 insertions(+), 104 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index d2d29d7..562f651 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -56,10 +56,10 @@ public: void Draw(); bool SetLevel(float level); - float RetLevel(); + float GetLevel(); void SetEnable(bool bEnable); - bool RetEnable(); + bool GetEnable(); protected: bool EventFrame(const Event &event); diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c5d2a1d..4bf80d2 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -674,6 +674,11 @@ Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) static_cast(size.h * m_size.h)); } +std::string Gfx::CEngine::GetTextureDir() +{ + return m_texPath; +} + void Gfx::CEngine::DrawMouse() { if (! m_mouseVisible) diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 3f7f4f2..cd89a1c 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -552,6 +552,7 @@ public: //! Converts interface size to window size Math::IntSize InterfaceToWindowSize(Math::Size size); + std::string GetTextureDir(); bool WriteProfile(); @@ -606,7 +607,7 @@ public: bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); - bool AddQuick(int objRank, Gfx::EngineObjLevel5* buffer, + bool AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material &mat, diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index bd9741f..94aacfc 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -260,7 +260,7 @@ public: CParticle(CInstanceManager* iMan, CEngine* engine); ~CParticle(); - void SetGLDevice(CDevice device); + void SetDevice(CDevice* device); void FlushParticle(); void FlushParticle(int sheet); @@ -283,7 +283,7 @@ public: void SetPhase(int channel, ParticlePhase phase, float duration); bool GetPosition(int channel, Math::Vector &pos); - Gfx::Color RetFogColor(Math::Vector pos); + Gfx::Color GetFogColor(Math::Vector pos); void SetFrameUpdate(int sheet, bool bUpdate); void FrameParticle(float rTime); @@ -311,7 +311,7 @@ protected: protected: CInstanceManager* m_iMan; CEngine* m_engine; - CDevice* m_pDevice; + CDevice* m_device; CRobotMain* m_main; CTerrain* m_terrain; CWater* m_water; diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index c489321..6d4fcd3 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -19,5 +19,1805 @@ #include "graphics/engine/terrain.h" +#include "app/app.h" +#include "common/iman.h" +#include "common/image.h" +#include "common/logger.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/water.h" +#include "math/geometry.h" -// TODO implementation +#include + +#include + +const int LEVEL_MAT_PREALLOCATE_COUNT = 101; +const int FLYING_LIMIT_PREALLOCATE_COUNT = 10; +const int BUILDING_LEVEL_PREALLOCATE_COUNT = 101; + + +Gfx::CTerrain::CTerrain(CInstanceManager* iMan) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_TERRAIN, this); + + m_engine = static_cast( m_iMan->SearchInstance(CLASS_ENGINE) ); + m_water = static_cast( m_iMan->SearchInstance(CLASS_WATER) ); + + m_mosaic = 20; + m_brick = 1 << 4; + m_size = 10.0f; + m_vision = 200.0f; + m_scaleMapping = 0.01f; + m_scaleRelief = 1.0f; + m_subdivMapping = 1; + m_depth = 2; + m_levelMatMax = 0; + m_multiText = true; + m_levelText = false; + m_wind = Math::Vector(0.0f, 0.0f, 0.0f); + m_defHardness = 0.5f; + + m_levelMat.reserve(LEVEL_MAT_PREALLOCATE_COUNT); + m_flyingLimits.reserve(FLYING_LIMIT_PREALLOCATE_COUNT); + m_buildingLevels.reserve(BUILDING_LEVEL_PREALLOCATE_COUNT); +} + +Gfx::CTerrain::~CTerrain() +{ +} + +/** + The terrain is composed of mosaics, themselves composed of bricks. + Each brick is composed of two triangles. + mosaic: number of mosaics along the axes X and Z + brick: number of bricks (power of 2) + size: size of a brick along the axes X and Z + vision: vision before a change of resolution + scaleMapping: scale textures for mapping + +\verbatim + ^ z + | <---> brick*size + +---+---+---+---+ + | | | |_|_| mosaic = 4 + | | | | | | brick = 2 (brickP2=1) + +---+---+---+---+ + |\ \| | | | + |\ \| | | | + +---+---o---+---+---> x + | | | | | + | | | | | + +---+---+---+---+ + | | | | | The land is viewed from above here. + | | | | | + +---+---+---+---+ + <---------------> mosaic*brick*size +\endverbatim */ +bool Gfx::CTerrain::Generate(int mosaic, int brickPow2, float size, float vision, + int depth, float hardness) +{ + m_mosaic = mosaic; + m_brick = 1 << brickPow2; + m_size = size; + m_vision = vision; + m_depth = depth; + m_defHardness = hardness; + + m_engine->SetTerrainVision(vision); + + m_multiText = true; + m_levelText = false; + m_scaleMapping = 1.0f / (m_brick*m_size); + m_subdivMapping = 1; + + int dim = 0; + + dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1); + std::vector(dim).swap(m_relief); + + dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping; + std::vector(dim).swap(m_texture); + + dim = m_mosaic*m_mosaic; + std::vector(dim).swap(m_objRank); + + return true; +} + + +int Gfx::CTerrain::GetMosaic() +{ + return m_mosaic; +} + +int Gfx::CTerrain::GetBrick() +{ + return m_brick; +} + +float Gfx::CTerrain::GetSize() +{ + return m_size; +} + +float Gfx::CTerrain::GetScaleRelief() +{ + return m_scaleRelief; +} + +bool Gfx::CTerrain::InitTextures(const std::string& baseName, int* table, int dx, int dy) +{ + m_levelText = false; + m_texBaseName = baseName; + size_t pos = baseName.find('.'); + if (pos == baseName.npos) + { + m_texBaseExt = ".png"; + } + else + { + m_texBaseName = m_texBaseName.substr(0, pos); + m_texBaseExt = m_texBaseName.substr(pos); + } + + for (int y = 0; y < m_mosaic*m_subdivMapping; y++) + { + for (int x = 0; x < m_mosaic*m_subdivMapping; x++) + { + m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx]; + } + } + return true; +} + + +void Gfx::CTerrain::LevelFlush() +{ + m_levelMat.clear(); + m_levelMatMax = 0; + m_levelID = 1000; + LevelCloseTable(); +} + +void Gfx::CTerrain::LevelMaterial(int id, std::string& baseName, float u, float v, + int up, int right, int down, int left, + float hardness) +{ + LevelOpenTable(); + + if (id == 0) + id = m_levelID++; // puts an ID internal standard + + Gfx::TerrainMaterial tm; + tm.texName = baseName; + tm.id = id; + tm.u = u; + tm.v = v; + tm.mat[0] = up; + tm.mat[1] = right; + tm.mat[2] = down; + tm.mat[3] = left; + tm.hardness = hardness; + + m_levelMat.push_back(tm); + + if (m_levelMatMax < up+1 ) m_levelMatMax = up+1; + if (m_levelMatMax < right+1) m_levelMatMax = right+1; + if (m_levelMatMax < down+1 ) m_levelMatMax = down+1; + if (m_levelMatMax < left+1 ) m_levelMatMax = left+1; + + m_levelText = true; + m_subdivMapping = 4; +} + + +/** + The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. + The image must be 24 bits/pixel + + Converts coordinated image (x;y) -> world (x;-;z) : + Wx = 5*Ix-400 + Wz = -(5*Iy-400) + + Converts coordinated world (x;-;z) -> image (x;y) : + Ix = (400+Wx)/5 + Iy = (400-Wz)/5 */ +bool Gfx::CTerrain::ResFromPNG(const std::string& fileName) +{ + CImage img; + if (! img.Load(CApplication::GetInstance().GetDataFilePath(m_engine->GetTextureDir(), fileName))) + return false; + + ImageData *data = img.GetData(); + + int size = (m_mosaic*m_brick)+1; + + m_resources.clear(); + + std::vector(3*size*size).swap(m_resources); + + if ( (data->surface->w != size) || (data->surface->h != size) || + (data->surface->format->BytesPerPixel != 3) ) + return false; + + // Assuming the data format is compatible + memcpy(&m_resources[0], data->surface->pixels, 3*size*size); + + return true; +} + +Gfx::TerrainRes Gfx::CTerrain::GetResource(const Math::Vector &p) +{ + if (m_resources.empty()) + return Gfx::TR_NULL; + + int x = static_cast((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size); + int y = static_cast((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) + return Gfx::TR_NULL; + + int size = (m_mosaic*m_brick)+1; + + int resR = m_resources[3*x+3*size*(size-y-1)]; + int resG = m_resources[3*x+3*size*(size-y-1)+1]; + int resB = m_resources[3*x+3*size*(size-y-1)+2]; + + if (resR == 255 && resG == 0 && resB == 0) return Gfx::TR_STONE; + if (resR == 255 && resG == 255 && resB == 0) return Gfx::TR_URANIUM; + if (resR == 0 && resG == 255 && resB == 0) return Gfx::TR_POWER; + + // TODO key res values + //if (ress == 24) return Gfx::TR_KEY_A; // ~green? + //if (ress == 25) return Gfx::TR_KEY_B; // ~green? + //if (ress == 26) return Gfx::TR_KEY_C; // ~green? + //if (ress == 27) return Gfx::TR_KEY_D; // ~green? + + return TR_NULL; +} + +void Gfx::CTerrain::FlushRelief() +{ + m_relief.clear(); +} + +/** + The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. + The image must be 24 bits/pixel, but gray scale: + white = ground (y=0) + black = mountain (y=255*scaleRelief) + + Converts coordinated image(x;y) -> world (x;-;z) : + Wx = 5*Ix-400 + Wz = -(5*Iy-400) + + Converts coordinated world (x;-;z) -> image (x;y) : + Ix = (400+Wx)/5 + Iy = (400-Wz)/5 */ +bool Gfx::CTerrain::ReliefFromPNG(const std::string &fileName, float scaleRelief, + bool adjustBorder) +{ + m_scaleRelief = scaleRelief; + + CImage img; + if (! img.Load(CApplication::GetInstance().GetDataFilePath(m_engine->GetTextureDir(), fileName))) + return false; + + ImageData *data = img.GetData(); + + int size = (m_mosaic*m_brick)+1; + + if ( (data->surface->w != size) || (data->surface->h != size) || + (data->surface->format->BytesPerPixel != 3) ) + return false; + + unsigned char* pixels = static_cast(data->surface->pixels); + + float limit = 0.9f; + for (int y = 0; y < size; y++) + { + for (int x = 0; x < size; x++) + { + float level = (255 - pixels[3*x+3*size*(size-y-1)]) * scaleRelief; + + float dist = Math::Max(fabs(static_cast(x-size/2)), + fabs(static_cast(y-size/2))); + dist = dist/ static_cast(size / 2); + if (dist > limit && adjustBorder) + { + dist = (dist-limit)/(1.0f-limit); // 0..1 + if (dist > 1.0f) dist = 1.0f; + float border = 300.0f+Math::Rand()*20.0f; + level = level+dist*(border-level); + } + + m_relief[x+y*size] = level; + } + } + + return true; +} + +bool Gfx::CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + int size = (m_mosaic*m_brick)+1; + + pos.x = (pos.x+dim)/m_size; + pos.z = (pos.z+dim)/m_size; + + int x = static_cast(pos.x); + int y = static_cast(pos.z); + + if ( x < 0 || x >= size || + y < 0 || y >= size ) return false; + + if (m_relief[x+y*size] < pos.y*scaleRelief) + m_relief[x+y*size] = pos.y*scaleRelief; + + return true; +} + +void Gfx::CTerrain::LimitPos(Math::Vector &pos) +{ +// TODO: #if _TEEN +// dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f; + + float dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f; + + if (pos.x < -dim) pos.x = -dim; + if (pos.x > dim) pos.x = dim; + if (pos.z < -dim) pos.z = -dim; + if (pos.z > dim) pos.z = dim; +} + +void Gfx::CTerrain::AdjustRelief() +{ + if (m_depth == 1) return; + + int ii = m_mosaic*m_brick+1; + int b = 1 << (m_depth-1); + + for (int y = 0; y < m_mosaic*m_brick; y += b) + { + for (int x = 0; x < m_mosaic*m_brick; x += b) + { + int xx = 0; + int yy = 0; + if ((y+yy)%m_brick == 0) + { + float level1 = m_relief[(x+0)+(y+yy)*ii]; + float level2 = m_relief[(x+b)+(y+yy)*ii]; + for (xx = 1; xx < b; xx++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1; + } + } + + yy = b; + if ((y+yy)%m_brick == 0) + { + float level1 = m_relief[(x+0)+(y+yy)*ii]; + float level2 = m_relief[(x+b)+(y+yy)*ii]; + for (xx = 1; xx < b; xx++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1; + } + } + + xx = 0; + if ((x+xx)%m_brick == 0) + { + float level1 = m_relief[(x+xx)+(y+0)*ii]; + float level2 = m_relief[(x+xx)+(y+b)*ii]; + for (yy = 1; yy < b; yy++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1; + } + } + + xx = b; + if ((x+xx)%m_brick == 0) + { + float level1 = m_relief[(x+xx)+(y+0)*ii]; + float level2 = m_relief[(x+xx)+(y+b)*ii]; + for (yy = 1; yy < b; yy++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1; + } + } + } + } +} + +Math::Vector Gfx::CTerrain::GetVector(int x, int y) +{ + Math::Vector p; + p.x = x*m_size - (m_mosaic*m_brick*m_size)/2; + p.z = y*m_size - (m_mosaic*m_brick*m_size)/2; + + if ( !m_relief.empty() && + x >= 0 && x <= m_mosaic*m_brick && + y >= 0 && y <= m_mosaic*m_brick ) + { + p.y = m_relief[x+y*(m_mosaic*m_brick+1)]; + } + else + { + p.y = 0.0f; + } + + return p; +} + +/** Calculates a normal soft, taking into account the six adjacent triangles: + +\verbatim + ^ y + | + b---c---+ + |\ |\ | + | \| \| + a---o---d + |\ |\ | + | \| \| + +---f---e--> x +\endverbatim */ +Gfx::VertexTex2 Gfx::CTerrain::GetVertex(int x, int y, int step) +{ + Gfx::VertexTex2 v; + + Math::Vector o = GetVector(x, y); + v.coord = o; + + Math::Vector a = GetVector(x-step, y ); + Math::Vector b = GetVector(x-step, y+step); + Math::Vector c = GetVector(x, y+step); + Math::Vector d = GetVector(x+step, y ); + Math::Vector e = GetVector(x+step, y-step); + Math::Vector f = GetVector(x, y-step); + + Math::Vector s(0.0f, 0.0f, 0.0f); + + if (x-step >= 0 && y+step <= m_mosaic*m_brick+1) + { + s += Math::NormalToPlane(b,a,o); + s += Math::NormalToPlane(c,b,o); + } + + if (x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1) + s += Math::NormalToPlane(d,c,o); + + if (x+step <= m_mosaic*m_brick+1 && y-step >= 0) + { + s += Math::NormalToPlane(e,d,o); + s += Math::NormalToPlane(f,e,o); + } + + if (x-step >= 0 && y-step >= 0) + s += Math::NormalToPlane(a,f,o); + + s = Normalize(s); + v.normal = s; + + if (m_multiText) + { + int brick = m_brick/m_subdivMapping; + Math::Vector oo = GetVector((x/brick)*brick, (y/brick)*brick); + o = GetVector(x, y); + v.texCoord.x = (o.x-oo.x)*m_scaleMapping*m_subdivMapping; + v.texCoord.y = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping; + } + else + { + v.texCoord.x = o.x*m_scaleMapping; + v.texCoord.y = o.z*m_scaleMapping; + } + + return v; +} + +/** The origin of mosaic is its center. +\verbatim + ^ z + | + | 2---4---6-- + | |\ |\ |\ + | | \| \| + | 1---3---5--- ... + | + +-------------------> x +\endverbatim */ +bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, + const Gfx::Material &mat, + float min, float max) +{ + std::string texName1; + std::string texName2; + + if ( step == 1 && m_engine->GetGroundSpot() ) + { + int i = (ox/5) + (oy/5)*(m_mosaic/5); + std::stringstream s; + s << "shadow"; + s.width(2); + s.fill('0'); + s << i; + s << ".png"; + texName2 = s.str(); + } + + int brick = m_brick/m_subdivMapping; + + Gfx::VertexTex2 o = GetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step); + int total = ((brick/step)+1)*2; + + float pixel = 1.0f/256.0f; // 1 pixel cover (*) + float dp = 1.0f/512.0f; + + Math::Point uv; + + for (int my = 0; my < m_subdivMapping; my++) + { + for (int mx = 0; mx < m_subdivMapping; mx++) + { + if (m_levelText) + { + int xx = ox*m_brick + mx*(m_brick/m_subdivMapping); + int yy = oy*m_brick + my*(m_brick/m_subdivMapping); + LevelTextureName(xx, yy, texName1, uv); + } + else + { + int i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic; + std::stringstream s; + s << m_texBaseName; + s.width(3); + s.fill('0'); + s << m_texture[i]; + s << m_texBaseExt; + texName1 = s.str(); + } + + for (int y = 0; y < brick; y += step) + { + Gfx::EngineObjLevel5 buffer; + buffer.vertices.reserve(total); + + buffer.type = Gfx::ENG_TRIANGLE_TYPE_6S; + buffer.material = mat; + + buffer.state = Gfx::ENG_RSTATE_WRAP; + + buffer.state |= Gfx::ENG_RSTATE_SECOND; + if (step == 1) + buffer.state |= Gfx::ENG_RSTATE_DUAL_BLACK; + + for (int x = 0; x <= brick; x += step) + { + Gfx::VertexTex2 p1 = GetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step); + Gfx::VertexTex2 p2 = GetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step); + p1.coord.x -= o.coord.x; p1.coord.z -= o.coord.z; + p2.coord.x -= o.coord.x; p2.coord.z -= o.coord.z; + + if (m_multiText) + { + if (x == 0) + { + p1.texCoord.x = 0.0f+(0.5f/256.0f); + p2.texCoord.x = 0.0f+(0.5f/256.0f); + } + if (x == brick) + { + p1.texCoord.x = 1.0f-(0.5f/256.0f); + p2.texCoord.x = 1.0f-(0.5f/256.0f); + } + if (y == 0) + p1.texCoord.y = 1.0f-(0.5f/256.0f); + + if (y == brick - step) + p2.texCoord.y = 0.0f+(0.5f/256.0f); + } + + if (m_levelText) + { + p1.texCoord.x /= m_subdivMapping; // 0..1 -> 0..0.25 + p1.texCoord.y /= m_subdivMapping; + p2.texCoord.x /= m_subdivMapping; + p2.texCoord.y /= m_subdivMapping; + + if (x == 0) + { + p1.texCoord.x = 0.0f+dp; + p2.texCoord.x = 0.0f+dp; + } + if (x == brick) + { + p1.texCoord.x = (1.0f/m_subdivMapping)-dp; + p2.texCoord.x = (1.0f/m_subdivMapping)-dp; + } + if (y == 0) + p1.texCoord.y = (1.0f/m_subdivMapping)-dp; + + if (y == brick - step) + p2.texCoord.y = 0.0f+dp; + + p1.texCoord.x += uv.x; + p1.texCoord.y += uv.y; + p2.texCoord.x += uv.x; + p2.texCoord.y += uv.y; + } + + int xx = mx*(m_brick/m_subdivMapping) + x; + int yy = my*(m_brick/m_subdivMapping) + y; + p1.texCoord2.x = (static_cast(ox%5)*m_brick+xx+0.0f)/(m_brick*5); + p1.texCoord2.y = (static_cast(oy%5)*m_brick+yy+0.0f)/(m_brick*5); + p2.texCoord2.x = (static_cast(ox%5)*m_brick+xx+0.0f)/(m_brick*5); + p2.texCoord2.y = (static_cast(oy%5)*m_brick+yy+1.0f)/(m_brick*5); + +// Correction for 1 pixel cover +// There is 1 pixel cover around each of the 16 surfaces: +// +// |<--------------256-------------->| +// | |<----------254---------->| | +// |---|---|---|-- ... --|---|---|---| +// | 0.0 1.0 | +// | | | | +// 0.0 min max 1.0 +// +// The uv coordinates used for texturing are between min and max (instead of 0 and 1) +// This allows to exclude the pixels situated in a margin of a pixel around the surface + + p1.texCoord2.x = (p1.texCoord2.x+pixel)*(1.0f-pixel)/(1.0f+pixel); + p1.texCoord2.y = (p1.texCoord2.y+pixel)*(1.0f-pixel)/(1.0f+pixel); + p2.texCoord2.x = (p2.texCoord2.x+pixel)*(1.0f-pixel)/(1.0f+pixel); + p2.texCoord2.y = (p2.texCoord2.y+pixel)*(1.0f-pixel)/(1.0f+pixel); + + + buffer.vertices.push_back(p1); + buffer.vertices.push_back(p2); + } + m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true); + } + } + } + + Math::Matrix transform; + transform.LoadIdentity(); + transform.Set(1, 4, o.coord.x); + transform.Set(3, 4, o.coord.z); + m_engine->SetObjectTransform(objRank, transform); + + return true; +} + +Gfx::TerrainMaterial* Gfx::CTerrain::LevelSearchMat(int id) +{ + for (int i = 0; i < static_cast( m_levelMat.size() ); i++) + { + if (id == m_levelMat[i].id) + return &m_levelMat[i]; + } + + return nullptr; +} + +void Gfx::CTerrain::LevelTextureName(int x, int y, std::string& name, Math::Point &uv) +{ + x /= m_brick/m_subdivMapping; + y /= m_brick/m_subdivMapping; + + TerrainMaterial* tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id); + if (tm == nullptr) + { + name = "xxx.png"; + uv.x = 0.0f; + uv.y = 0.0f; + } + else + { + name = tm->texName; + uv.x = tm->u; + uv.y = tm->v; + } +} + +float Gfx::CTerrain::LevelGetHeight(int x, int y) +{ + int size = (m_mosaic*m_brick+1); + + if (x < 0 ) x = 0; + if (x >= size) x = size-1; + if (y < 0 ) y = 0; + if (y >= size) y = size-1; + + return m_relief[x+y*size]; +} + +bool Gfx::CTerrain::LevelGetDot(int x, int y, float min, float max, float slope) +{ + float hc = LevelGetHeight(x, y); + float h[4] = + { + LevelGetHeight(x+0, y+1), + LevelGetHeight(x+1, y+0), + LevelGetHeight(x+0, y-1), + LevelGetHeight(x-1, y+0) + }; + + if (hc < min || hc > max) + return false; + + if (slope == 0.0f) + return true; + + if (slope > 0.0f) + { + for (int i = 0; i < 4; i++) + { + if (fabs(hc - h[i]) >= slope) + return false; + } + return true; + } + + if (slope < 0.0f) + { + for (int i = 0; i < 4; i++) + { + if (fabs(hc - h[i]) < -slope) + return false; + } + return true; + } + + return false; +} + + +/** Returns the index within m_levelMat or -1 if there is not. + m_levelMat[i].id gives the identifier. */ +int Gfx::CTerrain::LevelTestMat(char *mat) +{ + for (int i = 0; i < static_cast( m_levelMat.size() ); i++) + { + if ( m_levelMat[i].mat[0] == mat[0] && + m_levelMat[i].mat[1] == mat[1] && + m_levelMat[i].mat[2] == mat[2] && + m_levelMat[i].mat[3] == mat[3] ) return i; + } + + return -1; +} + +void Gfx::CTerrain::LevelSetDot(int x, int y, int id, char *mat) +{ + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return; + + if ( tm->mat[0] != mat[0] || + tm->mat[1] != mat[1] || + tm->mat[2] != mat[2] || + tm->mat[3] != mat[3] ) // id incompatible with mat? + { + int ii = LevelTestMat(mat); + if (ii == -1) return; + id = m_levelMat[ii].id; // looking for a id compatible with mat + } + + // Changes the point + m_levelDot[x+y*m_levelDotSize].id = id; + m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0]; + m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1]; + m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2]; + m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3]; + + // Changes the lower neighbor + if ( (x+0) >= 0 && (x+0) < m_levelDotSize && + (y-1) >= 0 && (y-1) < m_levelDotSize ) + { + int i = (x+0)+(y-1)*m_levelDotSize; + if (m_levelDot[i].mat[0] != mat[2]) + { + m_levelDot[i].mat[0] = mat[2]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } + + // Modifies the left neighbor + if ( (x-1) >= 0 && (x-1) < m_levelDotSize && + (y+0) >= 0 && (y+0) < m_levelDotSize ) + { + int i = (x-1)+(y+0)*m_levelDotSize; + if (m_levelDot[i].mat[1] != mat[3]) + { + m_levelDot[i].mat[1] = mat[3]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } + + // Changes the upper neighbor + if ( (x+0) >= 0 && (x+0) < m_levelDotSize && + (y+1) >= 0 && (y+1) < m_levelDotSize ) + { + int i = (x+0)+(y+1)*m_levelDotSize; + if (m_levelDot[i].mat[2] != mat[0]) + { + m_levelDot[i].mat[2] = mat[0]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } + + // Changes the right neighbor + if ( (x+1) >= 0 && (x+1) < m_levelDotSize && + (y+0) >= 0 && (y+0) < m_levelDotSize ) + { + int i = (x+1)+(y+0)*m_levelDotSize; + if ( m_levelDot[i].mat[3] != mat[1] ) + { + m_levelDot[i].mat[3] = mat[1]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } +} + +bool Gfx::CTerrain::LevelIfDot(int x, int y, int id, char *mat) +{ + char test[4]; + + // Compatible with lower neighbor? + if ( x+0 >= 0 && x+0 < m_levelDotSize && + y-1 >= 0 && y-1 < m_levelDotSize ) + { + test[0] = mat[2]; + test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1]; + test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2]; + test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + // Compatible with left neighbor? + if ( x-1 >= 0 && x-1 < m_levelDotSize && + y+0 >= 0 && y+0 < m_levelDotSize ) + { + test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0]; + test[1] = mat[3]; + test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2]; + test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + // Compatible with upper neighbor? + if ( x+0 >= 0 && x+0 < m_levelDotSize && + y+1 >= 0 && y+1 < m_levelDotSize ) + { + test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0]; + test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1]; + test[2] = mat[0]; + test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + // Compatible with right neighbor? + if ( x+1 >= 0 && x+1 < m_levelDotSize && + y+0 >= 0 && y+0 < m_levelDotSize ) + { + test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0]; + test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1]; + test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2]; + test[3] = mat[1]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + LevelSetDot(x, y, id, mat); // puts the point + return true; +} + +bool Gfx::CTerrain::LevelPutDot(int x, int y, int id) +{ + char mat[4]; + + x /= m_brick/m_subdivMapping; + y /= m_brick/m_subdivMapping; + + if ( x < 0 || x >= m_levelDotSize || + y < 0 || y >= m_levelDotSize ) return false; + + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return false; + + // Tries without changing neighbors. + if ( LevelIfDot(x, y, id, tm->mat) ) return true; + + // Tries changing a single neighbor (4x). + for (int up = 0; up < m_levelMatMax; up++) + { + mat[0] = up; + mat[1] = tm->mat[1]; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + for (int right = 0; right < m_levelMatMax; right++) + { + mat[0] = tm->mat[0]; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + for (int down = 0; down < m_levelMatMax; down++) + { + mat[0] = tm->mat[0]; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = tm->mat[0]; + mat[1] = tm->mat[1]; + mat[2] = tm->mat[2]; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + // Tries changing two neighbors (6x). + for (int up = 0; up < m_levelMatMax; up++) + { + for (int down = 0; down < m_levelMatMax; down++) + { + mat[0] = up; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int right = 0; right < m_levelMatMax; right++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = tm->mat[0]; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int up = 0; up < m_levelMatMax; up++) + { + for (int right = 0; right < m_levelMatMax; right++) + { + mat[0] = up; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int right = 0; right < m_levelMatMax; right++) + { + for (int down = 0; down < m_levelMatMax; down++) + { + mat[0] = tm->mat[0]; + mat[1] = right; + mat[2] = down; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int down = 0; down < m_levelMatMax; down++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = tm->mat[0]; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int up = 0; up < m_levelMatMax; up++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = up; + mat[1] = tm->mat[1]; + mat[2] = tm->mat[2]; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + // Tries changing all the neighbors. + for (int up = 0; up < m_levelMatMax; up++) + { + for (int right = 0; right < m_levelMatMax; right++) + { + for (int down = 0; down < m_levelMatMax; down++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = up; + mat[1] = right; + mat[2] = down; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + } + } + + GetLogger()->Error("LevelPutDot error\n"); + return false; +} + +bool Gfx::CTerrain::LevelInit(int id) +{ + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return false; + + for (int i = 0; i < m_levelDotSize*m_levelDotSize; i++) + { + m_levelDot[i].id = id; + + for (int j = 0; j < 4; j++) + m_levelDot[i].mat[j] = tm->mat[j]; + } + + return true; +} + +bool Gfx::CTerrain::LevelGenerate(int *id, float min, float max, + float slope, float freq, + Math::Vector center, float radius) +{ + static char random[100] = + { + 84,25,12, 6,34,52,85,38,97,16, + 21,31,65,19,62,40,72,22,48,61, + 56,47, 8,53,73,77, 4,91,26,88, + 76, 1,44,93,39,11,71,17,98,95, + 88,83,18,30, 3,57,28,49,74, 9, + 32,13,96,66,15,70,36,10,59,94, + 45,86, 2,29,63,42,51, 0,79,27, + 54, 7,20,69,89,23,64,43,81,92, + 90,33,46,14,67,35,50, 5,87,60, + 68,55,24,78,41,75,58,80,37,82, + }; + + TerrainMaterial* tm = nullptr; + + int i = 0; + while ( id[i] != 0 ) + { + tm = LevelSearchMat(id[i++]); + if (tm == nullptr) return false; + } + int numID = i; + + int group = m_brick / m_subdivMapping; + + if (radius > 0.0f && radius < 5.0f) // just a square? + { + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int xx = static_cast((center.x+dim)/m_size); + int yy = static_cast((center.z+dim)/m_size); + + int x = xx/group; + int y = yy/group; + + tm = LevelSearchMat(id[0]); + if (tm != nullptr) + LevelSetDot(x, y, id[0], tm->mat); // puts the point + } + else + { + for (int y = 0; y < m_levelDotSize; y++) + { + for (int x = 0; x < m_levelDotSize; x++) + { + if (radius != 0.0f) + { + Math::Vector pos; + pos.x = (static_cast(x)-m_levelDotSize/2.0f)*group*m_size; + pos.z = (static_cast(y)-m_levelDotSize/2.0f)*group*m_size; + if (Math::DistanceProjected(pos, center) > radius) continue; + } + + if (freq < 100.0f) + { + int rnd = random[(x%10)+(y%10)*10]; + if ( static_cast(rnd) > freq ) continue; + } + + int xx = x*group + group/2; + int yy = y*group + group/2; + + if (LevelGetDot(xx, yy, min, max, slope)) + { + int rnd = random[(x%10)+(y%10)*10]; + int ii = rnd % numID; + LevelPutDot(xx, yy, id[ii]); + } + } + } + } + + return true; +} + +void Gfx::CTerrain::LevelOpenTable() +{ + if (! m_levelText) return; + if (! m_levelDot.empty()) return; // already allocated + + m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1; + std::vector(m_levelDotSize*m_levelDotSize).swap(m_levelDot); + + for (int i = 0; i < m_levelDotSize * m_levelDotSize; i++) + { + for (int j = 0; j < 4; j++) + m_levelDot[i].mat[j] = 0; + } +} + +void Gfx::CTerrain::LevelCloseTable() +{ + m_levelDot.clear(); +} + +bool Gfx::CTerrain::CreateSquare(bool multiRes, int x, int y) +{ + Gfx::Material mat; + mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); + mat.ambient = Gfx::Color(0.0f, 0.0f, 0.0f); + + int objRank = m_engine->CreateObject(); + m_engine->SetObjectType(objRank, Gfx::ENG_OBJTYPE_TERRAIN); // it is a terrain + + m_objRank[x+y*m_mosaic] = objRank; + + if (multiRes) + { + float min = 0.0f; + float max = m_vision; + max *= m_engine->GetClippingDistance(); + for (int step = 0; step < m_depth; step++) + { + CreateMosaic(x, y, 1 << step, objRank, mat, min, max); + min = max; + max *= 2; + if (step == m_depth-1) max = Math::HUGE_NUM; + } + } + else + { + CreateMosaic(x, y, 1, objRank, mat, 0.0f, Math::HUGE_NUM); + } + + return true; +} + +bool Gfx::CTerrain::CreateObjects(bool multiRes) +{ + AdjustRelief(); + + for (int y = 0; y < m_mosaic; y++) + { + for (int x = 0; x < m_mosaic; x++) + CreateSquare(multiRes, x, y); + } + + return true; +} + +/** ATTENTION: ok only with m_depth = 2! */ +bool Gfx::CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + Math::IntPoint tp1, tp2; + tp1.x = static_cast((p1.x+dim+m_size/2.0f)/m_size); + tp1.y = static_cast((p1.z+dim+m_size/2.0f)/m_size); + tp2.x = static_cast((p2.x+dim+m_size/2.0f)/m_size); + tp2.y = static_cast((p2.z+dim+m_size/2.0f)/m_size); + + if (tp1.x > tp2.x) + { + int x = tp1.x; + tp1.x = tp2.x; + tp2.x = x; + } + + if (tp1.y > tp2.y) + { + int y = tp1.y; + tp1.y = tp2.y; + tp2.y = y; + } + + int size = (m_mosaic*m_brick)+1; + + // Calculates the current average height + float avg = 0.0f; + int nb = 0; + for (int y = tp1.y; y <= tp2.y; y++) + { + for (int x = tp1.x; x <= tp2.x; x++) + { + avg += m_relief[x+y*size]; + nb ++; + } + } + avg /= static_cast(nb); + + // Changes the description of the relief + for (int y = tp1.y; y <= tp2.y; y++) + { + for (int x = tp1.x; x <= tp2.x; x++) + { + m_relief[x+y*size] = avg+height; + + if (x % m_brick == 0 && y % m_depth != 0) + { + m_relief[(x+0)+(y-1)*size] = avg+height; + m_relief[(x+0)+(y+1)*size] = avg+height; + } + + if (y % m_brick == 0 && x % m_depth != 0) + { + m_relief[(x-1)+(y+0)*size] = avg+height; + m_relief[(x+1)+(y+0)*size] = avg+height; + } + } + } + AdjustRelief(); + + Math::IntPoint pp1, pp2; + pp1.x = (tp1.x-2)/m_brick; + pp1.y = (tp1.y-2)/m_brick; + pp2.x = (tp2.x+1)/m_brick; + pp2.y = (tp2.y+1)/m_brick; + + if (pp1.x < 0 ) pp1.x = 0; + if (pp1.x >= m_mosaic) pp1.x = m_mosaic-1; + if (pp1.y < 0 ) pp1.y = 0; + if (pp1.y >= m_mosaic) pp1.y = m_mosaic-1; + + for (int y = pp1.y; y <= pp2.y; y++) + { + for (int x = pp1.x; x <= pp2.x; x++) + { + m_engine->DeleteObject(m_objRank[x+y*m_mosaic]); + CreateSquare(m_multiText, x, y); // recreates the square + } + } + m_engine->Update(); + + return true; +} + +void Gfx::CTerrain::SetWind(Math::Vector speed) +{ + m_wind = speed; +} + +Math::Vector Gfx::CTerrain::GetWind() +{ + return m_wind; +} + +float Gfx::CTerrain::GetFineSlope(const Math::Vector &pos) +{ + Math::Vector n; + if (! GetNormal(n, pos)) return 0.0f; + return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y) - Math::PI/2.0f); +} + +float Gfx::CTerrain::GetCoarseSlope(const Math::Vector &pos) +{ + if (m_relief.empty()) return 0.0f; + + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((pos.x+dim)/m_size); + int y = static_cast((pos.z+dim)/m_size); + + if ( x < 0 || x >= m_mosaic*m_brick || + y < 0 || y >= m_mosaic*m_brick ) return 0.0f; + + float level[4] = + { + m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)], + m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)], + m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)], + m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)], + }; + + float min = Math::Min(level[0], level[1], level[2], level[3]); + float max = Math::Max(level[0], level[1], level[2], level[3]); + + return atanf((max-min)/m_size); +} + +bool Gfx::CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x+dim)/m_size); + int y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + if ( fabs(p.z - p2.z) < fabs(p.x - p2.x) ) + n = Math::NormalToPlane(p1,p2,p3); + else + n = Math::NormalToPlane(p2,p4,p3); + + return true; +} + +float Gfx::CTerrain::GetFloorLevel(const Math::Vector &p, bool brut, bool water) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x+dim)/m_size); + int y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + Math::Vector ps = p; + if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) + { + if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; + } + else + { + if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f; + } + + if (! brut) AdjustBuildingLevel(ps); + + if (water) // not going underwater? + { + float level = m_water->GetLevel(); + if (ps.y < level) ps.y = level; // not under water + } + + return ps.y; +} + + +/** This height is positive when you are above the ground */ +float Gfx::CTerrain::GetFloorHeight(const Math::Vector &p, bool brut, bool water) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x+dim)/m_size); + int y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + Math::Vector ps = p; + if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) + { + if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; + } + else + { + if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f; + } + + if (! brut) AdjustBuildingLevel(ps); + + if (water) // not going underwater? + { + float level = m_water->GetLevel(); + if ( ps.y < level ) ps.y = level; // not under water + } + + return p.y-ps.y; +} + +bool Gfx::CTerrain::MoveOnFloor(Math::Vector &p, bool brut, bool water) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x + dim) / m_size); + int y = static_cast((p.z + dim) / m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + if (fabs(p.z - p2.z) < fabs(p.x - p2.x)) + { + if (! Math::IntersectY(p1, p2, p3, p)) return false; + } + else + { + if (! Math::IntersectY(p2, p4, p3, p)) return false; + } + + if (! brut) AdjustBuildingLevel(p); + + if (water) // not going underwater? + { + float level = m_water->GetLevel(); + if (p.y < level) p.y = level; // not under water + } + + return true; +} + + +/** Returns false if the initial coordinate was too far */ +bool Gfx::CTerrain::ValidPosition(Math::Vector &p, float marging) +{ + bool ok = true; + + float limit = m_mosaic*m_brick*m_size/2.0f - marging; + + if (p.x < -limit) + { + p.x = -limit; + ok = false; + } + + if (p.z < -limit) + { + p.z = -limit; + ok = false; + } + + if (p.x > limit) + { + p.x = limit; + ok = false; + } + + if (p.z > limit) + { + p.z = limit; + ok = false; + } + + return ok; +} + +void Gfx::CTerrain::FlushBuildingLevel() +{ + m_buildingLevels.clear(); +} + +bool Gfx::CTerrain::AddBuildingLevel(Math::Vector center, float min, float max, + float height, float factor) +{ + int i = 0; + for ( ; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( center.x == m_buildingLevels[i].center.x && + center.z == m_buildingLevels[i].center.z ) + { + break; + } + } + + if (i == static_cast( m_buildingLevels.size() )) + m_buildingLevels.push_back(Gfx::BuildingLevel()); + + m_buildingLevels[i].center = center; + m_buildingLevels[i].min = min; + m_buildingLevels[i].max = max; + m_buildingLevels[i].level = GetFloorLevel(center, true); + m_buildingLevels[i].height = height; + m_buildingLevels[i].factor = factor; + m_buildingLevels[i].bboxMinX = center.x-max; + m_buildingLevels[i].bboxMaxX = center.x+max; + m_buildingLevels[i].bboxMinZ = center.z-max; + m_buildingLevels[i].bboxMaxZ = center.z+max; + + return true; +} + +bool Gfx::CTerrain::UpdateBuildingLevel(Math::Vector center) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( center.x == m_buildingLevels[i].center.x && + center.z == m_buildingLevels[i].center.z ) + { + m_buildingLevels[i].center = center; + m_buildingLevels[i].level = GetFloorLevel(center, true); + return true; + } + } + return false; +} + +bool Gfx::CTerrain::DeleteBuildingLevel(Math::Vector center) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( center.x == m_buildingLevels[i].center.x && + center.z == m_buildingLevels[i].center.z ) + { + for (int j = i+1; j < static_cast( m_buildingLevels.size() ); j++) + m_buildingLevels[j-1] = m_buildingLevels[j]; + + m_buildingLevels.pop_back(); + return true; + } + } + return false; +} + +float Gfx::CTerrain::GetBuildingFactor(const Math::Vector &p) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( p.x < m_buildingLevels[i].bboxMinX || + p.x > m_buildingLevels[i].bboxMaxX || + p.z < m_buildingLevels[i].bboxMinZ || + p.z > m_buildingLevels[i].bboxMaxZ ) continue; + + float dist = Math::DistanceProjected(p, m_buildingLevels[i].center); + + if (dist <= m_buildingLevels[i].max) + return m_buildingLevels[i].factor; + } + return 1.0f; // it is normal on the ground +} + +void Gfx::CTerrain::AdjustBuildingLevel(Math::Vector &p) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( p.x < m_buildingLevels[i].bboxMinX || + p.x > m_buildingLevels[i].bboxMaxX || + p.z < m_buildingLevels[i].bboxMinZ || + p.z > m_buildingLevels[i].bboxMaxZ ) continue; + + float dist = Math::DistanceProjected(p, m_buildingLevels[i].center); + + if (dist > m_buildingLevels[i].max) continue; + + if (dist < m_buildingLevels[i].min) + { + p.y = m_buildingLevels[i].level + m_buildingLevels[i].height; + return; + } + + Math::Vector border; + border.x = ((p.x - m_buildingLevels[i].center.x) * m_buildingLevels[i].max) / + dist + m_buildingLevels[i].center.x; + border.z = ((p.z - m_buildingLevels[i].center.z) * m_buildingLevels[i].max) / + dist + m_buildingLevels[i].center.z; + + float base = GetFloorLevel(border, true); + + p.y = (m_buildingLevels[i].max - dist) / + (m_buildingLevels[i].max - m_buildingLevels[i].min) * + (m_buildingLevels[i].level + m_buildingLevels[i].height-base) + + base; + + return; + } +} + + +// returns the hardness of the ground in a given place. +// The hardness determines the noise (SOUND_STEP and SOUND_BOUM). + +float Gfx::CTerrain::GetHardness(const Math::Vector &p) +{ + float factor = GetBuildingFactor(p); + if (factor != 1.0f) return 1.0f; // on building + + if (m_levelDot.empty()) return m_defHardness; + + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x, y; + + x = static_cast((p.x+dim)/m_size); + y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return m_defHardness; + + x /= m_brick/m_subdivMapping; + y /= m_brick/m_subdivMapping; + + if ( x < 0 || x >= m_levelDotSize || + y < 0 || y >= m_levelDotSize ) return m_defHardness; + + int id = m_levelDot[x+y*m_levelDotSize].id; + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return m_defHardness; + + return tm->hardness; +} + +void Gfx::CTerrain::GroundFlat(Math::Vector pos) +{ + static char table[41*41]; + + + float rapport = 3200.0f/1024.0f; + + for (int y = 0; y <= 40; y++) + { + for (int x = 0; x <= 40; x++) + { + int i = x + y*41; + table[i] = 0; + + Math::Vector p; + p.x = (x-20)*rapport; + p.z = (y-20)*rapport; + p.y = 0.0f; + + if (Math::Point(p.x, p.y).Length() > 20.0f*rapport) + continue; + + float angle = GetFineSlope(pos+p); + + if (angle < FLATLIMIT) + table[i] = 1; + else + table[i] = 2; + } + } + + m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table); +} + +float Gfx::CTerrain::GetFlatZoneRadius(Math::Vector center, float max) +{ + float angle = GetFineSlope(center); + if (angle >= Gfx::FLATLIMIT) + return 0.0f; + + float ref = GetFloorLevel(center, true); + + float radius = 1.0f; + while (radius <= max) + { + angle = 0.0f; + int nb = static_cast(2.0f*Math::PI*radius); + if (nb < 8) nb = 8; + + for (int i = 0; i < nb; i++) + { + Math::Point c(center.x, center.z); + Math::Point p (center.x+radius, center.z); + p = Math::RotatePoint(c, angle, p); + Math::Vector pos; + pos.x = p.x; + pos.z = p.y; + float h = GetFloorLevel(pos, true); + if ( fabs(h-ref) > 1.0f ) return radius; + + angle += Math::PI*2.0f/8.0f; + } + radius += 1.0f; + } + return max; +} + +void Gfx::CTerrain::SetFlyingMaxHeight(float height) +{ + m_flyingMaxHeight = height; +} + +float Gfx::CTerrain::GetFlyingMaxHeight() +{ + return m_flyingMaxHeight; +} + +void Gfx::CTerrain::FlushFlyingLimit() +{ + m_flyingMaxHeight = 280.0f; + m_flyingLimits.clear(); +} + +void Gfx::CTerrain::AddFlyingLimit(Math::Vector center, + float extRadius, float intRadius, + float maxHeight) +{ + Gfx::FlyingLimit fl; + fl.center = center; + fl.extRadius = extRadius; + fl.intRadius = intRadius; + fl.maxHeight = maxHeight; + m_flyingLimits.push_back(fl); +} + +float Gfx::CTerrain::GetFlyingLimit(Math::Vector pos, bool noLimit) +{ + if (noLimit) + return 280.0f; + + if (m_flyingLimits.empty()) + return m_flyingMaxHeight; + + for (int i = 0; i < static_cast( m_flyingLimits.size() ); i++) + { + float dist = Math::DistanceProjected(pos, m_flyingLimits[i].center); + + if (dist >= m_flyingLimits[i].extRadius) + continue; + + if (dist <= m_flyingLimits[i].intRadius) + return m_flyingLimits[i].maxHeight; + + dist -= m_flyingLimits[i].intRadius; + + float h = dist * (m_flyingMaxHeight - m_flyingLimits[i].maxHeight) / + (m_flyingLimits[i].extRadius - m_flyingLimits[i].intRadius); + + return h + m_flyingLimits[i].maxHeight; + } + + return m_flyingMaxHeight; +} diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index 8d8b165..a198590 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -40,56 +40,72 @@ enum TerrainRes TR_STONE = 1, TR_URANIUM = 2, TR_POWER = 3, - TR_KEYa = 4, - TR_KEYb = 5, - TR_KEYc = 6, - TR_KEYd = 7, + TR_KEY_A = 4, + TR_KEY_B = 5, + TR_KEY_C = 6, + TR_KEY_D = 7, }; - -const short MAXBUILDINGLEVEL = 100; - struct BuildingLevel { - Math::Vector center; - float factor; - float min; - float max; - float level; - float height; - float bboxMinX; - float bboxMaxX; - float bboxMinZ; - float bboxMaxZ; + Math::Vector center; + float factor; + float min; + float max; + float level; + float height; + float bboxMinX; + float bboxMaxX; + float bboxMinZ; + float bboxMaxZ; + + BuildingLevel() + { + factor = min = max = level = height = 0.0f; + bboxMinX = bboxMaxX = bboxMinZ = bboxMaxZ = 0.0f; + } }; - -const short MAXMATTERRAIN = 100; - struct TerrainMaterial { short id; - char texName[20]; + std::string texName; float u,v; float hardness; char mat[4]; // up, right, down, left + + TerrainMaterial() + { + id = 0; + u = v = 0.0f; + hardness = 0.0f; + mat[0] = mat[1] = mat[2] = mat[3] = 0; + } }; struct DotLevel { short id; char mat[4]; // up, right, down, left -}; - -const short MAXFLYINGLIMIT = 10; + DotLevel() + { + id = 0; + mat[0] = mat[1] = mat[2] = mat[3] = 0; + } +}; struct FlyingLimit { - Math::Vector center; - float extRadius; - float intRadius; - float maxHeight; + Math::Vector center; + float extRadius; + float intRadius; + float maxHeight; + + FlyingLimit() + { + extRadius = intRadius = maxHeight = 0.0f; + } }; @@ -100,72 +116,124 @@ public: CTerrain(CInstanceManager* iMan); ~CTerrain(); - bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness); - bool InitTextures(char* baseName, int* table, int dx, int dy); + //! Generates a new flat terrain + bool Generate(int mosaic, int brickPow2, float size, float vision, int depth, float hardness); + //! Initializes the names of textures to use for the land + bool InitTextures(const std::string& baseName, int* table, int dx, int dy); + //! Empties level void LevelFlush(); - bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness); + //! Initializes the names of textures to use for the land + void LevelMaterial(int id, std::string& baseName, float u, float v, int up, int right, int down, int left, float hardness); + //! Initializes all the ground with a material bool LevelInit(int id); + //! Generates a level in the terrain bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius); + //! Initializes a completely flat terrain void FlushRelief(); - bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder); - bool ReliefFromDXF(const char* filename, float scaleRelief); - bool ResFromBMP(const char* filename); - bool CreateObjects(bool bMultiRes); - bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height); - - void SetWind(Math::Vector speed); - Math::Vector RetWind(); - - float RetFineSlope(const Math::Vector &pos); - float RetCoarseSlope(const Math::Vector &pos); - bool GetNormal(Math::Vector &n, const Math::Vector &p); - float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false); - float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false); - bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false); - bool ValidPosition(Math::Vector &p, float marging); - TerrainRes RetResource(const Math::Vector &p); + //! Load relief from a PNG file + bool ReliefFromPNG(const std::string& filename, float scaleRelief, bool adjustBorder); + //! Load resources from a PNG file + bool ResFromPNG(const std::string& filename); + //! Creates all objects of the terrain within the 3D engine + bool CreateObjects(bool multiRes); + //! Modifies the terrain's relief + bool Terraform(const Math::Vector& p1, const Math::Vector& p2, float height); + + //@{ + //! Management of the wind + void SetWind(Math::Vector speed); + Math::Vector GetWind(); + //@} + + //! Gives the exact slope of the terrain of a place given + float GetFineSlope(const Math::Vector& pos); + //! Gives the approximate slope of the terrain of a specific location + float GetCoarseSlope(const Math::Vector& pos); + //! Gives the normal vector at the position p (x,-,z) of the ground + bool GetNormal(Math::Vector& n, const Math::Vector &p); + //! returns the height of the ground + float GetFloorLevel(const Math::Vector& p, bool brut=false, bool water=false); + //! Returns the height to the ground + float GetFloorHeight(const Math::Vector& p, bool brut=false, bool water=false); + //! Modifies the coordinate "y" of point "p" to rest on the ground floor + bool MoveOnFloor(Math::Vector& p, bool brut=false, bool water=false); + //! Modifies a coordinate so that it is on the ground + bool ValidPosition(Math::Vector& p, float marging); + //! Returns the resource type available underground + Gfx::TerrainRes GetResource(const Math::Vector& p); + //! Adjusts a position so that it does not exceed the boundaries void LimitPos(Math::Vector &pos); + //! Empty the table of elevations void FlushBuildingLevel(); + //! Adds a new elevation for a building bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor); + //! Updates the elevation for a building when it was moved up (after a terraforming) bool UpdateBuildingLevel(Math::Vector center); + //! Removes the elevation for a building when it was destroyed bool DeleteBuildingLevel(Math::Vector center); - float RetBuildingFactor(const Math::Vector &p); - float RetHardness(const Math::Vector &p); + //! Returns the influence factor whether a position is on a possible rise + float GetBuildingFactor(const Math::Vector& p); + float GetHardness(const Math::Vector& p); - int RetMosaic(); - int RetBrick(); - float RetSize(); - float RetScaleRelief(); + int GetMosaic(); + int GetBrick(); + float GetSize(); + float GetScaleRelief(); + //! Shows the flat areas on the ground void GroundFlat(Math::Vector pos); - float RetFlatZoneRadius(Math::Vector center, float max); + //! Calculates the radius of the largest flat area available + float GetFlatZoneRadius(Math::Vector center, float max); + //@{ + //! Management of the global max flying height void SetFlyingMaxHeight(float height); - float RetFlyingMaxHeight(); + float GetFlyingMaxHeight(); + //@} + //! Empty the table of flying limits void FlushFlyingLimit(); - bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight); - float RetFlyingLimit(Math::Vector pos, bool bNoLimit); + //! Adds a new flying limit + void AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight); + //! Returns the maximum height of flight + float GetFlyingLimit(Math::Vector pos, bool noLimit); protected: + //! Adds a point of elevation in the buffer of relief bool ReliefAddDot(Math::Vector pos, float scaleRelief); + //! Adjust the edges of each mosaic to be compatible with all lower resolutions void AdjustRelief(); - Math::Vector RetVector(int x, int y); - Gfx::VertexTex2 RetVertex(int x, int y, int step); - bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material &mat, float min, float max); - bool CreateSquare(bool bMultiRes, int x, int y); - - TerrainMaterial* LevelSearchMat(int id); - void LevelTextureName(int x, int y, char *name, Math::Point &uv); - float LevelRetHeight(int x, int y); + //! Calculates a vector of the terrain + Math::Vector GetVector(int x, int y); + //! Calculates a vertex of the terrain + Gfx::VertexTex2 GetVertex(int x, int y, int step); + //! Creates all objects of a mosaic + bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material& mat, float min, float max); + //! Creates all objects in a mesh square ground + bool CreateSquare(bool multiRes, int x, int y); + + //! Seeks a materials based on theirs identifier + Gfx::TerrainMaterial* LevelSearchMat(int id); + //! Chooses texture to use for a given square + void LevelTextureName(int x, int y, std::string& name, Math::Point &uv); + //! Returns the height of the terrain + float LevelGetHeight(int x, int y); + //! Decide whether a point is using the materials bool LevelGetDot(int x, int y, float min, float max, float slope); + //! Seeks if material exists int LevelTestMat(char *mat); + //! Modifies the state of a point and its four neighbors, without testing if possible void LevelSetDot(int x, int y, int id, char *mat); + //! Tests if a material can give a place, according to its four neighbors. If yes, puts the point. bool LevelIfDot(int x, int y, int id, char *mat); + //! Modifies the state of a point bool LevelPutDot(int x, int y, int id); + //! Initializes a table with empty levels void LevelOpenTable(); + //! Closes the level table void LevelCloseTable(); + //! Adjusts a position according to a possible rise void AdjustBuildingLevel(Math::Vector &p); protected: @@ -173,39 +241,49 @@ protected: CEngine* m_engine; CWater* m_water; - int m_mosaic; // number of mosaics - int m_brick; // number of bricks per mosaics - float m_size; // size of an item in an brick - float m_vision; // vision before a change of resolution - float* m_relief; // table of the relief - int* m_texture; // table of textures - int* m_objRank; // table of rows of objects - bool m_bMultiText; - bool m_bLevelText; - float m_scaleMapping; // scale of the mapping + //! Number of mosaics + int m_mosaic; + //! Number of bricks per mosaics + int m_brick; + int m_levelDotSize; + //! Size of an item in a brick + float m_size; + //! Vision before a change of resolution + float m_vision; + //! Table of the relief + std::vector m_relief; + //! Table of textures + std::vector m_texture; + //! Table of rows of objects + std::vector m_objRank; + //! Table of resources + std::vector m_resources; + bool m_multiText; + bool m_levelText; + //! Scale of the mapping + float m_scaleMapping; float m_scaleRelief; - int m_subdivMapping; - int m_depth; // number of different resolutions (1,2,3,4) - char m_texBaseName[20]; - char m_texBaseExt[10]; + int m_subdivMapping; + //! Number of different resolutions (1,2,3,4) + int m_depth; + std::string m_texBaseName; + std::string m_texBaseExt; float m_defHardness; - TerrainMaterial m_levelMat[MAXMATTERRAIN+1]; - int m_levelMatTotal; + std::vector m_levelMat; + std::vector m_levelDot; int m_levelMatMax; - int m_levelDotSize; - DotLevel* m_levelDot; int m_levelID; - int m_buildingUsed; - BuildingLevel m_buildingTable[MAXBUILDINGLEVEL]; + std::vector m_buildingLevels; - unsigned char* m_resources; - Math::Vector m_wind; // wind speed + //! Wind speed + Math::Vector m_wind; + //! Global flying height limit float m_flyingMaxHeight; - int m_flyingLimitTotal; - FlyingLimit m_flyingLimit[MAXFLYINGLIMIT]; + //! List of local flight limits + std::vector m_flyingLimits; }; }; // namespace Gfx diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index 67be9dc..6d3736e 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -72,7 +72,7 @@ public: CWater(CInstanceManager* iMan, Gfx::CEngine* engine); ~CWater(); - void SetGLDevice(Gfx::CDevice device); + void SetDevice(Gfx::CDevice* device); bool EventProcess(const Event &event); void Flush(); bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy); @@ -80,11 +80,11 @@ public: void DrawSurf(); bool SetLevel(float level); - float RetLevel(); - float RetLevel(CObject* object); + float GetLevel(); + float GetLevel(CObject* object); void SetLava(bool bLava); - bool RetLava(); + bool GetLava(); void AdjustEye(Math::Vector &eye); @@ -92,7 +92,7 @@ protected: bool EventFrame(const Event &event); void LavaFrame(float rTime); void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2); - bool RetWater(int x, int y); + bool GetWater(int x, int y); bool CreateLine(int x, int y, int len); void VaporFlush(); @@ -101,8 +101,8 @@ protected: protected: CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_pDevice; + CEngine* m_engine; + CDevice* m_device; CTerrain* m_terrain; CParticle* m_particule; CSound* m_sound; -- cgit v1.2.3-1-g7c22 From c1936514c054d6d7c85843bf2c3e0b97653ef651 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Wed, 8 Aug 2012 23:51:19 +0200 Subject: CWater and CCloud basic implementation Added rewritten implementation for CWater and CCloud Won't link yet because of missing functions --- src/graphics/engine/cloud.cpp | 267 +++++++++++++++++- src/graphics/engine/cloud.h | 74 +++-- src/graphics/engine/water.cpp | 640 +++++++++++++++++++++++++++++++++++++++++- src/graphics/engine/water.h | 137 +++++---- 4 files changed, 1043 insertions(+), 75 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index d0e5ed8..e46b074 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -19,5 +19,270 @@ #include "graphics/engine/cloud.h" +#include "common/iman.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/terrain.h" +#include "math/geometry.h" -// TODO implementation + +const int CLOUD_LINE_PREALLOCATE_COUNT = 100; + +const int DIMEXPAND = 4; // extension of the dimensions + + +Gfx::CCloud::CCloud(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_CLOUD, this); + + m_engine = engine; + m_terrain = nullptr; + + m_level = 0.0f; + m_wind = Math::Vector(0.0f, 0.0f, 0.0f); + m_subdiv = 8; + m_enable = true; + + m_line.reserve(CLOUD_LINE_PREALLOCATE_COUNT); +} + +Gfx::CCloud::~CCloud() +{ + m_iMan = nullptr; + m_engine = nullptr; + m_terrain = nullptr; +} + +bool Gfx::CCloud::EventProcess(const Event &event) +{ + /* TODO! + if ( event.event == EVENT_FRAME ) + return EventFrame(event); */ + + return true; +} + +bool Gfx::CCloud::EventFrame(const Event &event) +{ + /* TODO! + if (m_engine->GetPause()) return true; + + m_time += event.rTime; + + if (m_level == 0.0f) return true; + + if (m_time - m_lastTest < 0.2f) return true; + + m_lastTest = m_time; */ + + return true; +} + +void Gfx::CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, + Math::Point &uv1, Math::Point &uv2) +{ + uv1.x = (pos.x+20000.0f)/1280.0f; + uv1.y = (pos.z+20000.0f)/1280.0f; + uv1.x -= m_time*(m_wind.x/100.0f); + uv1.y -= m_time*(m_wind.z/100.0f); + + uv2.x = 0.0f; + uv2.y = 0.0f; + + float dist = Math::DistanceProjected(pos, eye); + float factor = powf(dist/deep, 2.0f); + pos.y -= m_level*factor*10.0f; +} + +void Gfx::CCloud::Draw() +{ + /* TODO! + LPDIRECT3DDEVICE7 device; + D3DVERTEX2* vertex; + Math::Matrix* matView; + D3DMATERIAL7 material; + Math::Matrix matrix; + Math::Vector n, pos, p, eye; + Math::Point uv1, uv2; + float iDeep, deep, size, fogStart, fogEnd; + int i, j, u; + + if ( !m_enable ) return; + if ( m_level == 0.0f ) return; + if ( m_lineUsed == 0 ) return; + + vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2); + + iDeep = m_engine->GetDeepView(); + deep = (m_brick*m_size)/2.0f; + m_engine->SetDeepView(deep); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // increases the depth of view + + fogStart = deep*0.15f; + fogEnd = deep*0.24f; + + device = m_engine->GetD3DDevice(); + device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000); + device->SetRenderState(D3DRENDERSTATE_LIGHTING, false); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, false); + device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); + device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart)); + device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd)); + + matView = m_engine->GetMatView(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(*matView); + device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat); + } + + ZeroMemory( &material, sizeof(D3DMATERIAL7) ); + material.diffuse = m_diffuse; + material.ambient = m_ambient; + m_engine->SetMaterial(material); + + m_engine->SetTexture(m_filename, 0); + m_engine->SetTexture(m_filename, 1); + + m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP); + + matrix.LoadIdentity(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(matrix); + device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + size = m_size/2.0f; + eye = m_engine->GetEyePt(); + n = Math::Vector(0.0f, -1.0f, 0.0f); + + // Draws all the lines. + for ( i=0 ; iDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL); + m_engine->AddStatisticTriangle(u-2); + } + + m_engine->SetDeepView(iDeep); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // gives depth to initial + + free(vertex); */ +} + +void Gfx::CCloud::CreateLine(int x, int y, int len) +{ + Gfx::CloudLine line; + + line.x = x; + line.y = y; + line.len = len; + + float offset = m_brick*m_size/2.0f - m_size/2.0f; + + line.px1 = m_size* line.x - offset; + line.px2 = m_size*(line.x+line.len) - offset; + line.pz = m_size* line.y - offset; + + m_line.push_back(line); +} + +void Gfx::CCloud::Create(const std::string& fileName, + Gfx::Color diffuse, Gfx::Color ambient, + float level) +{ + m_diffuse = diffuse; + m_ambient = ambient; + m_level = level; + m_time = 0.0f; + m_lastTest = 0.0f; + m_fileName = fileName; + + if (! m_fileName.empty()) + { + m_engine->LoadTexture(m_fileName, 0); + m_engine->LoadTexture(m_fileName, 1); + } + + if (m_terrain == nullptr) + m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); + + m_wind = m_terrain->GetWind(); + + m_brick = m_terrain->GetBrick()*m_terrain->GetMosaic()*DIMEXPAND; + m_size = m_terrain->GetSize(); + + m_brick /= m_subdiv*DIMEXPAND; + m_size *= m_subdiv*DIMEXPAND; + + if (m_level == 0.0f) + return; + + m_line.clear(); + for (int y = 0; y < m_brick; y++) + CreateLine(0, y, m_brick); + + return; +} + +void Gfx::CCloud::Flush() +{ + m_level = 0.0f; +} + + +void Gfx::CCloud::SetLevel(float level) +{ + m_level = level; + + Create(m_fileName, m_diffuse, m_ambient, m_level); +} + +float Gfx::CCloud::GetLevel() +{ + return m_level; +} + +void Gfx::CCloud::SetEnable(bool enable) +{ + m_enable = enable; +} + +bool Gfx::CCloud::GetEnable() +{ + return m_enable; +} diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index 562f651..676dfe8 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -24,6 +24,9 @@ #include "math/point.h" #include "math/vector.h" +#include +#include + class CInstanceManager; @@ -34,13 +37,20 @@ namespace Gfx { class CEngine; class CTerrain; -const short MAXCLOUDLINE = 100; - struct CloudLine { - short x, y; // beginning - short len; // in length x + //! Beginning + short x, y; + //! In length x + short len; float px1, px2, pz; + + CloudLine() + { + x = y = 0; + len = 0; + px1 = px2 = pz = 0; + } }; @@ -51,43 +61,59 @@ public: ~CCloud(); bool EventProcess(const Event &event); + //! Removes all the clouds void Flush(); - bool Create(const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level); + //! Creates all areas of cloud + void Create(const std::string& fileName, Gfx::Color diffuse, Gfx::Color ambient, float level); + //! Draw the clouds void Draw(); - bool SetLevel(float level); + //! Modifies the cloud level + void SetLevel(float level); + //! Returns the current level of clouds float GetLevel(); - void SetEnable(bool bEnable); + //! Activate management of clouds + void SetEnable(bool enable); bool GetEnable(); protected: + //! Makes the clouds evolve bool EventFrame(const Event &event); - void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2); - bool CreateLine(int x, int y, int len); + //! Adjusts the position to normal, to imitate the clouds at movement + void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, + Math::Point &uv1, Math::Point &uv2); + //! Updates the positions, relative to the ground + void CreateLine(int x, int y, int len); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; - CTerrain* m_terrain; - - char m_filename[100]; - float m_level; // overall level - Math::Point m_speed; // feedrate (wind) - Gfx::Color m_diffuse; // diffuse color - Gfx::Color m_ambient; // ambient color + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; + Gfx::CTerrain* m_terrain; + + std::string m_fileName; + //! Overall level + float m_level; + //! Feedrate (wind) + Math::Point m_speed; + //! Diffuse color + Gfx::Color m_diffuse; + //! Ambient color + Gfx::Color m_ambient; float m_time; float m_lastTest; int m_subdiv; - Math::Vector m_wind; // wind speed - int m_brick; // brick mosaic - float m_size; // size of a brick element + //! Wind speed + Math::Vector m_wind; + //! Brick mosaic + int m_brick; + //! Size of a brick element + float m_size; - int m_lineUsed; - CloudLine m_line[MAXCLOUDLINE]; + std::vector m_line; - bool m_bEnable; + bool m_enable; }; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index a157e82..1f11671 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -19,5 +19,643 @@ #include "graphics/engine/water.h" +#include "common/iman.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/terrain.h" +#include "sound/sound.h" + + +const int WATERLINE_PREALLOCATE_COUNT = 500; + +// TODO: remove the limit? +const int VAPOR_SIZE = 10; + + +Gfx::CWater::CWater(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_WATER, this); + + m_engine = engine; + m_terrain = nullptr; + m_particule = nullptr; + m_sound = nullptr; + + m_type[0] = WATER_NULL; + m_type[1] = WATER_NULL; + m_level = 0.0f; + m_draw = true; + m_lava = false; + m_color = 0xffffffff; + m_subdiv = 4; + + m_line.reserve(WATERLINE_PREALLOCATE_COUNT); + + std::vector(VAPOR_SIZE).swap(m_vapor); +} + +Gfx::CWater::~CWater() +{ + m_iMan = nullptr; + m_engine = nullptr; + m_terrain = nullptr; + m_particule = nullptr; + m_sound = nullptr; +} + + +bool Gfx::CWater::EventProcess(const Event &event) +{ + /* TODO! + if (event.type == EVENT_FRAME) + return EventFrame(event); +*/ + return true; +} + +bool Gfx::CWater::EventFrame(const Event &event) +{ + /* TODO! + if (m_engine->GetPause()) return true; + + m_time += event.rTime; + + if (m_type[0] == WATER_NULL) return true; + + if (m_lava) + LavaFrame(event.rTime);*/ + + return true; +} + +void Gfx::CWater::LavaFrame(float rTime) +{ + if (m_particule == nullptr) + m_particule = static_cast( m_iMan->SearchInstance(CLASS_PARTICULE) ); + + for (int i = 0; i < static_cast( m_vapor.size() ); i++) + VaporFrame(i, rTime); + + if (m_time - m_lastLava >= 0.1f) + { + Math::Vector eye = m_engine->GetEyePt(); + Math::Vector lookat = m_engine->GetLookatPt(); + + float distance = Math::Rand()*200.0f; + float shift = (Math::Rand()-0.5f)*200.0f; + + Math::Vector dir = Normalize(lookat-eye); + Math::Vector pos = eye + dir*distance; + + Math::Vector perp; + perp.x = -dir.z; + perp.y = dir.y; + perp.z = dir.x; + pos = pos + perp*shift; + + float level = m_terrain->GetFloorLevel(pos, true); + if (level < m_level) + { + pos.y = m_level; + + level = Math::Rand(); + if (level < 0.8f) + { + if ( VaporCreate(Gfx::PARTIFIRE, pos, 0.02f+Math::Rand()*0.06f) ) + m_lastLava = m_time; + } + else if (level < 0.9f) + { + if ( VaporCreate(Gfx::PARTIFLAME, pos, 0.5f+Math::Rand()*3.0f) ) + m_lastLava = m_time; + } + else + { + if ( VaporCreate(Gfx::PARTIVAPOR, pos, 0.2f+Math::Rand()*2.0f) ) + m_lastLava = m_time; + } + } + } +} + +void Gfx::CWater::VaporFlush() +{ + m_vapor.clear(); +} + +bool Gfx::CWater::VaporCreate(Gfx::ParticleType type, Math::Vector pos, float delay) +{ + for (int i = 0; i < static_cast( m_vapor.size() ); i++) + { + if (! m_vapor[i].used) + { + m_vapor[i].used = true; + m_vapor[i].type = type; + m_vapor[i].pos = pos; + m_vapor[i].delay = delay; + m_vapor[i].time = 0.0f; + m_vapor[i].last = 0.0f; + + if (m_vapor[i].type == PARTIFIRE) + m_sound->Play(SOUND_BLUP, pos, 1.0f, 1.0f-Math::Rand()*0.5f); + + if (m_vapor[i].type == PARTIVAPOR) + m_sound->Play(SOUND_PSHHH, pos, 0.3f, 2.0f); + + return true; + } + } + + return false; +} + +void Gfx::CWater::VaporFrame(int i, float rTime) +{ + m_vapor[i].time += rTime; + + if (m_sound == nullptr) + m_sound = static_cast(m_iMan->SearchInstance(CLASS_SOUND)); + + if (m_vapor[i].time <= m_vapor[i].delay) + { + if (m_time-m_vapor[i].last >= m_engine->ParticleAdapt(0.02f)) + { + m_vapor[i].last = m_time; + + if (m_vapor[i].type == PARTIFIRE) + { + for (int j = 0; j < 10; j++) + { + Math::Vector pos = m_vapor[i].pos; + pos.x += (Math::Rand()-0.5f)*2.0f; + pos.z += (Math::Rand()-0.5f)*2.0f; + pos.y -= 1.0f; + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*6.0f; + speed.z = (Math::Rand()-0.5f)*6.0f; + speed.y = 8.0f+Math::Rand()*5.0f; + Math::Point dim; + dim.x = Math::Rand()*1.5f+1.5f; + dim.y = dim.x; + m_particule->CreateParticle(pos, speed, dim, PARTIERROR, 2.0f, 10.0f); + } + } + else if (m_vapor[i].type == PARTIFLAME) + { + Math::Vector pos = m_vapor[i].pos; + pos.x += (Math::Rand()-0.5f)*8.0f; + pos.z += (Math::Rand()-0.5f)*8.0f; + pos.y -= 2.0f; + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 4.0f+Math::Rand()*4.0f; + Math::Point dim; + dim.x = Math::Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticle(pos, speed, dim, PARTIFLAME); + } + else + { + Math::Vector pos = m_vapor[i].pos; + pos.x += (Math::Rand()-0.5f)*4.0f; + pos.z += (Math::Rand()-0.5f)*4.0f; + pos.y -= 2.0f; + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 8.0f+Math::Rand()*8.0f; + Math::Point dim; + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticle(pos, speed, dim, PARTIVAPOR); + } + } + } + else + { + m_vapor[i].used = false; + } +} + +void Gfx::CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm, + Math::Point &uv1, Math::Point &uv2) +{ + float t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f; + pos.y += sinf(t1)*m_eddy.y; + + t1 = m_time*1.5f; + uv1.x = (pos.x+10000.0f)/40.0f+sinf(t1)*m_eddy.x*0.02f; + uv1.y = (pos.z+10000.0f)/40.0f-cosf(t1)*m_eddy.z*0.02f; + uv2.x = (pos.x+10010.0f)/20.0f+cosf(-t1)*m_eddy.x*0.02f; + uv2.y = (pos.z+10010.0f)/20.0f-sinf(-t1)*m_eddy.z*0.02f; + + t1 = m_time*0.50f + pos.x*2.1f + pos.z*1.1f; + float t2 = m_time*0.75f + pos.x*2.0f + pos.z*1.0f; + norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint); +} + +/** This surface prevents to see the sky (background) underwater! */ +void Gfx::CWater::DrawBack() +{ + /* TODO! + LPDIRECT3DDEVICE7 device; + D3DVERTEX2 vertex[4]; // 2 triangles + D3DMATERIAL7 material; + Math::Matrix matrix; + Math::Vector eye, lookat, n, p, p1, p2; + Math::Point uv1, uv2; + float deep, dist; + + if ( !m_bDraw ) return; + if ( m_type[0] == WATER_NULL ) return; + if ( m_lineUsed == 0 ) return; + + eye = m_engine->GetEyePt(); + lookat = m_engine->GetLookatPt(); + + ZeroMemory( &material, sizeof(D3DMATERIAL7) ); + material.diffuse = m_diffuse; + material.ambient = m_ambient; + m_engine->SetMaterial(material); + + m_engine->SetTexture("", 0); + + device = m_engine->GetD3DDevice(); + device->SetRenderState(D3DRENDERSTATE_LIGHTING, false); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, false); + device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); + m_engine->SetState(D3DSTATENORMAL); + + deep = m_engine->GetDeepView(0); + m_engine->SetDeepView(deep*2.0f, 0); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // twice the depth of view + + matrix.LoadIdentity(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(matrix); + device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + p.x = eye.x; + p.z = eye.z; + dist = Math::DistanceProjected(eye, lookat); + p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x; + p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z; + + p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x; + p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z; + p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x; + p2.z = (lookat.x-eye.x)*deep*2.0f/dist + p.z; + + p1.y = -50.0f; + p2.y = m_level; + + n.x = (lookat.x-eye.x)/dist; + n.z = (lookat.z-eye.z)/dist; + n.y = 0.0f; + + uv1.x = uv1.y = 0.0f; + uv2.x = uv2.y = 0.0f; + + vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y); + vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y); + vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y); + vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y); + + device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); + m_engine->AddStatisticTriangle(2); + + m_engine->SetDeepView(deep, 0); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // gives the initial depth of view + + device->SetRenderState(D3DRENDERSTATE_LIGHTING, true); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, true); + device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);*/ +} + +void Gfx::CWater::DrawSurf() +{ + /* TODO! + LPDIRECT3DDEVICE7 device; + D3DVERTEX2* vertex; // triangles + D3DMATERIAL7 material; + Math::Matrix matrix; + Math::Vector eye, lookat, n, pos, p; + Math::Point uv1, uv2; + bool bUnder; + DWORD flags; + float deep, size, sizez, radius; + int rankview, i, j, u; + + if (! m_draw) return; + if (m_type[0] == Gfx::WATER_NULL) return; + if (m_line.empty()) return; + + vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2); + + eye = m_engine->GetEyePt(); + lookat = m_engine->GetLookatPt(); + + rankview = m_engine->GetRankView(); + bUnder = ( rankview == 1); + + device = m_engine->GetD3DDevice(); + device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); + + matrix.LoadIdentity(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(matrix); + device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + ZeroMemory( &material, sizeof(D3DMATERIAL7) ); + material.diffuse = m_diffuse; + material.ambient = m_ambient; + m_engine->SetMaterial(material); + + m_engine->SetTexture(m_filename, 0); + m_engine->SetTexture(m_filename, 1); + + if ( m_type[rankview] == WATER_TT ) + { + m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color); + } + if ( m_type[rankview] == WATER_TO ) + { + m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP); + } + if ( m_type[rankview] == WATER_CT ) + { + m_engine->SetState(D3DSTATETTb); + } + if ( m_type[rankview] == WATER_CO ) + { + m_engine->SetState(D3DSTATENORMAL); + } + device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); + + size = m_size/2.0f; + if ( bUnder ) sizez = -size; + else sizez = size; + + // Draws all the lines. + deep = m_engine->GetDeepView(0)*1.5f; + + for ( i=0 ; i deep+radius ) continue; + + D3DVECTOR pD3D = VEC_TO_D3DVEC(p); + device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags); + + if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue; + + u = 0; + p.x = pos.x-size; + p.z = pos.z-sizez; + p.y = pos.y; + AdjustLevel(p, n, uv1, uv2); + if ( bUnder ) n.y = -n.y; + vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y); + + p.x = pos.x-size; + p.z = pos.z+sizez; + p.y = pos.y; + AdjustLevel(p, n, uv1, uv2); + if ( bUnder ) n.y = -n.y; + vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y); + + for ( j=0 ; jDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL); + m_engine->AddStatisticTriangle(u-2); + } + + free(vertex);*/ +} + +bool Gfx::CWater::GetWater(int x, int y) +{ + x *= m_subdiv; + y *= m_subdiv; + + float size = m_size/m_subdiv; + float offset = m_brick*m_size/2.0f; + + for (int dy = 0; dy <= m_subdiv; dy++) + { + for (int dx = 0; dx <= m_subdiv; dx++) + { + Math::Vector pos; + pos.x = (x+dx)*size - offset; + pos.z = (y+dy)*size - offset; + pos.y = 0.0f; + float level = m_terrain->GetFloorLevel(pos, true); + if (level < m_level+m_eddy.y) + return true; + } + } + return false; +} + +void Gfx::CWater::CreateLine(int x, int y, int len) +{ + Gfx::WaterLine line; + + line.x = x; + line.y = y; + line.len = len; + + float offset = m_brick*m_size/2.0f - m_size/2.0f; + + line.px1 = m_size* line.x - offset; + line.px2 = m_size*(line.x+line.len) - offset; + line.pz = m_size* line.y - offset; + + m_line.push_back(line); +} + +void Gfx::CWater::Create(Gfx::WaterType type1, Gfx::WaterType type2, const std::string& fileName, + Gfx::Color diffuse, Gfx::Color ambient, + float level, float glint, Math::Vector eddy) +{ + m_type[0] = type1; + m_type[1] = type2; + m_diffuse = diffuse; + m_ambient = ambient; + m_level = level; + m_glint = glint; + m_eddy = eddy; + m_time = 0.0f; + m_lastLava = 0.0f; + m_fileName = fileName; + + VaporFlush(); + + if (! m_fileName.empty()) + { + m_engine->LoadTexture(m_fileName, 0); + m_engine->LoadTexture(m_fileName, 1); + } + + if (m_terrain == nullptr) + m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); + + m_brick = m_terrain->GetBrick()*m_terrain->GetMosaic(); + m_size = m_terrain->GetSize(); + + m_brick /= m_subdiv; + m_size *= m_subdiv; + + if (m_type[0] == WATER_NULL) + return; + + m_line.clear(); + + for (int y = 0; y < m_brick; y++) + { + int len = 0; + for (int x = 0; x < m_brick; x++) + { + if (GetWater(x,y)) // water here? + { + len ++; + if (len >= 5) + { + CreateLine(x-len+1, y, len); + len = 0; + } + } + else // dry? + { + if (len != 0) + { + CreateLine(x-len, y, len); + len = 0; + } + } + } + if (len != 0) + CreateLine(m_brick - len, y, len); + } +} + +void Gfx::CWater::Flush() +{ + m_type[0] = Gfx::WATER_NULL; + m_type[1] = Gfx::WATER_NULL; + m_level = 0.0f; + m_lava = false; +} + +void Gfx::CWater::SetLevel(float level) +{ + m_level = level; + + Create(m_type[0], m_type[1], m_fileName, m_diffuse, m_ambient, + m_level, m_glint, m_eddy); +} + +float Gfx::CWater::GetLevel() +{ + return m_level; +} + +float Gfx::CWater::GetLevel(CObject* object) +{ + /* TODO! + ObjectType type = object->GetType(); + + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH ) + { + return m_level-3.0f; + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr ) + { + return m_level-2.0f; + } +*/ + return m_level; +} + +void Gfx::CWater::SetLava(bool lava) +{ + m_lava = lava; +} + +bool Gfx::CWater::GetLava() +{ + return m_lava; +} + +void Gfx::CWater::AdjustEye(Math::Vector &eye) +{ + if (m_lava) + { + if (eye.y < m_level+2.0f) + eye.y = m_level+2.0f; // never under the lava + } + else + { + if (eye.y >= m_level-2.0f && + eye.y <= m_level+2.0f) // close to the surface? + eye.y = m_level+2.0f; // bam, well above + } +} -// TODO implementation diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index 6d3736e..245baf7 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -19,50 +19,64 @@ #pragma once -#include "graphics/engine/engine.h" -#include "graphics/engine/particle.h" #include "common/event.h" +#include "graphics/engine/particle.h" class CInstanceManager; -class CSound; +class CSoundInterface; namespace Gfx { +class CEngine; class CTerrain; - -const short MAXWATERLINE = 500; - struct WaterLine { - short x, y; // beginning - short len; // length by x + //! Beginning + short x, y; + //! Length by x + short len; float px1, px2, pz; -}; - -const short MAXWATVAPOR = 10; + WaterLine() + { + x = y = 0; + len = 0; + px1 = px2 = pz = 0.0f; + } +}; struct WaterVapor { - bool bUsed; - ParticleType type; - Math::Vector pos; - float delay; - float time; - float last; + bool used; + Gfx::ParticleType type; + Math::Vector pos; + float delay; + float time; + float last; + + WaterVapor() + { + used = false; + type = Gfx::PARTIWATER; + delay = time = last = 0.0f; + } }; - enum WaterType { - WATER_NULL = 0, // no water - WATER_TT = 1, // transparent texture - WATER_TO = 2, // opaque texture - WATER_CT = 3, // transparent color - WATER_CO = 4, // opaque color + //! No water + WATER_NULL = 0, + //! Transparent texture + WATER_TT = 1, + //! Opaque texture + WATER_TO = 2, + //! Transparent color + WATER_CT = 3, + //! Opaque color + WATER_CO = 4, }; @@ -74,61 +88,86 @@ public: void SetDevice(Gfx::CDevice* device); bool EventProcess(const Event &event); + //! Removes all the water void Flush(); - bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy); + //! Creates all expanses of water + void Create(WaterType type1, WaterType type2, const std::string& fileName, + Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy); + //! Draw the back surface of the water void DrawBack(); + //! Draws the flat surface of the water void DrawSurf(); - bool SetLevel(float level); + //! Changes the level of the water + void SetLevel(float level); + //! Returns the current level of water float GetLevel(); + //! Returns the current level of water for a given object float GetLevel(CObject* object); - void SetLava(bool bLava); + //@{ + //! Management of the mode of lava/water + void SetLava(bool lava); bool GetLava(); + //@} + //! Adjusts the eye of the camera, not to be in the water void AdjustEye(Math::Vector &eye); protected: + //! Makes water evolve bool EventFrame(const Event &event); + //! Makes evolve the steam jets on the lava void LavaFrame(float rTime); + //! Adjusts the position to normal, to imitate reflections on an expanse of water at rest void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2); + //! Indicates if there is water in a given position bool GetWater(int x, int y); - bool CreateLine(int x, int y, int len); + //! Updates the positions, relative to the ground + void CreateLine(int x, int y, int len); + //! Removes all the steam jets void VaporFlush(); + //! Creates a new steam bool VaporCreate(ParticleType type, Math::Vector pos, float delay); + //! Makes evolve a steam jet void VaporFrame(int i, float rTime); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_device; - CTerrain* m_terrain; - CParticle* m_particule; - CSound* m_sound; + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; + Gfx::CDevice* m_device; + Gfx::CTerrain* m_terrain; + Gfx::CParticle* m_particule; + CSoundInterface* m_sound; WaterType m_type[2]; - char m_filename[100]; - float m_level; // overall level - float m_glint; // amplitude of reflections - Math::Vector m_eddy; // amplitude of swirls - Gfx::Color m_diffuse; // diffuse color - Gfx::Color m_ambient; // ambient color + std::string m_fileName; + //! Overall level + float m_level; + //! Amplitude of reflections + float m_glint; + //! Amplitude of swirls + Math::Vector m_eddy; + //! Diffuse color + Gfx::Color m_diffuse; + //! Ambient color + Gfx::Color m_ambient; float m_time; float m_lastLava; - int m_subdiv; - - int m_brick; // number of brick*mosaics - float m_size; // size of a item in an brick + int m_subdiv; - int m_lineUsed; - WaterLine m_line[MAXWATERLINE]; + //! Number of brick*mosaics + int m_brick; + //! Size of a item in an brick + float m_size; - WaterVapor m_vapor[MAXWATVAPOR]; + std::vector m_line; + std::vector m_vapor; - bool m_bDraw; - bool m_bLava; - long m_color; + bool m_draw; + bool m_lava; + long m_color; }; }; // namespace Gfx -- cgit v1.2.3-1-g7c22 From acff306cc132c4f8cc71f44f85ffd7bdd18a114e Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 9 Aug 2012 22:49:13 +0200 Subject: CPlanet implementation Added rewritten CPlanet implementation --- src/graphics/engine/planet.cpp | 164 ++++++++++++++++++++++++++++++++++++++++- src/graphics/engine/planet.h | 72 +++++++++++------- 2 files changed, 209 insertions(+), 27 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp index 4f1f614..022de66 100644 --- a/src/graphics/engine/planet.cpp +++ b/src/graphics/engine/planet.cpp @@ -19,5 +19,167 @@ #include "graphics/engine/planet.h" +#include "common/iman.h" +#include "graphics/core/device.h" +#include "graphics/engine/engine.h" -// TODO implementation + +const int PLANET_PREALLOCATE_COUNT = 10; + + +Gfx::CPlanet::CPlanet(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_PLANET, this); + + m_planet[0].reserve(PLANET_PREALLOCATE_COUNT); + m_planet[1].reserve(PLANET_PREALLOCATE_COUNT); + + m_engine = engine; + Flush(); + +} + +Gfx::CPlanet::~CPlanet() +{ + m_iMan = nullptr; +} + +void Gfx::CPlanet::Flush() +{ + for (int j = 0; j < 2; j++) + m_planet[j].clear(); + + m_planetExist = false; + m_mode = 0; + m_time = 0.0f; +} + +bool Gfx::CPlanet::EventProcess(const Event &event) +{ + if (event.type == EVENT_FRAME) + return EventFrame(event); + + return true; +} + +bool Gfx::CPlanet::EventFrame(const Event &event) +{ + if (m_engine->GetPause()) return true; + + m_time += event.rTime; + + for (int i = 0; i < static_cast( m_planet[m_mode].size() ); i++) + { + float a = m_time*m_planet[m_mode][i].speed; + if (a < 0.0f) + a += Math::PI*1000.0f; + + m_planet[m_mode][i].angle.x = a+m_planet[m_mode][i].start.x; + m_planet[m_mode][i].angle.y = sinf(a)*sinf(m_planet[m_mode][i].dir)+m_planet[m_mode][i].start.y; + } + + return true; +} + +void Gfx::CPlanet::LoadTexture() +{ + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < static_cast( m_planet[j].size() ); i++) + { + m_engine->LoadTexture(m_planet[j][i].name); + } + } +} + +void Gfx::CPlanet::Draw() +{ + Gfx::CDevice* device = m_engine->GetDevice(); + float eyeDirH = m_engine->GetEyeDirH(); + float eyeDirV = m_engine->GetEyeDirV(); + + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal + float dp = 0.5f/256.0f; + + for (int i = 0; i < static_cast( m_planet[m_mode].size() ); i++) + { + m_engine->SetTexture(m_planet[m_mode][i].name); + + if (m_planet[m_mode][i].transparent) + m_engine->SetState(Gfx::ENG_RSTATE_WRAP | Gfx::ENG_RSTATE_ALPHA); + else + m_engine->SetState(Gfx::ENG_RSTATE_WRAP | Gfx::ENG_RSTATE_TTEXTURE_BLACK); + + Math::Point p1, p2; + + float a = eyeDirH + m_planet[m_mode][i].angle.x; + p1.x = Math::Mod(a, Math::PI*2.0f)-0.5f; + + a = eyeDirV + m_planet[m_mode][i].angle.y; + p1.y = 0.4f+(Math::Mod(a+Math::PI, Math::PI*2.0f)-Math::PI)*(2.0f/Math::PI); + + p1.x -= m_planet[m_mode][i].dim/2.0f*0.75f; + p1.y -= m_planet[m_mode][i].dim/2.0f; + p2.x = p1.x+m_planet[m_mode][i].dim*0.75f; + p2.y = p1.y+m_planet[m_mode][i].dim; + + float u1 = m_planet[m_mode][i].uv1.x + dp; + float v1 = m_planet[m_mode][i].uv1.y + dp; + float u2 = m_planet[m_mode][i].uv2.x - dp; + float v2 = m_planet[m_mode][i].uv2.y - dp; + + Gfx::Vertex quad[4] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) + }; + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); + } +} + +void Gfx::CPlanet::Create(int mode, Math::Point start, float dim, float speed, + float dir, const std::string& name, Math::Point uv1, Math::Point uv2) +{ + if (mode < 0) mode = 0; + if (mode > 1) mode = 1; + + Gfx::Planet planet; + + planet.start = start; + planet.angle = start; + planet.dim = dim; + planet.speed = speed; + planet.dir = dir; + + planet.name = name; + planet.uv1 = uv1; + planet.uv2 = uv2; + + planet.transparent = planet.name.find("planet") != std::string::npos; + + m_planet[mode].push_back(planet); + + m_planetExist = true; +} + +bool Gfx::CPlanet::PlanetExist() +{ + return m_planetExist; +} + +void Gfx::CPlanet::SetMode(int mode) +{ + if (mode < 0) mode = 0; + if (mode > 1) mode = 1; + m_mode = mode; +} + +int Gfx::CPlanet::GetMode() +{ + return m_mode; +} diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 264d05c..5ba318b 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -22,6 +22,8 @@ #include "common/event.h" #include "math/point.h" +#include + class CInstanceManager; @@ -30,51 +32,69 @@ namespace Gfx { class CEngine; - -const short MAXPLANET = 10; - struct Planet { - char bUsed; // TRUE -> planet exists - Math::Point start; // initial position in degrees - Math::Point angle; // current position in degrees - float dim; // dimensions (0..1) - float speed; // speed - float dir; // direction in the sky - char name[20]; // name of the texture - Math::Point uv1, uv2; // texture mapping - char bTGA; // texture .TGA + //! Initial position in degrees + Math::Point start; + //! Current position in degrees + Math::Point angle; + //! Dimensions (0..1) + float dim; + //! Speed + float speed; + //! Direction in the sky + float dir; + //! Name of the texture + std::string name; + //! Texture mapping + Math::Point uv1, uv2; + //! Transparent texture + bool transparent; + + Planet() + { + dim = speed = dir = 0.0f; + transparent = false; + } }; - - - -class CPlanet { +class CPlanet +{ public: - CPlanet(CInstanceManager* iMan, CEngine* engine); + CPlanet(CInstanceManager* iMan, Gfx::CEngine* engine); ~CPlanet(); + //! Removes all the planets void Flush(); + //! Management of an event bool EventProcess(const Event &event); - bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2); + //! Creates a new planet + void Create(int mode, Math::Point start, float dim, float speed, float dir, + const std::string& name, Math::Point uv1, Math::Point uv2); + //! Indicates if there is at least one planet bool PlanetExist(); + //! Load all the textures for the planets void LoadTexture(); + //! Draws all the planets void Draw(); + //@{ + //! Choice of mode void SetMode(int mode); - int RetMode(); + int GetMode(); + //@} protected: + //! Makes the planets evolve bool EventFrame(const Event &event); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; - float m_time; - int m_mode; - Planet m_planet[2][MAXPLANET]; - bool m_bPlanetExist; + float m_time; + int m_mode; + std::vector m_planet[2]; + bool m_planetExist; }; - }; // namespace Gfx -- cgit v1.2.3-1-g7c22 From c3ab23ac9dc02d59180f2f1af5f3aa5b50f9f8d8 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 9 Aug 2012 22:50:04 +0200 Subject: Graphics stubs - added stubs for functions in CLightning, CParticle and CPyro - cleaned object.h and physics.h headers - created temporary stubs to compile CCamera - other necessary changes to compile successfully --- src/graphics/engine/camera.cpp | 81 +++++++++-- src/graphics/engine/camera.h | 4 +- src/graphics/engine/cloud.cpp | 8 +- src/graphics/engine/engine.cpp | 129 ++++++++++++++++- src/graphics/engine/engine.h | 22 ++- src/graphics/engine/lightning.cpp | 68 ++++++++- src/graphics/engine/lightning.h | 2 +- src/graphics/engine/particle.cpp | 281 +++++++++++++++++++++++++++++++++++++- src/graphics/engine/particle.h | 91 ++++++------ src/graphics/engine/pyro.cpp | 158 ++++++++++++++++++++- src/graphics/engine/pyro.h | 51 ++++--- src/graphics/engine/water.cpp | 6 +- 12 files changed, 798 insertions(+), 103 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp index c7ca503..2db6398 100644 --- a/src/graphics/engine/camera.cpp +++ b/src/graphics/engine/camera.cpp @@ -29,6 +29,66 @@ #include "physics/physics.h" +// TODO temporary stubs for CObject and CPhysics + +void CObject::SetTransparency(float) +{ +} + +CObject* CObject::GetFret() +{ + return nullptr; +} + +CObject* CObject::GetPower() +{ + return nullptr; +} + +CObject* CObject::GetTruck() +{ + return nullptr; +} + +ObjectType CObject::GetType() +{ + return OBJECT_NULL; +} + +void CObject::SetGunGoalH(float) +{ +} + +void CObject::GetGlobalSphere(Math::Vector &pos, float &radius) +{ +} + +float CObject::GetAngleY(int) +{ + return 0.0f; +} + +Math::Vector CObject::GetPosition(int) +{ + return Math::Vector(); +} + +void CObject::SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, + Math::Vector &lookat, Math::Vector &upVec, + Gfx::CameraType type) +{ +} + +CPhysics* CObject::GetPhysics() +{ + return nullptr; +} + +bool CPhysics::GetLand() +{ + return false; +} + //! Changes the level of transparency of an object and objects transported (battery & cargo) void SetTransparency(CObject* obj, float value) { @@ -332,7 +392,7 @@ void Gfx::CCamera::SetType(CameraType type) SetSmooth(Gfx::CAM_SMOOTH_NORM); } -CameraType Gfx::CCamera::GetType() +Gfx::CameraType Gfx::CCamera::GetType() { return m_type; } @@ -342,7 +402,7 @@ void Gfx::CCamera::SetSmooth(CameraSmooth type) m_smooth = type; } -CameraSmooth Gfx::CCamera::GetSmoth() +Gfx::CameraSmooth Gfx::CCamera::GetSmoth() { return m_smooth; } @@ -692,7 +752,7 @@ void Gfx::CCamera::OverFrame(const Event &event) } else { - color = Gfx::Color(0.0f. 0.0f, 0.0f); + color = Gfx::Color(0.0f, 0.0f, 0.0f); } color.a = 0.0f; m_engine->SetOverColor(color, m_overMode); @@ -873,7 +933,7 @@ bool Gfx::CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat) for (int i = 0 ;i < 1000000; i++) { - CObject *obj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + CObject *obj = static_cast( m_iMan->SearchInstance(CLASS_OBJECT, i) ); if (obj == NULL) break; if (obj->GetTruck()) continue; // battery or cargo? @@ -899,7 +959,7 @@ bool Gfx::CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat) iType == OBJECT_SAFE || iType == OBJECT_HUSTON ) continue; - ObjType oType = obj->GetType(); + ObjectType oType = obj->GetType(); if ( oType == OBJECT_HUMAN || oType == OBJECT_TECH || oType == OBJECT_TOTO || @@ -995,7 +1055,6 @@ bool Gfx::CCamera::EventProcess(const Event &event) { switch (event.type) { - // TODO: frame update event case EVENT_FRAME: EventFrame(event); break; @@ -1004,11 +1063,11 @@ bool Gfx::CCamera::EventProcess(const Event &event) EventMouseMove(event); break; - case EVENT_KEY_DOWN: - // TODO: mouse wheel event + // TODO: mouse wheel event + /*case EVENT_KEY_DOWN: if ( event.param == VK_WHEELUP ) EventMouseWheel(+1); if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1); - break; + break;*/ default: break; @@ -1489,8 +1548,6 @@ bool Gfx::CCamera::EventFrameFix(const Event &event) bool Gfx::CCamera::EventFrameExplo(const Event &event) { - float factor = m_heightEye * 0.5f + 30.0f; - if (m_mouseDirH != 0.0f) m_directionH -= m_mouseDirH * event.rTime * 0.7f * m_speed; @@ -1526,7 +1583,7 @@ bool Gfx::CCamera::EventFrameOnBoard(const Event &event) { Math::Vector lookatPt, upVec; m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV, - lookatPt, vUpVec, m_type); + lookatPt, upVec, m_type); Math::Vector eye = m_effectOffset * 0.3f + m_eyePt; Math::Vector lookat = m_effectOffset * 0.3f + lookatPt; diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h index 935f8b0..ec6afcb 100644 --- a/src/graphics/engine/camera.h +++ b/src/graphics/engine/camera.h @@ -353,13 +353,13 @@ protected: float m_centeringTime; float m_centeringProgress; - CameraEffect m_effectType; + Gfx::CameraEffect m_effectType; Math::Vector m_effectPos; float m_effectForce; float m_effectProgress; Math::Vector m_effectOffset; - OverEffect m_overType; + Gfx::CameraOverEffect m_overType; float m_overForce; float m_overTime; Gfx::Color m_overColorBase; diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index e46b074..71dd969 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -55,16 +55,14 @@ Gfx::CCloud::~CCloud() bool Gfx::CCloud::EventProcess(const Event &event) { - /* TODO! - if ( event.event == EVENT_FRAME ) - return EventFrame(event); */ + if ( event.type == EVENT_FRAME ) + return EventFrame(event); return true; } bool Gfx::CCloud::EventFrame(const Event &event) { - /* TODO! if (m_engine->GetPause()) return true; m_time += event.rTime; @@ -73,7 +71,7 @@ bool Gfx::CCloud::EventFrame(const Event &event) if (m_time - m_lastTest < 0.2f) return true; - m_lastTest = m_time; */ + m_lastTest = m_time; return true; } diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 4bf80d2..c8fa05c 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -25,8 +25,16 @@ #include "common/key.h" #include "common/logger.h" #include "graphics/core/device.h" +#include "graphics/engine/camera.h" +#include "graphics/engine/cloud.h" #include "graphics/engine/lightman.h" +#include "graphics/engine/lightning.h" +#include "graphics/engine/particle.h" +#include "graphics/engine/planet.h" +#include "graphics/engine/pyro.h" +#include "graphics/engine/terrain.h" #include "graphics/engine/text.h" +#include "graphics/engine/water.h" #include "math/geometry.h" // Initial size of various vectors @@ -207,12 +215,11 @@ bool Gfx::CEngine::Create() m_lightMan = new Gfx::CLightManager(m_iMan, this); m_text = new Gfx::CText(m_iMan, this); - /* TODO: m_particle = new Gfx::CParticle(m_iMan, this); m_water = new Gfx::CWater(m_iMan, this); m_cloud = new Gfx::CCloud(m_iMan, this); m_lightning = new Gfx::CLightning(m_iMan, this); - m_planet = new Gfx::CPlanet(m_iMan, this);*/ + m_planet = new Gfx::CPlanet(m_iMan, this); m_text->SetDevice(m_device); if (! m_text->Create()) @@ -250,7 +257,6 @@ void Gfx::CEngine::Destroy() delete m_text; m_text = nullptr; - /* TODO: delete m_particle; m_particle = nullptr; @@ -264,7 +270,7 @@ void Gfx::CEngine::Destroy() m_lightning = nullptr; delete m_planet; - m_planet = nullptr;*/ + m_planet = nullptr; } void Gfx::CEngine::ResetAfterDeviceChanged() @@ -807,3 +813,118 @@ bool Gfx::CEngine::GetShowStat() return m_showStats; } +void Gfx::CEngine::SetFocus(float focus) +{ + m_focus = focus; +} + + +void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) +{ + // TODO! +} + +void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) +{ + // TODO! +} + +Gfx::Color Gfx::CEngine::GetFogColor(int rank) +{ + // TODO! + return Gfx::Color(); +} + +void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, + const Math::Vector& upVec, float eyeDistance) +{ + // TODO! +} + +void Gfx::CEngine::SetRankView(int rank) +{ + m_rankView = rank; +} + +float Gfx::CEngine::GetEyeDirH() +{ + return m_eyeDirH; +} + +float Gfx::CEngine::GetEyeDirV() +{ + return m_eyeDirV; +} + +float Gfx::CEngine::GetClippingDistance() +{ + return m_clippingDistance; +} + +bool Gfx::CEngine::GetGroundSpot() +{ + return m_groundSpotVisible; +} + +void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) +{ + m_terrain = terrain; +} + +void Gfx::CEngine::SetTerrainVision(float vision) +{ + // TODO! +} + +bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +{ + // TODO! + return true; +} + +float Gfx::CEngine::ParticleAdapt(float factor) +{ + // TODO! + return 0.0f; +} + +bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) +{ + // TODO! + return true; +} + +int Gfx::CEngine::CreateObject() +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::DeleteObject(int objRank) +{ + // TODO! + return true; +} + +int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate) +{ + // TODO! + return false; +} + +void Gfx::CEngine::Update() +{ + // TODO! +} diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index cd89a1c..e61aca6 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -170,7 +170,10 @@ struct EngineObjLevel5 Gfx::EngineTriangleType type; std::vector vertices; - EngineObjLevel5(); + EngineObjLevel5() + { + state = 0; + } }; /** @@ -182,7 +185,10 @@ struct EngineObjLevel4 std::vector up; Gfx::EngineObjLevel3* down; - EngineObjLevel4(); + EngineObjLevel4() + { + reserved = 0; + } }; /** @@ -195,7 +201,10 @@ struct EngineObjLevel3 std::vector up; Gfx::EngineObjLevel2* down; - EngineObjLevel3(); + EngineObjLevel3() + { + min = max = 0.0f; + } }; /** @@ -207,7 +216,10 @@ struct EngineObjLevel2 std::vector up; Gfx::EngineObjLevel1* down; - EngineObjLevel2(); + EngineObjLevel2() + { + objRank = 0; + } }; /** @@ -219,7 +231,7 @@ struct EngineObjLevel1 Gfx::Texture tex2; std::vector up; - EngineObjLevel1(); + EngineObjLevel1() {} }; /** diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp index 4db5511..4ecdb3c 100644 --- a/src/graphics/engine/lightning.cpp +++ b/src/graphics/engine/lightning.cpp @@ -19,5 +19,71 @@ #include "graphics/engine/lightning.h" +#include "common/logger.h" -// TODO implementation + +Gfx::CLightning::CLightning(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + GetLogger()->Info("CLightning::CLightning() stub!\n"); + // TODO! +} + +Gfx::CLightning::~CLightning() +{ + GetLogger()->Info("CLightning::~CLightning() stub!\n"); + // TODO! +} + +void Gfx::CLightning::Flush() +{ + GetLogger()->Info("CLightning::Flush() stub!\n"); + // TODO! +} + +bool Gfx::CLightning::EventProcess(const Event &event) +{ + GetLogger()->Info("CLightning::EventProcess() stub!\n"); + // TODO! + return true; +} + +bool Gfx::CLightning::Create(float sleep, float delay, float magnetic) +{ + GetLogger()->Info("CLightning::Create() stub!\n"); + // TODO! + return true; +} + +bool Gfx::CLightning::GetStatus(float &sleep, float &delay, float &magnetic, float &progress) +{ + GetLogger()->Info("CLightning::GetStatus() stub!\n"); + // TODO! + return true; +} + +bool Gfx::CLightning::SetStatus(float sleep, float delay, float magnetic, float progress) +{ + GetLogger()->Info("CLightning::SetStatus() stub!\n"); + // TODO! + return true; +} + +void Gfx::CLightning::Draw() +{ + GetLogger()->Info("CLightning::Draw() stub!\n"); + // TODO! +} + +bool Gfx::CLightning::EventFrame(const Event &event) +{ + GetLogger()->Info("CLightning::EventFrame() stub!\n"); + // TODO! + return true; +} + +CObject* Gfx::CLightning::SearchObject(Math::Vector pos) +{ + GetLogger()->Info("CLightning::SearchObject() stub!\n"); + // TODO! + return nullptr; +} diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h index 957344c..9e854be 100644 --- a/src/graphics/engine/lightning.h +++ b/src/graphics/engine/lightning.h @@ -73,7 +73,7 @@ protected: float m_sleep; float m_delay; float m_magnetic; - BlitzPhase m_phase; + Gfx::BlitzPhase m_phase; float m_time; float m_speed; float m_progress; diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 84e2f9d..9a21fe0 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -19,5 +19,284 @@ #include "graphics/engine/particle.h" +#include "common/logger.h" -// TODO implementation + +Gfx::CParticle::CParticle(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + GetLogger()->Info("CParticle::CParticle() stub!\n"); + // TODO! +} + +Gfx::CParticle::~CParticle() +{ + GetLogger()->Info("CParticle::~CParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetDevice(Gfx::CDevice* device) +{ + GetLogger()->Info("CParticle::SetDevice() stub!\n"); + // TODO! +} + +void Gfx::CParticle::FlushParticle() +{ + GetLogger()->Info("CParticle::FlushParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::FlushParticle(int sheet) +{ + GetLogger()->Info("CParticle::FlushParticle() stub!\n"); + // TODO! +} + +int Gfx::CParticle::CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, + Gfx::ParticleType type, float duration, float mass, + float windSensitivity, int sheet) +{ + GetLogger()->Info("CParticle::CreateParticle() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, + Gfx::ParticleType type, float duration, float mass, + float windSensitivity, int sheet) +{ + GetLogger()->Info("CParticle::CreateFrag() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreatePart(Math::Vector pos, Math::Vector speed, Gfx::ParticleType type, + float duration, float mass, float weight, + float windSensitivity, int sheet) +{ + GetLogger()->Info("CParticle::CreatePart() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreateRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, Math::Point dim, + float duration, int sheet) +{ + GetLogger()->Info("CParticle::CreateRay() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, Gfx::ParticleType type, + float duration, float mass, float length, float width) +{ + GetLogger()->Info("CParticle::CreateTrack() stub!\n"); + // TODO! + return 0; +} + +void Gfx::CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, + const Math::Vector &p4, Gfx::ParticleType type) +{ + GetLogger()->Info("CParticle::CreateWheelTrace() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DeleteParticle(Gfx::ParticleType type) +{ + GetLogger()->Info("CParticle::DeleteParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DeleteParticle(int channel) +{ + GetLogger()->Info("CParticle::DeleteParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetObjectLink(int channel, CObject *object) +{ + GetLogger()->Info("CParticle::SetObjectLink() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetObjectFather(int channel, CObject *object) +{ + GetLogger()->Info("CParticle::SetObjectFather() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetPosition(int channel, Math::Vector pos) +{ + GetLogger()->Info("CParticle::SetPosition() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetDimension(int channel, Math::Point dim) +{ + GetLogger()->Info("CParticle::SetDimension() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetZoom(int channel, float zoom) +{ + GetLogger()->Info("CParticle::SetZoom() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetAngle(int channel, float angle) +{ + GetLogger()->Info("CParticle::SetAngle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetIntensity(int channel, float intensity) +{ + GetLogger()->Info("CParticle::SetIntensity() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity) +{ + GetLogger()->Info("CParticle::SetParam() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetPhase(int channel, Gfx::ParticlePhase phase, float duration) +{ + GetLogger()->Info("CParticle::SetPhase() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::GetPosition(int channel, Math::Vector &pos) +{ + GetLogger()->Info("CParticle::GetPosition() stub!\n"); + // TODO! + return true; +} + +Gfx::Color Gfx::CParticle::GetFogColor(Math::Vector pos) +{ + GetLogger()->Info("CParticle::GetFogColor() stub!\n"); + // TODO! + return Gfx::Color(); +} + +void Gfx::CParticle::SetFrameUpdate(int sheet, bool update) +{ + GetLogger()->Info("CParticle::SetFrameUpdate() stub!\n"); + // TODO! +} + +void Gfx::CParticle::FrameParticle(float rTime) +{ + GetLogger()->Info("CParticle::FrameParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticle(int sheet) +{ + GetLogger()->Info("CParticle::DrawParticle() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur) +{ + GetLogger()->Info("CParticle::WriteWheelTrace() stub!\n"); + // TODO! + return true; +} + +void Gfx::CParticle::DeleteRank(int rank) +{ + GetLogger()->Info("CParticle::DeleteRank() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::CheckChannel(int &channel) +{ + GetLogger()->Info("CParticle::CheckChannel() stub!\n"); + // TODO! + return true; +} + +void Gfx::CParticle::DrawParticleTriangle(int i) +{ + GetLogger()->Info("CParticle::DrawParticleTriangle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleNorm(int i) +{ + GetLogger()->Info("CParticle::DrawParticleNorm() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleFlat(int i) +{ + GetLogger()->Info("CParticle::DrawParticleFlat() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleFog(int i) +{ + GetLogger()->Info("CParticle::DrawParticleFog() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleRay(int i) +{ + GetLogger()->Info("CParticle::DrawParticleRay() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleSphere(int i) +{ + GetLogger()->Info("CParticle::DrawParticleSphere() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleCylinder(int i) +{ + GetLogger()->Info("CParticle::DrawParticleCylinder() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleWheel(int i) +{ + GetLogger()->Info("CParticle::DrawParticleWheel() stub!\n"); + // TODO! +} + +CObject* Gfx::CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, Gfx::ParticleType type, CObject *father) +{ + GetLogger()->Info("CParticle::SearchObjectGun() stub!\n"); + // TODO! + return nullptr; +} + +CObject* Gfx::CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, CObject *father) +{ + GetLogger()->Info("CParticle::SearchObjectRay() stub!\n"); + // TODO! + return nullptr; +} + +void Gfx::CParticle::Play(Sound sound, Math::Vector pos, float amplitude) +{ + GetLogger()->Info("CParticle::Play() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::TrackMove(int i, Math::Vector pos, float progress) +{ + GetLogger()->Info("CParticle::TrackMove() stub!\n"); + // TODO! + return true; +} + +void Gfx::CParticle::TrackDraw(int i, Gfx::ParticleType type) +{ + GetLogger()->Info("CParticle::TrackDraw() stub!\n"); + // TODO! +} diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index 94aacfc..89e2c5b 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -202,26 +202,26 @@ enum ParticlePhase struct Particle { - char bUsed; // TRUE -> particle used - char bRay; // TRUE -> ray with goal - unsigned short uniqueStamp; // unique mark + char used; // TRUE -> particle used + char ray; // TRUE -> ray with goal + unsigned short uniqueStamp; // unique mark short sheet; // sheet (0..n) - ParticleType type; // type PARTI* - ParticlePhase phase; // phase PARPH* + ParticleType type; // type PARTI* + ParticlePhase phase; // phase PARPH* float mass; // mass of the particle (in rebounding) float weight; // weight of the particle (for noise) float duration; // length of life - Math::Vector pos; // absolute position (relative if object links) - Math::Vector goal; // goal position (if bRay) - Math::Vector speed; // speed of displacement + Math::Vector pos; // absolute position (relative if object links) + Math::Vector goal; // goal position (if ray) + Math::Vector speed; // speed of displacement float windSensitivity; short bounce; // number of rebounds - Math::Point dim; // dimensions of the rectangle + Math::Point dim; // dimensions of the rectangle float zoom; // zoom (0..1) float angle; // angle of rotation float intensity; // intensity - Math::Point texSup; // coordinated upper texture - Math::Point texInf; // coordinated lower texture + Math::Point texSup; // coordinated upper texture + Math::Point texInf; // coordinated lower texture float time; // age of the particle (0..n) float phaseTime; // age at the beginning of phase float testTime; // time since last test @@ -233,22 +233,22 @@ struct Particle struct Track { - char bUsed; // TRUE -> drag used - char bDrawParticle; + char used; // TRUE -> drag used + char drawParticle; float step; // duration of not float last; // increase last not memorized float intensity; // intensity at starting (0..1) float width; // tail width - int used; // number of positions in "pos" - int head; // head to write index - Math::Vector pos[MAXTRACKLEN]; + int posUsed; // number of positions in "pos" + int head; // head to write index + Math::Vector pos[MAXTRACKLEN]; float len[MAXTRACKLEN]; }; struct WheelTrace { - ParticleType type; // type PARTI* - Math::Vector pos[4]; // rectangle positions + ParticleType type; // type PARTI* + Math::Vector pos[4]; // rectangle positions float startTime; // beginning of life }; @@ -257,20 +257,29 @@ struct WheelTrace class CParticle { public: - CParticle(CInstanceManager* iMan, CEngine* engine); + CParticle(CInstanceManager* iMan, Gfx::CEngine* engine); ~CParticle(); - void SetDevice(CDevice* device); + void SetDevice(Gfx::CDevice* device); void FlushParticle(); void FlushParticle(int sheet); - int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0); - int CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, ParticleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0); - int CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0); - int CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim, float duration=1.0f, int sheet=0); - int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f); - void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticleType type); - void DeleteParticle(ParticleType type); + int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, + Gfx::ParticleType type, float duration=1.0f, float mass=0.0f, + float windSensitivity=1.0f, int sheet=0); + int CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, + Gfx::ParticleType type, float duration=1.0f, float mass=0.0f, + float windSensitivity=1.0f, int sheet=0); + int CreatePart(Math::Vector pos, Math::Vector speed, Gfx::ParticleType type, + float duration=1.0f, float mass=0.0f, float weight=0.0f, + float windSensitivity=1.0f, int sheet=0); + int CreateRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, Math::Point dim, + float duration=1.0f, int sheet=0); + int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, Gfx::ParticleType type, + float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f); + void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, + const Math::Vector &p4, Gfx::ParticleType type); + void DeleteParticle(Gfx::ParticleType type); void DeleteParticle(int channel); void SetObjectLink(int channel, CObject *object); void SetObjectFather(int channel, CObject *object); @@ -280,12 +289,12 @@ public: void SetAngle(int channel, float angle); void SetIntensity(int channel, float intensity); void SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity); - void SetPhase(int channel, ParticlePhase phase, float duration); + void SetPhase(int channel, Gfx::ParticlePhase phase, float duration); bool GetPosition(int channel, Math::Vector &pos); Gfx::Color GetFogColor(Math::Vector pos); - void SetFrameUpdate(int sheet, bool bUpdate); + void SetFrameUpdate(int sheet, bool update); void FrameParticle(float rTime); void DrawParticle(int sheet); @@ -302,29 +311,29 @@ protected: void DrawParticleSphere(int i); void DrawParticleCylinder(int i); void DrawParticleWheel(int i); - CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father); - CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father); + CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, Gfx::ParticleType type, CObject *father); + CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, CObject *father); void Play(Sound sound, Math::Vector pos, float amplitude); bool TrackMove(int i, Math::Vector pos, float progress); - void TrackDraw(int i, ParticleType type); + void TrackDraw(int i, Gfx::ParticleType type); protected: CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_device; - CRobotMain* m_main; - CTerrain* m_terrain; - CWater* m_water; - CSound* m_sound; + Gfx::CEngine* m_engine; + Gfx::CDevice* m_device; + Gfx::CTerrain* m_terrain; + Gfx::CWater* m_water; + CRobotMain* m_main; + CSound* m_sound; Gfx::Particle m_particule[MAXPARTICULE*MAXPARTITYPE]; Gfx::EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0 - Track m_track[MAXTRACK]; + Gfx::Track m_track[MAXTRACK]; int m_wheelTraceTotal; int m_wheelTraceIndex; - WheelTrace m_wheelTrace[MAXWHEELTRACE]; + Gfx::WheelTrace m_wheelTrace[MAXWHEELTRACE]; int m_totalInterface[MAXPARTITYPE][SH_MAX]; - bool m_bFrameUpdate[SH_MAX]; + bool m_frameUpdate[SH_MAX]; int m_fogTotal; int m_fog[MAXPARTIFOG]; int m_uniqueStamp; diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp index e699db2..327befa 100644 --- a/src/graphics/engine/pyro.cpp +++ b/src/graphics/engine/pyro.cpp @@ -19,5 +19,161 @@ #include "graphics/engine/pyro.h" +#include "common/logger.h" -// TODO implementation + +Gfx::CPyro::CPyro(CInstanceManager* iMan) +{ + GetLogger()->Info("CParticle::CPyro() stub!\n"); + // TODO! +} + +Gfx::CPyro::~CPyro() +{ + GetLogger()->Info("CPyro::~CPyro() stub!"); + // TODO! +} + +void Gfx::CPyro::DeleteObject(bool all) +{ + GetLogger()->Info("CPyro::DeleteObject() stub!"); + // TODO! +} + +bool Gfx::CPyro::Create(Gfx::PyroType type, CObject* pObj, float force) +{ + GetLogger()->Info("CPyro::Create() stub!"); + // TODO! + return true; +} + +bool Gfx::CPyro::EventProcess(const Event &event) +{ + GetLogger()->Info("CPyro::EventProcess() stub!\n"); + // TODO! + return true; +} + +Error Gfx::CPyro::IsEnded() +{ + GetLogger()->Info("CPyro::IsEnded() stub!\n"); + // TODO! + return ERR_OK; +} + +void Gfx::CPyro::CutObjectLink(CObject* pObj) +{ + GetLogger()->Info("CPyro::CutObjectLink() stub!\n"); + // TODO! +} + +void Gfx::CPyro::DisplayError(PyroType type, CObject* pObj) +{ + GetLogger()->Info("CPyro::DisplayError() stub!\n"); + // TODO! +} + +bool Gfx::CPyro::CreateLight(Math::Vector pos, float height) +{ + GetLogger()->Info("CPyro::CreateLight() stub!\n"); + // TODO! + return true; +} + +void Gfx::CPyro::DeleteObject(bool primary, bool secondary) +{ + GetLogger()->Info("CPyro::DeleteObject() stub!\n"); + // TODO! +} + +void Gfx::CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part) +{ + GetLogger()->Info("CPyro::CreateTriangle() stub!\n"); + // TODO! +} + +void Gfx::CPyro::ExploStart() +{ + GetLogger()->Info("CPyro::ExploStart() stub!\n"); + // TODO! +} +void Gfx::CPyro::ExploTerminate() +{ + GetLogger()->Info("CPyro::ExploTerminate() stub!\n"); + // TODO! +} + +void Gfx::CPyro::BurnStart() +{ + GetLogger()->Info("CPyro::BurnStart() stub!\n"); + // TODO! +} + +void Gfx::CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle) +{ + GetLogger()->Info("CPyro::BurnAddPart() stub!\n"); + // TODO! +} + +void Gfx::CPyro::BurnProgress() +{ + GetLogger()->Info("CPyro::BurnProgress() stub!\n"); + // TODO! +} + +bool Gfx::CPyro::BurnIsKeepPart(int part) +{ + GetLogger()->Info("CPyro::BurnIsKeepPart() stub!\n"); + // TODO! + return true; +} + +void Gfx::CPyro::BurnTerminate() +{ + GetLogger()->Info("CPyro::BurnTerminate() stub!\n"); + // TODO! +} + +void Gfx::CPyro::FallStart() +{ + GetLogger()->Info("CPyro::FallStart() stub!\n"); + // TODO! +} + +CObject* Gfx::CPyro::FallSearchBeeExplo() +{ + GetLogger()->Info("CPyro::FallSearchBeeExplo() stub!\n"); + // TODO! + return nullptr; +} + +void Gfx::CPyro::FallProgress(float rTime) +{ + GetLogger()->Info("CPyro::FallProgress() stub!\n"); + // TODO! +} + +Error Gfx::CPyro::FallIsEnded() +{ + GetLogger()->Info("CPyro::FallIsEnded() stub!\n"); + // TODO! + return ERR_OK; +} + +void Gfx::CPyro::LightOperFlush() +{ + GetLogger()->Info("CPyro::LightOperFlush() stub!\n"); + // TODO! +} + +void Gfx::CPyro::LightOperAdd(float progress, float intensity, float r, float g, float b) +{ + GetLogger()->Info("CPyro::LightOperAdd() stub!\n"); + // TODO! +} + +void Gfx::CPyro::LightOperFrame(float rTime) +{ + GetLogger()->Info("CPyro::LightOperFrame() stub!\n"); + // TODO! +} diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h index d663ca5..35b5c5f 100644 --- a/src/graphics/engine/pyro.h +++ b/src/graphics/engine/pyro.h @@ -21,9 +21,7 @@ #include "common/misc.h" #include "graphics/engine/engine.h" -//#include "object/object.h" -// TEMPORARILY! -enum ObjectType {}; +#include "object/object.h" class CInstanceManager; @@ -90,13 +88,14 @@ struct PyroLightOper -class CPyro { +class CPyro +{ public: CPyro(CInstanceManager* iMan); ~CPyro(); - void DeleteObject(bool bAll=false); - bool Create(PyroType type, CObject* pObj, float force=1.0f); + void DeleteObject(bool all=false); + bool Create(Gfx::PyroType type, CObject* pObj, float force=1.0f); bool EventProcess(const Event &event); Error IsEnded(); void CutObjectLink(CObject* pObj); @@ -104,7 +103,7 @@ public: protected: void DisplayError(PyroType type, CObject* pObj); bool CreateLight(Math::Vector pos, float height); - void DeleteObject(bool bPrimary, bool bSecondary); + void DeleteObject(bool primary, bool secondary); void CreateTriangle(CObject* pObj, ObjectType oType, int part); @@ -127,21 +126,21 @@ protected: void LightOperFrame(float rTime); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; - CTerrain* m_terrain; - CCamera* m_camera; - CParticle* m_particule; - CLight* m_light; - CObject* m_object; - CDisplayText* m_displayText; - CRobotMain* m_main; - CSound* m_sound; - - Math::Vector m_pos; // center of the effect - Math::Vector m_posPower; // center of the battery - bool m_bPower; // battery exists? - PyroType m_type; + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; + Gfx::CTerrain* m_terrain; + Gfx::CCamera* m_camera; + Gfx::CParticle* m_particule; + Gfx::CLightManager* m_lightMan; + CObject* m_object; + CDisplayText* m_displayText; + CRobotMain* m_main; + CSound* m_sound; + + Math::Vector m_pos; // center of the effect + Math::Vector m_posPower; // center of the battery + bool m_power; // battery exists? + Gfx::PyroType m_type; float m_force; float m_size; float m_progress; @@ -153,22 +152,22 @@ protected: int m_lightRank; int m_lightOperTotal; - PyroLightOper m_lightOper[10]; + Gfx::PyroLightOper m_lightOper[10]; float m_lightHeight; ObjectType m_burnType; int m_burnPartTotal; - PyroBurnPart m_burnPart[10]; + Gfx::PyroBurnPart m_burnPart[10]; int m_burnKeepPart[10]; float m_burnFall; float m_fallFloor; float m_fallSpeed; float m_fallBulletTime; - bool m_bFallEnding; + bool m_fallEnding; int m_crashSphereUsed; // number of spheres used - Math::Vector m_crashSpherePos[50]; + Math::Vector m_crashSpherePos[50]; float m_crashSphereRadius[50]; }; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 1f11671..0ec52eb 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -66,16 +66,14 @@ Gfx::CWater::~CWater() bool Gfx::CWater::EventProcess(const Event &event) { - /* TODO! if (event.type == EVENT_FRAME) return EventFrame(event); -*/ + return true; } bool Gfx::CWater::EventFrame(const Event &event) { - /* TODO! if (m_engine->GetPause()) return true; m_time += event.rTime; @@ -83,7 +81,7 @@ bool Gfx::CWater::EventFrame(const Event &event) if (m_type[0] == WATER_NULL) return true; if (m_lava) - LavaFrame(event.rTime);*/ + LavaFrame(event.rTime); return true; } -- cgit v1.2.3-1-g7c22 From 63257034c946d40fb3ecc73a9ee3dc9d1e0a1e34 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 10 Aug 2012 23:31:42 +0200 Subject: Partial CEngine implementation - added rewritten implementation for basic modesetting in CEngine - started rewriting proper rendering and object handling in CEngine --- src/graphics/core/color.h | 6 +- src/graphics/engine/engine.cpp | 2722 +++++++++++++++++++++++++++++++++------- src/graphics/engine/engine.h | 477 ++++--- 3 files changed, 2561 insertions(+), 644 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h index 6973644..0e08de3 100644 --- a/src/graphics/core/color.h +++ b/src/graphics/core/color.h @@ -18,7 +18,6 @@ #pragma once - #include @@ -66,6 +65,11 @@ struct Color { return r == other.r && g == other.g && b == other.b && a == other.a; } + + inline bool operator!=(const Gfx::Color &other) const + { + return ! this->operator==(other); + } }; /** diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c8fa05c..4244fb2 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -36,6 +36,8 @@ #include "graphics/engine/text.h" #include "graphics/engine/water.h" #include "math/geometry.h" +#include "sound/sound.h" + // Initial size of various vectors const int OBJECT_PREALLOCATE_COUNT = 1200; @@ -50,6 +52,13 @@ const int LEVEL5_PREALLOCATE_COUNT = 100; const int LEVEL5_VERTEX_PREALLOCATE_COUNT = 200; +// TODO: temporary stub for CInterface +class CInterface +{ +public: + void Draw() {} +}; + Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) { m_iMan = iMan; @@ -60,7 +69,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_iMan->AddInstance(CLASS_ENGINE, this); m_app = app; - m_lightMan = nullptr; + m_lightMan = nullptr; m_text = nullptr; m_particle = nullptr; m_water = nullptr; @@ -107,15 +116,14 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_overFront = true; m_overColor = 0; m_overMode = ENG_RSTATE_TCOLOR_BLACK; - m_frontsizeName = ""; // no front image - m_hiliteRank[0] = -1; // empty list + m_highlightRank[0] = -1; // empty list m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f); m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f); m_drawWorld = true; m_drawFront = false; m_limitLOD[0] = 100.0f; m_limitLOD[1] = 200.0f; - m_particuleDensity = 1.0f; + m_particleDensity = 1.0f; m_clippingDistance = 1.0f; m_lastClippingDistance = m_clippingDistance; m_objectDetail = 1.0f; @@ -186,11 +194,10 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) Gfx::CEngine::~CEngine() { - m_iMan = nullptr; - m_app = nullptr; - m_device = nullptr; - - m_sound = nullptr; + m_iMan = nullptr; + m_app = nullptr; + m_device = nullptr; + m_sound = nullptr; m_terrain = nullptr; } @@ -209,6 +216,16 @@ Gfx::CDevice* Gfx::CEngine::GetDevice() return m_device; } +void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) +{ + m_terrain = terrain; +} + +Gfx::CText* Gfx::CEngine::GetText() +{ + return m_text; +} + bool Gfx::CEngine::Create() { m_size = m_lastSize = m_app->GetVideoConfig().size; @@ -228,14 +245,17 @@ bool Gfx::CEngine::Create() return false; } + m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetShadeModel(Gfx::SHADE_SMOOTH); + m_device->SetFillMode(Gfx::FILL_FILL); + + SetFocus(m_focus); m_matWorldInterface.LoadIdentity(); m_matViewInterface.LoadIdentity(); - Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); - - m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); Gfx::TextureCreateParams params; params.format = Gfx::TEX_IMG_RGB; @@ -275,414 +295,2326 @@ void Gfx::CEngine::Destroy() void Gfx::CEngine::ResetAfterDeviceChanged() { - // TODO + // TODO reload textures, reset device state, etc. } -Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) +bool Gfx::CEngine::ProcessEvent(const Event &event) { - CImage img; - if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) + if (event.type == EVENT_MOUSE_MOVE) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << img.GetError(); - m_error = str.str(); - return Gfx::Texture(); // invalid texture + m_mousePos = event.mouseMove.pos; } + else if (event.type == EVENT_KEY_DOWN) + { + // !! Debug, to be removed later !! - Gfx::Texture result = m_device->CreateTexture(&img, params); + if (event.key.key == KEY(F1)) + { + m_mouseVisible = !m_mouseVisible; + m_app->SetSystemMouseVisible(! m_app->GetSystemMouseVisibile()); + } + else if (event.key.key == KEY(F2)) + { + int index = static_cast(m_mouseType); + m_mouseType = static_cast( (index + 1) % Gfx::ENG_MOUSE_COUNT ); + } + } - if (! result.valid) + // By default, pass on all events + return true; +} + +void Gfx::CEngine::FrameMove(float rTime) +{ + m_lightMan->UpdateProgression(rTime); + m_particle->FrameParticle(rTime); + ComputeDistance(); + UpdateGeometry(); + + if (m_groundMark.draw) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); - m_error = str.str(); - return result; + if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_INC) // growing? + { + m_groundMark.intensity += rTime*(1.0f/m_groundMark.delay[0]); + if (m_groundMark.intensity >= 1.0f) + { + m_groundMark.intensity = 1.0f; + m_groundMark.fix = 0.0f; + m_groundMark.phase = Gfx::ENG_GR_MARK_PHASE_FIX; + } + } + else if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_FIX) // fixed? + { + m_groundMark.fix += rTime*(1.0f/m_groundMark.delay[1]); + if (m_groundMark.fix >= 1.0f) + m_groundMark.phase = Gfx::ENG_GR_MARK_PHASE_DEC; + } + else if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_DEC) // decay? + { + m_groundMark.intensity -= rTime*(1.0f/m_groundMark.delay[2]); + if (m_groundMark.intensity < 0.0f) + { + m_groundMark.intensity = 0.0f; + m_groundMark.phase = Gfx::ENG_GR_MARK_PHASE_NULL; + m_groundMark.draw = false; + } + } } - m_texNameMap[texName] = result; - m_revTexNameMap[result] = texName; + if (m_sound == nullptr) + m_sound = static_cast( m_iMan->SearchInstance(CLASS_SOUND) ); - return result; + m_sound->FrameMove(rTime); } -Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName) +void Gfx::CEngine::StepSimulation(float rTime) { - return CreateTexture(texName, m_defaultTexParams); + m_app->StepSimulation(rTime); } -void Gfx::CEngine::DestroyTexture(const std::string &texName) +void Gfx::CEngine::TimeInit() { - std::map::iterator it = m_texNameMap.find(texName); - if (it == m_texNameMap.end()) - return; - - std::map::iterator revIt = m_revTexNameMap.find((*it).second); + /* TODO! + m_baseTime = timeGetTime(); + m_lastTime = 0; + m_absTime = 0.0f;*/ +} - m_device->DestroyTexture((*it).second); +void Gfx::CEngine::TimeEnterGel() +{ + /* TODO! + m_stopTime = timeGetTime();*/ +} - m_revTexNameMap.erase(revIt); - m_texNameMap.erase(it); +void Gfx::CEngine::TimeExitGel() +{ + /* TODO! + m_baseTime += timeGetTime() - m_stopTime;*/ } -void Gfx::CEngine::SetTexture(const std::string &name, int stage) +float Gfx::CEngine::TimeGet() { - std::map::iterator it = m_texNameMap.find(name); - if (it != m_texNameMap.end()) - m_device->SetTexture(stage, (*it).second); + /* TODO! + float aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms + float rTime = (aTime - m_lastTime)*m_speed; + m_absTime += rTime; + m_lastTime = aTime; - // TODO if not present... + return rTime;*/ + return 0.0f; } -void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) +bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height) { - m_device->SetMaterial(mat); + // TODO! + return true; } -void Gfx::CEngine::SetState(int state, Gfx::Color color) +bool Gfx::CEngine::ReadSettings() { - if ( state == m_lastState && color == m_lastColor ) - return; + // TODO! + return true; +} - m_lastState = state; - m_lastColor = color; +bool Gfx::CEngine::WriteSettings() +{ + // TODO! + return true; +} - if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) ) - { - state &= ~Gfx::ENG_RSTATE_ALPHA; +void Gfx::CEngine::SetPause(bool pause) +{ + m_pause = pause; +} - if (m_alphaMode == 2) - state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK; - } +bool Gfx::CEngine::GetPause() +{ + return m_pause; +} - // TODO other modes & thorough testing +void Gfx::CEngine::SetMovieLock(bool lock) +{ + m_movieLock = lock; +} - if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +bool Gfx::CEngine::GetMovieLock() +{ + return m_movieLock; +} - m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureFactor(color); +void Gfx::CEngine::SetShowStats(bool show) +{ + m_showStats = show; +} - Gfx::TextureStageParams params; - params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; - params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; - params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; - m_device->SetTextureStageParams(0, params); - } - else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +bool Gfx::CEngine::GetShowStats() +{ + return m_showStats; +} - m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureFactor(color.Inverse()); +void Gfx::CEngine::SetRenderEnable(bool enable) +{ + m_render = enable; +} - Gfx::TextureStageParams params; - params.colorOperation = Gfx::TEX_MIX_OPER_ADD; - params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; - params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; - m_device->SetTextureStageParams(0, params); - } - else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +Math::IntSize Gfx::CEngine::GetWindowSize() +{ + return m_size; +} - m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); +Math::IntSize Gfx::CEngine::GetLastWindowSize() +{ + return m_lastSize; +} - m_device->SetTextureFactor(color); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); - } - else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) +{ + return Math::Point( static_cast(pos.x) / static_cast(m_size.w), + 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); +} - m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); +Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +{ + return Math::IntPoint(static_cast(pos.x * m_size.w), + static_cast((1.0f - pos.y) * m_size.h)); +} - m_device->SetTextureFactor(color.Inverse()); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); - } - else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]); +Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +{ + return Math::Size( static_cast(size.w) / static_cast(m_size.w), + static_cast(size.h) / static_cast(m_size.h) ); +} - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ - } - else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128)); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]); +Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +{ + return Math::IntSize(static_cast(size.w * m_size.w), + static_cast(size.h * m_size.h)); +} - m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color); - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ - } - else if (state & Gfx::ENG_RSTATE_TEXT) - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); +std::string Gfx::CEngine::GetTextureDir() +{ + return m_texPath; +} - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); +void Gfx::CEngine::AddStatisticTriangle(int count) +{ + m_statisticTriangle += count; +} + +int Gfx::CEngine::GetStatisticTriangle() +{ + return m_statisticTriangle; +} + + + +/******************************************************* + Object management + *******************************************************/ + + + +int Gfx::CEngine::CreateObject() +{ + // TODO! + return 0; +} + +void Gfx::CEngine::FlushObject() +{ + // TODO! +} + +bool Gfx::CEngine::DeleteObject(int objRank) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetDrawWorld(int objRank, bool draw) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetDrawFront(int objRank, bool draw) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, + const Gfx::Material& mat, int state, + std::string texName1, std::string texName2, + float min, float max, bool globalUpdate) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, + const Gfx::Material& mat, int state, + std::string texName1, std::string texName2, + float min, float max, bool globalUpdate) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, + std::string texName1, std::string texName2, + float min, float max, bool globalUpdate) +{ + // TODO! + return true; +} + +Gfx::EngineObjLevel5* Gfx::CEngine::SearchTriangle(int objRank, const Gfx::Material& mat, + int state, std::string texName1, + std::string texName2, float min, float max) +{ + // TODO! + return nullptr; +} + +void Gfx::CEngine::ChangeLOD() +{ + // TODO! +} + +bool Gfx::CEngine::ChangeSecondTexture(int objRank, const std::string& texName2) +{ + // TODO! + return true; +} + +int Gfx::CEngine::GetTotalTriangles(int objRank) +{ + // TODO! + return 0; +} + +int Gfx::CEngine::GetTriangles(int objRank, float min, float max, Gfx::EngineTriangle* buffer, int size, float percent) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::GetBBox(int objRank, Math::Vector& min, Math::Vector& max) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::ChangeTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, + float min, float max, Gfx::EngineTextureMapping mode, + float au, float bu, float av, float bv) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::TrackTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, + float min, float max, Gfx::EngineTextureMapping mode, + float pos, float factor, float tl, float ts, float tt) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::GetObjectTransform(int objRank, Math::Matrix& transform) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) +{ + // TODO! + return true; +} + +Gfx::EngineObjectType Gfx::CEngine::GetObjectType(int objRank) +{ + // TODO! + return Gfx::ENG_OBJTYPE_FIX; +} + +bool Gfx::CEngine::SetObjectTransparency(int objRank, float value) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::ShadowCreate(int objRank) +{ + // TODO! + return true; +} + +void Gfx::CEngine::ShadowDelete(int objRank) +{ + // TODO! +} + +bool Gfx::CEngine::SetObjectShadowHide(int objRank, bool hide) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowType(int objRank, Gfx::EngineShadowType type) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowPos(int objRank, const Math::Vector& pos) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowNormal(int objRank, const Math::Vector& n) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowAngle(int objRank, float angle) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowRadius(int objRank, float radius) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowIntensity(int objRank, float intensity) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowHeight(int objRank, float h) +{ + // TODO! + return true; +} + +float Gfx::CEngine::GetObjectShadowRadius(int objRank) +{ + // TODO! + return 0.0f; +} + +bool Gfx::CEngine::GetHighlight(Math::Point &p1, Math::Point &p2) +{ + p1 = m_highlightP1; + p2 = m_highlightP2; + return m_highlight; +} + +void Gfx::CEngine::SetHighlightRank(int *rankList) +{ + int i = 0; + while ( *rankList != -1 ) + { + m_highlightRank[i++] = *rankList++; + } + m_highlightRank[i] = -1; // terminator +} + +bool Gfx::CEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max) +{ + min.x = 1000000.0f; + min.y = 1000000.0f; + max.x = -1000000.0f; + max.y = -1000000.0f; + + for (int i = 0; i < 8; i++) + { + Math::Vector p; + + if ( i & (1<<0) ) p.x = m_objects[objRank].bboxMin.x; + else p.x = m_objects[objRank].bboxMax.x; + if ( i & (1<<1) ) p.y = m_objects[objRank].bboxMin.y; + else p.y = m_objects[objRank].bboxMax.y; + if ( i & (1<<2) ) p.z = m_objects[objRank].bboxMin.z; + else p.z = m_objects[objRank].bboxMax.z; + + Math::Vector pp; + if (TransformPoint(pp, objRank, p)) + { + if (pp.x < min.x) min.x = pp.x; + if (pp.x > max.x) max.x = pp.x; + if (pp.y < min.y) min.y = pp.y; + if (pp.y > max.y) max.y = pp.y; + } + } + + if ( min.x == 1000000.0f || + min.y == 1000000.0f || + max.x == -1000000.0f || + max.y == -1000000.0f ) return false; + + return true; +} + +void Gfx::CEngine::GroundSpotFlush() +{ + // TODO +} + +int Gfx::CEngine::GroundSpotCreate() +{ + // TODO! + return 0; +} + +void Gfx::CEngine::GroundSpotDelete(int rank) +{ + // TODO! +} + +bool Gfx::CEngine::SetObjectGroundSpotPos(int rank, const Math::Vector& pos) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotRadius(int rank, float radius) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotColor(int rank, const Gfx::Color& color) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotMinMax(int rank, float min, float max) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotSmooth(int rank, float smooth) +{ + // TODO! + return true; +} + +int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, + float delay1, float delay2, float delay3, + int dx, int dy, char* table) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::GroundMarkDelete(int rank) +{ + // TODO! + return true; +} + +void Gfx::CEngine::ComputeDistance() +{ + // TODO! +} + +void Gfx::CEngine::UpdateGeometry() +{ + // TODO! +} + +void Gfx::CEngine::Update() +{ + ComputeDistance(); + UpdateGeometry(); +} + +bool Gfx::CEngine::DetectBBox(int objRank, Math::Point mouse) +{ + // TODO! + return true; +} + +int Gfx::CEngine::DetectObject(Math::Point mouse) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::DetectTriangle(Math::Point mouse, Gfx::VertexTex2* triangle, int objRank, float& dist) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::IsVisible(int objRank) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D) +{ + // TODO! + return true; +} + + + +/******************************************************* + Mode setting + *******************************************************/ + + + +void Gfx::CEngine::SetState(int state, const Gfx::Color& color) +{ + if ( state == m_lastState && color == m_lastColor ) + return; + + m_lastState = state; + m_lastColor = color; + + if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) ) + { + state &= ~Gfx::ENG_RSTATE_ALPHA; + + if (m_alphaMode == 2) + state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK; + } + + // TODO other modes & thorough testing + + if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureFactor(color); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + m_device->SetTextureStageParams(0, params); + } + else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureFactor(color.Inverse()); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_ADD; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + m_device->SetTextureStageParams(0, params); + } + else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); + + m_device->SetTextureFactor(color); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + } + else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); + + m_device->SetTextureFactor(color.Inverse()); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + } + else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? + { + /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]); + m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]); + + m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + } + else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? + { + /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); + m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128)); + m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]); + m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]); + + m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color); + m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ + } + else if (state & Gfx::ENG_RSTATE_TEXT) + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + } + else // normal ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + } + + if (state & Gfx::ENG_RSTATE_FOG) + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + + + bool second = m_groundSpotVisible || m_dirty; + + if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false; + if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false; + + if ( (state & ENG_RSTATE_DUAL_BLACK) && second ) + { + /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + } + else if ( (state & ENG_RSTATE_DUAL_WHITE) && second ) + { + /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); + m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + } + else + { + m_device->SetTextureEnabled(1, false); + } + + if (state & Gfx::ENG_RSTATE_WRAP) + { + /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP); + m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/ + } + else if (state & Gfx::ENG_RSTATE_CLAMP) + { + /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); + m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + } + else + { + /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); + m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + } + + if (state & Gfx::ENG_RSTATE_2FACE) + { + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + } + else + { + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); + m_device->SetCullMode(Gfx::CULL_CCW); + } + + if (state & Gfx::ENG_RSTATE_LIGHT) + m_device->SetGlobalAmbient(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); + else + m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); +} + +void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) +{ + m_device->SetMaterial(mat); +} + +void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, + const Math::Vector& upVec, float eyeDistance) +{ + m_eyePt = eyePt; + m_lookatPt = lookatPt; + m_eyeDirH = Math::RotateAngle(eyePt.x - lookatPt.x, eyePt.z - lookatPt.z); + m_eyeDirV = Math::RotateAngle(Math::DistanceProjected(eyePt, lookatPt), eyePt.y - lookatPt.y); + + Math::LoadViewMatrix(m_matView, eyePt, lookatPt, upVec); + + if (m_sound == nullptr) + m_sound = static_cast( m_iMan->SearchInstance(CLASS_SOUND) ); + + m_sound->SetListener(eyePt, lookatPt); +} + +Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) +{ + CImage img; + if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) + { + std::stringstream str; + str << "Couldn't load texture '" << texName << "': " << img.GetError(); + m_error = str.str(); + return Gfx::Texture(); // invalid texture + } + + Gfx::Texture result = m_device->CreateTexture(&img, params); + + if (! result.valid) + { + std::stringstream str; + str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); + m_error = str.str(); + return result; + } + + m_texNameMap[texName] = result; + m_revTexNameMap[result] = texName; + + return result; +} + +Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName) +{ + return CreateTexture(texName, m_defaultTexParams); +} + +void Gfx::CEngine::DestroyTexture(const std::string &texName) +{ + std::map::iterator it = m_texNameMap.find(texName); + if (it == m_texNameMap.end()) + return; + + std::map::iterator revIt = m_revTexNameMap.find((*it).second); + + m_device->DestroyTexture((*it).second); + + m_revTexNameMap.erase(revIt); + m_texNameMap.erase(it); +} + +bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +{ + std::map::iterator it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; + } + + // TODO if not present... + return false; +} + +bool Gfx::CEngine::LoadAllTextures() +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetTexture(const std::string& name, int stage) +{ + // TODO! + return true; +} + +void Gfx::CEngine::SetLimitLOD(int rank, float limit) +{ + m_limitLOD[rank] = limit; +} + +float Gfx::CEngine::GetLimitLOD(int rank, bool last) +{ + float limit = 0.0f; + + if (last) + { + limit = m_limitLOD[rank]; + limit *= m_lastSize.w/640.0f; // limit further if large window! + limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f); + } + else + { + limit = m_limitLOD[rank]; + limit *= m_size.w/640.0f; // limit further if large window! + limit += m_limitLOD[0]*(m_objectDetail*2.0f); + } + + if (limit < 0.0f) limit = 0.0f; + + return limit; +} + +void Gfx::CEngine::SetTerrainVision(float vision) +{ + m_terrainVision = vision; +} + +void Gfx::CEngine::SetFocus(float focus) +{ + m_focus = focus; + m_size = m_app->GetVideoConfig().size; + + float aspect = (static_cast(m_size.h)) / m_size.w; + Math::LoadProjectionMatrix(m_matProj, m_focus, aspect, 0.5f, m_deepView[0]); +} + +float Gfx::CEngine::GetFocus() +{ + return m_focus; +} + +void Gfx::CEngine::SetGroundSpot(bool mode) +{ + m_groundSpotVisible = mode; +} + +bool Gfx::CEngine::GetGroundSpot() +{ + return m_groundSpotVisible; +} + +void Gfx::CEngine::SetShadow(bool mode) +{ + m_shadowVisible = mode; +} + +bool Gfx::CEngine::GetShadow() +{ + return m_shadowVisible; +} + +void Gfx::CEngine::SetDirty(bool mode) +{ + m_dirty = mode; +} + +bool Gfx::CEngine::GetDirty() +{ + return m_dirty; +} + +void Gfx::CEngine::SetFog(bool mode) +{ + m_fog = mode; +} + +bool Gfx::CEngine::GetFog() +{ + return m_fog; +} + +bool Gfx::CEngine::GetStateColor() +{ + return m_stateColor; +} + +void Gfx::CEngine::SetSecondTexture(int texNum) +{ + m_secondTexNum = texNum; +} + +int Gfx::CEngine::GetSecondTexture() +{ + return m_secondTexNum; +} + +void Gfx::CEngine::SetRankView(int rank) +{ + if (rank < 0) rank = 0; + if (rank > 1) rank = 1; + + if (m_rankView == 0 && rank == 1) // enters the water? + m_lightMan->AdaptLightColor(m_waterAddColor, +1.0f); + + if (m_rankView == 1 && rank == 0) // out of the water? + m_lightMan->AdaptLightColor(m_waterAddColor, -1.0f); + + m_rankView = rank; +} + +int Gfx::CEngine::GetRankView() +{ + return m_rankView; +} + +void Gfx::CEngine::SetDrawWorld(bool draw) +{ + m_drawWorld = draw; +} + +void Gfx::CEngine::SetDrawFront(bool draw) +{ + m_drawFront = draw; +} + +void Gfx::CEngine::SetAmbientColor(const Gfx::Color& color, int rank) +{ + m_ambientColor[rank] = color; +} + +Gfx::Color Gfx::CEngine::GetAmbientColor(int rank) +{ + return m_ambientColor[rank]; +} + +void Gfx::CEngine::SetWaterAddColor(const Gfx::Color& color) +{ + m_waterAddColor = color; +} + +Gfx::Color Gfx::CEngine::GetWaterAddColor() +{ + return m_waterAddColor; +} + +void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) +{ + m_fogColor[rank] = color; +} + +Gfx::Color Gfx::CEngine::GetFogColor(int rank) +{ + return m_fogColor[rank]; +} + +void Gfx::CEngine::SetDeepView(float length, int rank, bool ref) +{ + if (ref) + length *= m_clippingDistance; + + m_deepView[rank] = length; +} + +float Gfx::CEngine::GetDeepView(int rank) +{ + return m_deepView[rank]; +} + +void Gfx::CEngine::SetFogStart(float start, int rank) +{ + m_fogStart[rank] = start; +} + +float Gfx::CEngine::GetFogStart(int rank) +{ + return m_fogStart[rank]; +} + + +void Gfx::CEngine::SetBackground(const std::string& name, Gfx::Color up, Gfx::Color down, + Gfx::Color cloudUp, Gfx::Color cloudDown, + bool full, bool quarter) +{ + m_backgroundName = name; + m_backgroundColorUp = up; + m_backgroundColorDown = down; + m_backgroundCloudUp = cloudUp; + m_backgroundCloudDown = cloudDown; + m_backgroundFull = full; + m_backgroundQuarter = quarter; +} + +void Gfx::CEngine::GetBackground(std::string& name, Gfx::Color& up, Gfx::Color& down, + Gfx::Color& cloudUp, Gfx::Color& cloudDown, + bool &full, bool &quarter) +{ + name = m_backgroundName; + up = m_backgroundColorUp; + down = m_backgroundColorDown; + cloudUp = m_backgroundCloudUp; + cloudDown = m_backgroundCloudDown; + full = m_backgroundFull; + quarter = m_backgroundQuarter; +} + +void Gfx::CEngine::SetForegroundImageName(const std::string& name) +{ + if (! m_foregroundImageName.empty()) + DestroyTexture(m_foregroundImageName); + + m_foregroundImageName = name; +} + +void Gfx::CEngine::SetOverFront(bool front) +{ + m_overFront = front; +} + +void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) +{ + m_overColor = color; + m_overMode = mode; +} + +void Gfx::CEngine::SetParticleDensity(float value) +{ + if (value < 0.0f) value = 0.0f; + if (value > 2.0f) value = 2.0f; + m_particleDensity = value; +} + +float Gfx::CEngine::GetParticleDensity() +{ + return m_particleDensity; +} + +float Gfx::CEngine::ParticleAdapt(float factor) +{ + if (m_particleDensity == 0.0f) + return 1000000.0f; + + return factor / m_particleDensity; +} + +void Gfx::CEngine::SetClippingDistance(float value) +{ + if (value < 0.5f) value = 0.5f; + if (value > 2.0f) value = 2.0f; + m_clippingDistance = value; +} + +float Gfx::CEngine::GetClippingDistance() +{ + return m_clippingDistance; +} + +void Gfx::CEngine::SetObjectDetail(float value) +{ + if ( value < 0.0f ) value = 0.0f; + if ( value > 2.0f ) value = 2.0f; + m_objectDetail = value; +} + +float Gfx::CEngine::GetObjectDetail() +{ + return m_objectDetail; +} + +void Gfx::CEngine::SetGadgetQuantity(float value) +{ + if (value < 0.0f) value = 0.0f; + if (value > 1.0f) value = 1.0f; + + m_gadgetQuantity = value; +} + +float Gfx::CEngine::GetGadgetQuantity() +{ + return m_gadgetQuantity; +} + +void Gfx::CEngine::SetTextureQuality(int value) +{ + if (value < 0) value = 0; + if (value > 2) value = 2; + + if (value != m_textureQuality) + { + m_textureQuality = value; + LoadAllTextures(); + } +} + +int Gfx::CEngine::GetTextureQuality() +{ + return m_textureQuality; +} + +void Gfx::CEngine::SetTotoMode(bool present) +{ + m_totoMode = present; +} + +bool Gfx::CEngine::GetTotoMode() +{ + return m_totoMode; +} + +void Gfx::CEngine::SetLensMode(bool present) +{ + m_lensMode = present; +} + +bool Gfx::CEngine::GetLensMode() +{ + return m_lensMode; +} + +void Gfx::CEngine::SetWaterMode(bool present) +{ + m_waterMode = present; +} + +bool Gfx::CEngine::GetWaterMode() +{ + return m_waterMode; +} + +void Gfx::CEngine::SetLightingMode(bool present) +{ + m_lightMode = present; +} + +bool Gfx::CEngine::GetLightingMode() +{ + return m_lightMode; +} + +void Gfx::CEngine::SetSkyMode(bool present) +{ + m_skyMode = present; +} + +bool Gfx::CEngine::GetSkyMode() +{ + return m_skyMode; +} + +void Gfx::CEngine::SetBackForce(bool present) +{ + m_backForce = present; +} + +bool Gfx::CEngine::GetBackForce() +{ + return m_backForce; +} + +void Gfx::CEngine::SetPlanetMode(bool present) +{ + m_planetMode = present; +} + +bool Gfx::CEngine::GetPlanetMode() +{ + return m_planetMode; +} + +void Gfx::CEngine::SetLightMode(bool present) +{ + m_lightMode = present; +} + +bool Gfx::CEngine::GetLightMode() +{ + return m_lightMode; +} + +void Gfx::CEngine::SetEditIndentMode(bool autoIndent) +{ + m_editIndentMode = autoIndent; +} + +bool Gfx::CEngine::GetEditIndentMode() +{ + return m_editIndentMode; +} + +void Gfx::CEngine::SetEditIndentValue(int value) +{ + m_editIndentValue = value; +} + +int Gfx::CEngine::GetEditIndentValue() +{ + return m_editIndentValue; +} + +void Gfx::CEngine::SetSpeed(float speed) +{ + m_speed = speed; +} + +float Gfx::CEngine::GetSpeed() +{ + return m_speed; +} + +void Gfx::CEngine::SetTracePrecision(float factor) +{ + m_tracePrecision = factor; +} + +float Gfx::CEngine::GetTracePrecision() +{ + return m_tracePrecision; +} + +void Gfx::CEngine::SetMouseVisible(bool visible) +{ + m_mouseVisible = visible; +} + +bool Gfx::CEngine::GetMouseVisible() +{ + return m_mouseVisible; +} + +void Gfx::CEngine::SetMousePos(Math::Point pos) +{ + m_mousePos = pos; +} + +Math::Point Gfx::CEngine::GetMousePos() +{ + return m_mousePos; +} + +void Gfx::CEngine::SetMouseType(Gfx::EngineMouseType type) +{ + m_mouseType = type; +} + +Gfx::EngineMouseType Gfx::CEngine::GetMouseType() +{ + return m_mouseType; +} + +const Math::Matrix& Gfx::CEngine::GetMatView() +{ + return m_matView; +} + +Math::Vector Gfx::CEngine::GetEyePt() +{ + return m_eyePt; +} + +Math::Vector Gfx::CEngine::GetLookatPt() +{ + return m_lookatPt; +} - m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); +float Gfx::CEngine::GetEyeDirH() +{ + return m_eyeDirH; +} + +float Gfx::CEngine::GetEyeDirV() +{ + return m_eyeDirV; +} + +bool Gfx::CEngine::IsVisiblePoint(const Math::Vector &pos) +{ + return Math::Distance(m_eyePt, pos) <= m_deepView[0]; +} + +void Gfx::CEngine::UpdateMatProj() +{ + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); +} + +void Gfx::CEngine::ApplyChange() +{ + m_deepView[0] /= m_lastClippingDistance; + m_deepView[1] /= m_lastClippingDistance; + + SetFocus(m_focus); + ChangeLOD(); + + m_deepView[0] *= m_clippingDistance; + m_deepView[1] *= m_clippingDistance; +} + + + +/******************************************************* + Rendering + *******************************************************/ + + + +/** + This function sets up render states, clears the + viewport, and renders the scene. */ +void Gfx::CEngine::Render() +{ + /* TODO! + D3DObjLevel1* p1; + D3DObjLevel2* p2; + D3DObjLevel3* p3; + D3DObjLevel4* p4; + D3DObjLevel5* p5; + D3DVERTEX2* pv; + int l1, l2, l3, l4, l5, objRank;*/ + + if (! m_render) return; + + m_statisticTriangle = 0; + m_lastState = -1; + m_lastColor = 999; + m_lastMaterial = Gfx::Material(); + + m_lightMan->UpdateLights(); + + Gfx::Color color; + if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds? + color = m_backgroundCloudDown; + else + color = m_backgroundColorDown; + + m_device->SetClearColor(color); + + // Begin the scene + m_device->BeginScene(); + + + if (m_drawWorld) + { + Draw3DScene(); } - else // normal ? + + + DrawInterface(); + + // End the scene + m_device->EndScene(); +} + +void Gfx::CEngine::Draw3DScene() +{ + if (m_groundSpotVisible) + UpdateGroundSpotTextures(); + + DrawBackground(); // draws the background + if (m_planetMode) DrawPlanet(); // draws the planets + if (m_skyMode) m_cloud->Draw(); // draws the clouds + + + // Display the objects + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + + float fogStart = m_deepView[m_rankView]*m_fogStart[m_rankView]; + float fogEnd = m_deepView[m_rankView]; + m_device->SetFogParams(Gfx::FOG_LINEAR, m_fogColor[m_rankView], fogStart, fogEnd, 1.0f); + + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matView); + + if (m_waterMode) m_water->DrawBack(); // draws water background + + if (m_shadowVisible) { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + // Draw the field + // TODO! + /* + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( m_objectParam[objRank].type != TYPETERRAIN ) continue; + if ( !m_objectParam[objRank].bDrawWorld ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + SetState(p6->state); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + }*/ + + // Draws the shadows + DrawShadow(); + } - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + // Draw objects + bool transparent = false; + /* TODO! + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue; + if ( !m_objectParam[objRank].bDrawWorld ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + if ( m_objectParam[objRank].transparency != 0.0f ) // transparent ? + { + transparent = true; + continue; + } + SetState(p6->state); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + }*/ - /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + if (transparent) + { + int tState = 0; + Gfx::Color tColor; + if (m_stateColor) + { + tState = Gfx::ENG_RSTATE_TTEXTURE_BLACK | Gfx::ENG_RSTATE_2FACE; + tColor = Gfx::Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f); + } + else + { + tState = Gfx::ENG_RSTATE_TCOLOR_BLACK; + tColor = Gfx::Color(136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f); + } + + // Draw transparent objects. + /* TODO! + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue; + if ( !m_objectParam[objRank].bDrawWorld ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + if ( m_objectParam[objRank].transparency == 0.0f ) continue; + SetState(tState, tColor); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + } */ } - if (state & Gfx::ENG_RSTATE_FOG) + m_lightMan->UpdateLightsEnableState(Gfx::ENG_OBJTYPE_TERRAIN); + + if (m_waterMode) m_water->DrawSurf(); // draws water surface + + m_particle->DrawParticle(Gfx::SH_WORLD); // draws the particles of the 3D world + m_lightning->Draw(); // draws lightning + if (m_lensMode) DrawForegroundImage(); // draws the foreground + if (! m_overFront) DrawOverColor(); // draws the foreground color +} + +void Gfx::CEngine::DrawInterface() +{ + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + // Draw the entire interface + CInterface* interface = static_cast( m_iMan->SearchInstance(CLASS_INTERFACE) ); + if (interface != nullptr) + interface->Draw(); + + m_particle->DrawParticle(Gfx::SH_INTERFACE); // draws the particles of the interface + + // 3D objects drawn in front of interface + if (m_drawFront) + { + // Display the objects + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); + + m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + float fogStart = m_deepView[m_rankView]*m_fogStart[m_rankView]; + float fogEnd = m_deepView[m_rankView]; + m_device->SetFogParams(Gfx::FOG_LINEAR, m_fogColor[m_rankView], fogStart, fogEnd, 1.0f); - bool second = m_groundSpotVisible || m_dirty; + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matView); - if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false; - if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false; + // TODO! + /* + for (int l1 = 0; l1 < m_objectTree.size(); l1++) + { + Gfx::EngineObjLevel1* p1 = &m_objectTree[l1]; + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( !m_objectParam[objRank].bDrawFront ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + SetState(p6->state); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + }*/ + + m_particle->DrawParticle(Gfx::SH_FRONT); // draws the particles of the 3D world + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - if ( (state & ENG_RSTATE_DUAL_BLACK) && second ) + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + } + + // Draw foreground color + if (m_overFront) + DrawOverColor(); + + // Mouse & highlight at the end + DrawMouse(); + DrawHighlight(); +} + +void Gfx::CEngine::UpdateGroundSpotTextures() +{ + // TODO! +} + +void Gfx::CEngine::DrawShadow() +{ + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + + Math::Matrix matrix; + matrix.LoadIdentity(); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, matrix); + + + Gfx::Material material; + material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); + material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f); + SetMaterial(material); + + // TODO: wtf? + SetTexture("text.png"); + + Math::Point ts, ti; + + float dp = 0.5f/256.0f; + ts.y = 192.0f/256.0f; + ti.y = 224.0f/256.0f; + ts.y += dp; + ti.y -= dp; + + Math::Vector n(0.0f, 1.0f, 0.0f); + + float startDeepView = m_deepView[m_rankView]*m_fogStart[m_rankView]; + float endDeepView = m_deepView[m_rankView]; + + float lastIntensity = -1.0f; + for (int i = 0; i < static_cast( m_shadow.size() ); i++) { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + if (m_shadow[i].hide) continue; + + Math::Vector pos = m_shadow[i].pos; // pos = center of the shadow on the ground + + if (m_eyePt.y == pos.y) continue; // camera at the same level? + + float d = 0.0f; + float D = 0.0f; + + // h is the height above the ground to which the shadow + // will be drawn. + if (m_eyePt.y > pos.y) // camera on? + { + float height = m_eyePt.y-pos.y; + float h = m_shadow[i].radius; + float max = height*0.5f; + if ( h > max ) h = max; + if ( h > 4.0f ) h = 4.0f; + + D = Math::Distance(m_eyePt, pos); + if ( D >= endDeepView ) continue; + d = D*h/height; + + pos.x += (m_eyePt.x-pos.x)*d/D; + pos.z += (m_eyePt.z-pos.z)*d/D; + pos.y += h; + } + else // camera underneath? + { + float height = pos.y-m_eyePt.y; + float h = m_shadow[i].radius; + float max = height*0.1f; + if ( h > max ) h = max; + if ( h > 4.0f ) h = 4.0f; + + D = Math::Distance(m_eyePt, pos); + if ( D >= endDeepView ) continue; + d = D*h/height; + + pos.x += (m_eyePt.x-pos.x)*d/D; + pos.z += (m_eyePt.z-pos.z)*d/D; + pos.y -= h; + } + + // The hFactor decreases the intensity and size increases more + // the object is high relative to the ground. + float hFactor = m_shadow[i].height/20.0f; + if ( hFactor < 0.0f ) hFactor = 0.0f; + if ( hFactor > 1.0f ) hFactor = 1.0f; + hFactor = powf(1.0f-hFactor, 2.0f); + if ( hFactor < 0.2f ) hFactor = 0.2f; + + float radius = m_shadow[i].radius*1.5f; + radius *= 2.0f-hFactor; // greater if high + radius *= 1.0f-d/D; // smaller if close + + + Math::Vector corner[4]; + + if (m_shadow[i].type == Gfx::ENG_SHADOW_NORM) + { + corner[0].x = +radius; + corner[0].z = +radius; + corner[0].y = 0.0f; + + corner[1].x = -radius; + corner[1].z = +radius; + corner[1].y = 0.0f; + + corner[2].x = +radius; + corner[2].z = -radius; + corner[2].y = 0.0f; + + corner[3].x = -radius; + corner[3].z = -radius; + corner[3].y = 0.0f; + + ts.x = 64.0f/256.0f; + ti.x = 96.0f/256.0f; + } + else + { + Math::Point rot; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius)); + corner[0].x = rot.x; + corner[0].z = rot.y; + corner[0].y = 0.0f; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius)); + corner[1].x = rot.x; + corner[1].z = rot.y; + corner[1].y = 0.0f; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius)); + corner[2].x = rot.x; + corner[2].z = rot.y; + corner[2].y = 0.0f; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius)); + corner[3].x = rot.x; + corner[3].z = rot.y; + corner[3].y = 0.0f; + + if (m_shadow[i].type == Gfx::ENG_SHADOW_WORM) + { + ts.x = 96.0f/256.0f; + ti.x = 128.0f/256.0f; + } + else + { + ts.x = 64.0f/256.0f; + ti.x = 96.0f/256.0f; + } + } + + corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal); + corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal); + corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal); + corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal); + + corner[0] += pos; + corner[1] += pos; + corner[2] += pos; + corner[3] += pos; + + ts.x += dp; + ti.x -= dp; + + Gfx::Vertex vertex[4] = + { + Gfx::Vertex(corner[1], n, Math::Point(ts.x, ts.y)), + Gfx::Vertex(corner[0], n, Math::Point(ti.x, ts.y)), + Gfx::Vertex(corner[3], n, Math::Point(ts.x, ti.y)), + Gfx::Vertex(corner[2], n, Math::Point(ti.x, ti.y)) + }; + + float intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor; + + // Decreases the intensity of the shade if you're in the area + // between the beginning and the end of the fog. + if ( D > startDeepView ) + intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView); + + if (intensity == 0.0f) continue; + + if (lastIntensity != intensity) // intensity changed? + { + lastIntensity = intensity; + SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::Color(intensity, intensity, intensity, intensity)); + } + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } - else if ( (state & ENG_RSTATE_DUAL_WHITE) && second ) + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); +} + +void Gfx::CEngine::DrawBackground() +{ + if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ? { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + if (m_backgroundCloudUp != m_backgroundCloudDown) // degraded? + DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown); } else { - m_device->SetTextureEnabled(1, false); + if (m_backgroundColorUp != m_backgroundColorDown) // degraded? + DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown); } - if (state & Gfx::ENG_RSTATE_WRAP) + if (m_backForce || (m_skyMode && m_backgroundName[0] != 0) ) { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/ + DrawBackgroundImage(); // image } - else if (state & Gfx::ENG_RSTATE_CLAMP) +} + +void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down) +{ + Math::Point p1(0.0f, 0.5f); + Math::Point p2(1.0f, 1.0f); + + Gfx::Color color[3] = { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ - } - else + up, + down, + Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) + }; + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + + SetState(Gfx::ENG_RSTATE_NORMAL); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + Gfx::VertexCol vertex[4] = { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ - } + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0], color[2]) + }; - if (state & Gfx::ENG_RSTATE_2FACE) + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); +} + +void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name) +{ + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal + + float u1, u2, v1, v2; + if (m_backgroundFull) { - m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + u1 = 0.0f; + v1 = 0.0f; + u2 = 1.0f; + v2 = 1.0f; + + if (m_backgroundQuarter) + { + u1 += 0.5f/512.0f; + v1 += 0.5f/384.0f; + u2 -= 0.5f/512.0f; + v2 -= 0.5f/384.0f; + } } else { - m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); - m_device->SetCullMode(Gfx::CULL_CCW); + float h = 0.5f; // visible area vertically (1=all) + float a = m_eyeDirV-Math::PI*0.15f; + if (a > Math::PI ) a -= Math::PI*2.0f; // a = -Math::PI..Math::PI + if (a > Math::PI/4.0f) a = Math::PI/4.0f; + if (a < -Math::PI/4.0f) a = -Math::PI/4.0f; + + u1 = -m_eyeDirH/Math::PI; + u2 = u1+1.0f/Math::PI; + + v1 = (1.0f-h)*(0.5f+a/(2.0f*Math::PI/4.0f))+0.1f; + v2 = v1+h; } - if (state & Gfx::ENG_RSTATE_LIGHT) - m_device->SetGlobalAmbient(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); - else - m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + + SetTexture(name); + SetState(Gfx::ENG_RSTATE_WRAP); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + Gfx::Vertex vertex[4] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -bool Gfx::CEngine::ProcessEvent(const Event &event) +void QuarterName(std::string& buffer, const std::string& name, int quarter) { - if (event.type == EVENT_MOUSE_MOVE) + size_t pos = name.find('.'); + if (pos == std::string::npos) { - m_mousePos = event.mouseMove.pos; + buffer = name; + return; } - else if (event.type == EVENT_KEY_DOWN) - { - // !! Debug, to be removed later !! - if (event.key.key == KEY(F1)) - { - m_mouseVisible = !m_mouseVisible; - m_app->SetSystemMouseVisible(! m_app->GetSystemMouseVisibile()); - } - else if (event.key.key == KEY(F2)) - { - int index = static_cast(m_mouseType); - m_mouseType = static_cast( (index + 1) % Gfx::ENG_MOUSE_COUNT ); - } + buffer = name.substr(0, pos) + std::string(1, static_cast('a' + quarter)) + name.substr(pos); +} + +void Gfx::CEngine::DrawBackgroundImage() +{ + Math::Point p1, p2; + std::string name; + + if (m_backgroundQuarter) + { + p1.x = 0.0f; + p1.y = 0.5f; + p2.x = 0.5f; + p2.y = 1.0f; + QuarterName(name, m_backgroundName, 0); + DrawBackgroundImageQuarter(p1, p2, name); + + p1.x = 0.5f; + p1.y = 0.5f; + p2.x = 1.0f; + p2.y = 1.0f; + QuarterName(name, m_backgroundName, 1); + DrawBackgroundImageQuarter(p1, p2, name); + + p1.x = 0.0f; + p1.y = 0.0f; + p2.x = 0.5f; + p2.y = 0.5f; + QuarterName(name, m_backgroundName, 2); + DrawBackgroundImageQuarter(p1, p2, name); + + p1.x = 0.5f; + p1.y = 0.0f; + p2.x = 1.0f; + p2.y = 0.5f; + QuarterName(name, m_backgroundName, 3); + DrawBackgroundImageQuarter(p1, p2, name); + } + else + { + p1.x = 0.0f; + p1.y = 0.0f; + p2.x = 1.0f; + p2.y = 1.0f; + DrawBackgroundImageQuarter(p1, p2, m_backgroundName); } - - // By default, pass on all events - return true; } -bool Gfx::CEngine::Render() +void Gfx::CEngine::DrawPlanet() { - m_statisticTriangle = 0; + if (! m_planet->PlanetExist()) return; - m_lastState = -1; - SetState(Gfx::ENG_RSTATE_NORMAL); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->BeginScene(); + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); - SetUp3DView(); + m_planet->Draw(); // draws the planets +} - if (! Draw3DScene() ) - return false; +void Gfx::CEngine::DrawForegroundImage() +{ + if (m_foregroundImageName.empty()) return; - SetUpInterfaceView(); + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal - if (! DrawInterface() ) - return false; + Math::Point p1(0.0f, 0.0f); + Math::Point p2(1.0f, 1.0f); - m_device->EndScene(); + float u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f; + float u2 = u1+0.50f; - return true; -} + float v1 = 0.2f; + float v2 = 1.0f; -void Gfx::CEngine::SetUp3DView() -{ - // TODO -} -bool Gfx::CEngine::Draw3DScene() -{ - // TODO - return true; -} + Gfx::Vertex vertex[4] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) + }; -void Gfx::CEngine::SetUpInterfaceView() -{ - m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); - m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false ); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + + SetTexture(m_foregroundImageName); + SetState(Gfx::ENG_RSTATE_CLAMP | Gfx::ENG_RSTATE_TTEXTURE_BLACK); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -bool Gfx::CEngine::DrawInterface() +void Gfx::CEngine::DrawOverColor() { - Gfx::VertexCol vertices[3] = - { - Gfx::VertexCol(Math::Vector( 0.25f, 0.25f, 0.0f), Gfx::Color(1.0f, 0.0f, 0.0f)), - Gfx::VertexCol(Math::Vector( 0.75f, 0.25f, 0.0f), Gfx::Color(0.0f, 1.0f, 0.0f)), - Gfx::VertexCol(Math::Vector( 0.5f, 0.75f, 0.0f), Gfx::Color(0.0f, 0.0f, 1.0f)) - }; + if (! m_stateColor) return; - m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, vertices, 3); + // TODO: fuzzy compare? + if ( (m_overColor == Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) && m_overMode == Gfx::ENG_RSTATE_TCOLOR_BLACK) || + (m_overColor == Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f) && m_overMode == Gfx::ENG_RSTATE_TCOLOR_WHITE) ) return; - DrawMouse(); - - std::vector format; - for (int i = 0; i < 10; ++i) - format.push_back(Gfx::FONT_COLOBOT_BOLD | Gfx::FONT_HIGHLIGHT_CONST); - for (int i = 0; i < 10; ++i) - format.push_back(Gfx::FONT_COLOBOT_ITALIC | Gfx::FONT_HIGHLIGHT_KEY); - for (int i = 0; i < 10; ++i) - format.push_back(Gfx::FONT_COURIER | Gfx::FONT_HIGHLIGHT_LINK); - for (int i = 0; i < 5; ++i) - format.push_back(Gfx::FONT_COURIER_BOLD | Gfx::FONT_HIGHLIGHT_REM); + Math::Point p1(0.0f, 0.0f); + Math::Point p2(1.0f, 1.0f); - m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); - float h = m_text->GetHeight(Gfx::FONT_COLOBOT, 15.0f); - m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", format, 13.0f, Math::Point(0.25f, 0.2f - h), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); + Gfx::Color color[3] = + { + m_overColor, + m_overColor, + Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) + }; - return true; -} + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); -Math::IntSize Gfx::CEngine::GetWindowSize() -{ - return m_size; -} + SetState(m_overMode); -Math::IntSize Gfx::CEngine::GetLastWindowSize() -{ - return m_lastSize; -} + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); -/** Conversion of the position of the mouse from window coords to interface coords: - - x: 0=left, 1=right - - y: 0=down, 1=up */ -Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) -{ - return Math::Point( static_cast(pos.x) / static_cast(m_size.w), - 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); -} + Gfx::VertexCol vertex[4] = + { + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1],color[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0],color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1],color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0],color[2]) + }; -Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) -{ - return Math::IntPoint(static_cast(pos.x * m_size.w), - static_cast((1.0f - pos.y) * m_size.h)); + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +void Gfx::CEngine::DrawHighlight() { - return Math::Size( static_cast(size.w) / static_cast(m_size.w), - static_cast(size.h) / static_cast(m_size.h) ); -} + Math::Point min, max; + min.x = 1000000.0f; + min.y = 1000000.0f; + max.x = -1000000.0f; + max.y = -1000000.0f; + + int i = 0; + while (m_highlightRank[i] != -1) + { + Math::Point omin, omax; + if (GetBBox2D(m_highlightRank[i++], omin, omax)) + { + min.x = Math::Min(min.x, omin.x); + min.y = Math::Min(min.y, omin.y); + max.x = Math::Max(max.x, omax.x); + max.y = Math::Max(max.y, omax.y); + } + } -Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) -{ - return Math::IntSize(static_cast(size.w * m_size.w), - static_cast(size.h * m_size.h)); -} + if ( min.x == 1000000.0f || + min.y == 1000000.0f || + max.x == -1000000.0f || + max.y == -1000000.0f ) + { + m_highlight = false; // not highlighted + } + else + { + m_highlightP1 = min; + m_highlightP2 = max; + m_highlight = true; + } -std::string Gfx::CEngine::GetTextureDir() -{ - return m_texPath; + // TODO: draw highlight! } void Gfx::CEngine::DrawMouse() @@ -752,179 +2684,3 @@ void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); AddStatisticTriangle(2); } - -bool Gfx::CEngine::GetPause() -{ - return m_pause; -} - -Math::Vector Gfx::CEngine::GetLookatPt() -{ - return m_lookatPt; -} - -Math::Vector Gfx::CEngine::GetEyePt() -{ - return m_eyePt; -} - -void Gfx::CEngine::SetMouseVisible(bool visible) -{ - m_mouseVisible = visible; -} - -bool Gfx::CEngine::GetMouseVisible() -{ - return m_mouseVisible; -} - -void Gfx::CEngine::SetMousePos(Math::Point pos) -{ - m_mousePos = pos; -} - -Math::Point Gfx::CEngine::GetMousePos() -{ - return m_mousePos; -} - -void Gfx::CEngine::SetMouseType(Gfx::EngineMouseType type) -{ - m_mouseType = type; -} - -Gfx::EngineMouseType Gfx::CEngine::GetMouseType() -{ - return m_mouseType; -} - -void Gfx::CEngine::AddStatisticTriangle(int count) -{ - m_statisticTriangle += count; -} - -void Gfx::CEngine::SetShowStat(bool show) -{ - m_showStats = show; -} - -bool Gfx::CEngine::GetShowStat() -{ - return m_showStats; -} - -void Gfx::CEngine::SetFocus(float focus) -{ - m_focus = focus; -} - - -void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) -{ - // TODO! -} - -void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) -{ - // TODO! -} - -Gfx::Color Gfx::CEngine::GetFogColor(int rank) -{ - // TODO! - return Gfx::Color(); -} - -void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, - const Math::Vector& upVec, float eyeDistance) -{ - // TODO! -} - -void Gfx::CEngine::SetRankView(int rank) -{ - m_rankView = rank; -} - -float Gfx::CEngine::GetEyeDirH() -{ - return m_eyeDirH; -} - -float Gfx::CEngine::GetEyeDirV() -{ - return m_eyeDirV; -} - -float Gfx::CEngine::GetClippingDistance() -{ - return m_clippingDistance; -} - -bool Gfx::CEngine::GetGroundSpot() -{ - return m_groundSpotVisible; -} - -void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) -{ - m_terrain = terrain; -} - -void Gfx::CEngine::SetTerrainVision(float vision) -{ - // TODO! -} - -bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) -{ - // TODO! - return true; -} - -float Gfx::CEngine::ParticleAdapt(float factor) -{ - // TODO! - return 0.0f; -} - -bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) -{ - // TODO! - return true; -} - -bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) -{ - // TODO! - return true; -} - -int Gfx::CEngine::CreateObject() -{ - // TODO! - return 0; -} - -bool Gfx::CEngine::DeleteObject(int objRank) -{ - // TODO! - return true; -} - -int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table) -{ - // TODO! - return 0; -} - -bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate) -{ - // TODO! - return false; -} - -void Gfx::CEngine::Update() -{ - // TODO! -} diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index e61aca6..d01a679 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1,5 +1,5 @@ // * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2001-2008, Daniel ROUX& EPSITEC SA, www.epsitec.ch // * Copyright (C) 2012, Polish Portal of Colobot (PPC) // * // * This program is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ class CApplication; class CInstanceManager; class CObject; -class CSound; +class CSoundInterface; namespace Gfx { @@ -310,12 +310,14 @@ struct EngineGroundSpot \brief Phase of life of an EngineGroundMark */ enum EngineGroundMarkPhase { + //! Null phase + ENG_GR_MARK_PHASE_NULL = 0, //! Increase ENG_GR_MARK_PHASE_INC = 1, //! Fixed ENG_GR_MARK_PHASE_FIX = 2, //! Decrease - ENG_GR_MARK_PHASE_DEC = 2 + ENG_GR_MARK_PHASE_DEC = 3 }; /** @@ -526,17 +528,24 @@ struct EngineMouse class CEngine { public: - CEngine(CInstanceManager *iMan, CApplication *app); + CEngine(CInstanceManager* iMan, CApplication* app); ~CEngine(); //! Returns the last error encountered std::string GetError(); //! Sets the device to be used - void SetDevice(Gfx::CDevice *device); + void SetDevice(Gfx::CDevice* device); //! Returns the current device Gfx::CDevice* GetDevice(); + //! Sets the terrain object + void SetTerrain(Gfx::CTerrain* terrain); + + //! Returns the text rendering engine + CText* GetText(); + + //! Performs the initialization; must be called after device was set bool Create(); //! Frees all resources before exit @@ -545,102 +554,122 @@ public: //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) void ResetAfterDeviceChanged(); - void SetTerrain(Gfx::CTerrain* terrain); + + //! Called once per frame, the call is the entry point for rendering + void Render(); + //! Processes incoming event - bool ProcessEvent(const Event &event); + bool ProcessEvent(const Event& event); - //! Renders a single frame - bool Render(); + //! Called once per frame, the call is the entry point for animating the scene + void FrameMove(float rTime); + //! Evolved throughout the game + void StepSimulation(float rTime); + //! Initialize timestamps at the beginning of animation + void TimeInit(); + //! Suspend animation + void TimeEnterGel(); + //! Resume animation + void TimeExitGel(); + //! Returns the relative time since last animation update + float TimeGet(); - //! Converts window coords to interface coords - Math::Point WindowToInterfaceCoords(Math::IntPoint pos); - //! Converts interface coords to window coords - Math::IntPoint InterfaceToWindowCoords(Math::Point pos); - //! Converts window size to interface size - Math::Size WindowToInterfaceSize(Math::IntSize size); - //! Converts interface size to window size - Math::IntSize InterfaceToWindowSize(Math::Size size); + //! Writes a screenshot containing the current frame + bool WriteScreenShot(const std::string& fileName, int width, int height); - std::string GetTextureDir(); - bool WriteProfile(); + //! Reads settings from INI + bool ReadSettings(); + //! Writes settings to INI + bool WriteSettings(); + //@{ + //! Management of game pause mode void SetPause(bool pause); bool GetPause(); + //@} + //@{ + //! Management of lock for the duration of movie sequence void SetMovieLock(bool lock); bool GetMovieLock(); + //@} - void SetShowStat(bool show); - bool GetShowStat(); + //@{ + //! Management of displaying statistic information + void SetShowStats(bool show); + bool GetShowStats(); + //@} + //! Enables/disables rendering void SetRenderEnable(bool enable); - int OneTimeSceneInit(); - int InitDeviceObjects(); - int DeleteDeviceObjects(); - int RestoreSurfaces(); - int FrameMove(float rTime); - void StepSimulation(float rTime); - int FinalCleanup(); + //! Returns current size of viewport window + Math::IntSize GetWindowSize(); + //! Returns the last size of viewport window + Math::IntSize GetLastWindowSize(); + + //! Converts window coords to interface coords + /** Conversion of the position of the mouse from window coords to interface coords: + - x: 0=left, 1=right + - y: 0=down, 1=up */ + Math::Point WindowToInterfaceCoords(Math::IntPoint pos); + //! Converts interface coords to window coords + Math::IntPoint InterfaceToWindowCoords(Math::Point pos); + + //! Converts window size to interface size + Math::Size WindowToInterfaceSize(Math::IntSize size); + //! Converts interface size to window size + Math::IntSize InterfaceToWindowSize(Math::Size size); + + //! Returns the name of directory with textures + std::string GetTextureDir(); + + //! Increments the triangle counter for the current frame void AddStatisticTriangle(int nb); + //! Returns the number of triangles in current frame int GetStatisticTriangle(); - void SetHiliteRank(int *rankList); - bool GetHilite(Math::Point &p1, Math::Point &p2); - bool GetSpriteCoord(int &x, int &y); - void SetInfoText(int line, char* text); - char* GetInfoText(int line); - void FirstExecuteAdapt(bool first); - bool GetFullScreen(); - Math::Matrix* GetMatView(); - Math::Matrix* GetMatLeftView(); - Math::Matrix* GetMatRightView(); + /* *************** Object management *************** */ - void TimeInit(); - void TimeEnterGel(); - void TimeExitGel(); - float TimeGet(); - - int GetRestCreate(); int CreateObject(); void FlushObject(); bool DeleteObject(int objRank); bool SetDrawWorld(int objRank, bool draw); bool SetDrawFront(int objRank, bool draw); - bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, + bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material& mat, int state, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); - bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, + bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material& mat, int state, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); bool AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); - Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material &mat, + Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material& mat, int state, std::string texName1, std::string texName2, float min, float max); void ChangeLOD(); - bool ChangeSecondTexture(int objRank, char* texName2); + bool ChangeSecondTexture(int objRank, const std::string& texName2); int GetTotalTriangles(int objRank); int GetTriangles(int objRank, float min, float max, Gfx::EngineTriangle* buffer, int size, float percent); - bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max); - bool ChangeTextureMapping(int objRank, const Gfx::Material &mat, int state, - const std::string &texName1, const std::string &texName2, + bool GetBBox(int objRank, Math::Vector& min, Math::Vector& max); + bool ChangeTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, float min, float max, Gfx::EngineTextureMapping mode, float au, float bu, float av, float bv); - bool TrackTextureMapping(int objRank, const Gfx::Material &mat, int state, - const std::string &texName1, const std::string &texName2, + bool TrackTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, float min, float max, Gfx::EngineTextureMapping mode, float pos, float factor, float tl, float ts, float tt); - bool SetObjectTransform(int objRank, const Math::Matrix &transform); - bool GetObjectTransform(int objRank, Math::Matrix &transform); + bool SetObjectTransform(int objRank, const Math::Matrix& transform); + bool GetObjectTransform(int objRank, Math::Matrix& transform); bool SetObjectType(int objRank, Gfx::EngineObjectType type); Gfx::EngineObjectType GetObjectType(int objRank); bool SetObjectTransparency(int objRank, float value); @@ -649,20 +678,25 @@ public: void ShadowDelete(int objRank); bool SetObjectShadowHide(int objRank, bool hide); bool SetObjectShadowType(int objRank, Gfx::EngineShadowType type); - bool SetObjectShadowPos(int objRank, const Math::Vector &pos); - bool SetObjectShadowNormal(int objRank, const Math::Vector &n); + bool SetObjectShadowPos(int objRank, const Math::Vector& pos); + bool SetObjectShadowNormal(int objRank, const Math::Vector& n); bool SetObjectShadowAngle(int objRank, float angle); bool SetObjectShadowRadius(int objRank, float radius); bool SetObjectShadowIntensity(int objRank, float intensity); bool SetObjectShadowHeight(int objRank, float h); float GetObjectShadowRadius(int objRank); + //! Lists the ranks of objects and subobjects selected + void SetHighlightRank(int* rankList); + //! Returns the highlighted rectangle + bool GetHighlight(Math::Point& p1, Math::Point& p2); + void GroundSpotFlush(); int GroundSpotCreate(); void GroundSpotDelete(int rank); - bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos); + bool SetObjectGroundSpotPos(int rank, const Math::Vector& pos); bool SetObjectGroundSpotRadius(int rank, float radius); - bool SetObjectGroundSpotColor(int rank, const Gfx::Color &color); + bool SetObjectGroundSpotColor(int rank, const Gfx::Color& color); bool SetObjectGroundSpotMinMax(int rank, float min, float max); bool SetObjectGroundSpotSmooth(int rank, float smooth); @@ -671,217 +705,347 @@ public: int dx, int dy, char* table); bool GroundMarkDelete(int rank); + //! Updates the state after creating objects void Update(); - void SetViewParams(const Math::Vector &eyePt, const Math::Vector &lookatPt, - const Math::Vector &upVec, float eyeDistance); - Gfx::Texture CreateTexture(const std::string &texName, - const Gfx::TextureCreateParams ¶ms); - Gfx::Texture CreateTexture(const std::string &texName); - void DestroyTexture(const std::string &texName); + /* *************** Mode setting *************** */ + + //! Sets the current rendering state + void SetState(int state, const Gfx::Color& color = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); + + //! Sets the current material + void SetMaterial(const Gfx::Material& mat); + + //! Specifies the location and direction of view + void SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, + const Math::Vector& upVec, float eyeDistance); - bool LoadTexture(const std::string &name, int stage = 0); + Gfx::Texture CreateTexture(const std::string& texName, + const Gfx::TextureCreateParams& params); + Gfx::Texture CreateTexture(const std::string& texName); + void DestroyTexture(const std::string& texName); + bool LoadTexture(const std::string& name, int stage = 0); bool LoadAllTextures(); + bool SetTexture(const std::string& name, int stage = 0); + //@{ + //! Border management (distance limits) depends of the resolution (LOD = level-of-detail) void SetLimitLOD(int rank, float limit); float GetLimitLOD(int rank, bool last=false); + //@} + //! Defines of the distance field of vision void SetTerrainVision(float vision); + //@{ + //! Management of camera angle + /** + 0.75 = normal + 1.50 = wide-angle */ + void SetFocus(float focus); + float GetFocus(); + //@} + + //@{ + //! Management of the global mode of marking void SetGroundSpot(bool mode); bool GetGroundSpot(); + //@} + + //@{ + //! Management of the global mode of shading void SetShadow(bool mode); bool GetShadow(); + //@} + + //@{ + //! Management of the global mode of contamination void SetDirty(bool mode); bool GetDirty(); + //@} + + //@{ + //! Management of the global mode of horizontal fog patches void SetFog(bool mode); bool GetFog(); + //@} + + //! Indicates whether it is possible to give a color SetState bool GetStateColor(); + //@{ + //! Management of the global mode of secondary texturing void SetSecondTexture(int texNum); int GetSecondTexture(); + //@} + //@{ + //! Management of view mode void SetRankView(int rank); int GetRankView(); + //@} + //! Whether to draw the world void SetDrawWorld(bool draw); + + //! Whether to draw the world on the interface void SetDrawFront(bool draw); - void SetAmbientColor(const Gfx::Color &color, int rank = 0); + //@{ + //! Ambient color management + void SetAmbientColor(const Gfx::Color& color, int rank = 0); Gfx::Color GetAmbientColor(int rank = 0); + //@} - void SetWaterAddColor(const Gfx::Color &color); + //@{ + //! Color management under water + void SetWaterAddColor(const Gfx::Color& color); Gfx::Color GetWaterAddColor(); + //@} - void SetFogColor(const Gfx::Color &color, int rank = 0); + //@{ + //! Management of the fog color + void SetFogColor(const Gfx::Color& color, int rank = 0); Gfx::Color GetFogColor(int rank = 0); + //@} + //@{ + //! Management of the depth of field. + /** Beyond this distance, nothing is visible. + Shortly (according SetFogStart), one enters the fog. */ void SetDeepView(float length, int rank = 0, bool ref=false); float GetDeepView(int rank = 0); + //@} + + //@{ + //! Management the start of fog. + /** With 0.0, the fog from the point of view (fog max). + With 1.0, the fog from the depth of field (no fog). */ void SetFogStart(float start, int rank = 0); float GetFogStart(int rank = 0); + //@} - void SetBackground(const std::string &name, Gfx::Color up = Gfx::Color(), Gfx::Color down = Gfx::Color(), + //@{ + //! Management of the background image to use + void SetBackground(const std::string& name, Gfx::Color up = Gfx::Color(), Gfx::Color down = Gfx::Color(), Gfx::Color cloudUp = Gfx::Color(), Gfx::Color cloudDown = Gfx::Color(), bool full = false, bool quarter = false); - void GetBackground(const std::string &name, Gfx::Color &up, Gfx::Color &down, - Gfx::Color &cloudUp, Gfx::Color &cloudDown, - bool &full, bool &quarter); - void SetFrontsizeName(char *name); + void GetBackground(std::string& name, Gfx::Color& up, Gfx::Color& down, + Gfx::Color& cloudUp, Gfx::Color& cloudDown, + bool& full, bool& quarter); + //@} + + //! Specifies the foreground image + void SetForegroundImageName(const std::string& name); + //! Specifies whether to draw the foreground void SetOverFront(bool front); - void SetOverColor(const Gfx::Color &color = Gfx::Color(), int mode = ENG_RSTATE_TCOLOR_BLACK); + //! Sets the foreground overlay color + void SetOverColor(const Gfx::Color& color = Gfx::Color(), int mode = ENG_RSTATE_TCOLOR_BLACK); + //@{ + //! Management of the particle density void SetParticleDensity(float value); float GetParticleDensity(); + //@} + + //! Adapts particle factor according to particle density float ParticleAdapt(float factor); + //@{ + //! Management of the distance of clipping. void SetClippingDistance(float value); float GetClippingDistance(); + //@} + //@{ + //! Management of objects detals. void SetObjectDetail(float value); float GetObjectDetail(); + //@} + //@{ + //! The amount of management objects gadgets void SetGadgetQuantity(float value); float GetGadgetQuantity(); + //@} + //@{ + //! Management the quality of textures void SetTextureQuality(int value); int GetTextureQuality(); + //@} + //@{ + //! Management mode of toto void SetTotoMode(bool present); bool GetTotoMode(); + //@} + //@{ + //! Management the mode of foreground void SetLensMode(bool present); bool GetLensMode(); + //@} + //@{ + //! Management the mode of water void SetWaterMode(bool present); bool GetWaterMode(); + //@} void SetLightingMode(bool present); bool GetLightingMode(); + //@{ + //! Management the mode of sky void SetSkyMode(bool present); bool GetSkyMode(); + //@} + //@{ + //! Management the mode of background void SetBackForce(bool present); bool GetBackForce(); + //@} + //@{ + //! Management the mode of planets void SetPlanetMode(bool present); bool GetPlanetMode(); + //@} + //@{ + //! Managing the mode of dynamic lights. void SetLightMode(bool present); bool GetLightMode(); + //@} + //@{ + // TODO: move to more appropriate class ? + //! Management of the indentation mode while editing (CEdit) void SetEditIndentMode(bool autoIndent); bool GetEditIndentMode(); + //@} + //@{ + // TODO: move to more appropriate class ? + //! Management of tab indent when editing (CEdit) void SetEditIndentValue(int value); int GetEditIndentValue(); + //@} + //@{ + //! Management of game speed void SetSpeed(float speed); float GetSpeed(); + //@{ + //! Management of precision of robot tracks void SetTracePrecision(float factor); float GetTracePrecision(); + //@} - void SetFocus(float focus); - float GetFocus(); - Math::Vector GetEyePt(); - Math::Vector GetLookatPt(); - float GetEyeDirH(); - float GetEyeDirV(); - Math::IntSize GetWindowSize(); - Math::IntSize GetLastWindowSize(); - void UpdateMatProj(); - - void ApplyChange(); - - void FlushPressKey(); - void ResetKey(); - void SetKey(int keyRank, int option, int key); - int GetKey(int keyRank, int option); - - void SetJoystick(bool enable); - bool GetJoystick(); - - void SetDebugMode(bool mode); - bool GetDebugMode(); - bool GetSetupMode(); - - bool IsVisiblePoint(const Math::Vector &pos); - - int DetectObject(Math::Point mouse); - void SetState(int state, Gfx::Color color = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); - void SetTexture(const std::string &name, int stage = 0); - void SetMaterial(const Gfx::Material &mat); - + //@{ + //! Management of mouse cursor visibility void SetMouseVisible(bool show); bool GetMouseVisible(); + //@} + + //@{ + //! Management of mouse cursor position void SetMousePos(Math::Point pos); Math::Point GetMousePos(); + //@} + + //@{ + //! Management of mouse cursor type void SetMouseType(Gfx::EngineMouseType type); Gfx::EngineMouseType GetMouseType(); + //@} - CText* GetText(); + //! Returns the view matrix + const Math::Matrix& GetMatView(); + //! Returns the camera center point + Math::Vector GetEyePt(); + //! Returns the camera target point + Math::Vector GetLookatPt(); + //! Returns the horizontal direction angle of view + float GetEyeDirH(); + //! Returns the vertical direction angle of view + float GetEyeDirV(); + //! Indicates whether a point is visible + bool IsVisiblePoint(const Math::Vector& pos); - bool ChangeColor(char *name, Gfx::Color colorRef1, Gfx::Color colorNew1, - Gfx::Color colorRef2, Gfx::Color colorNew2, - float tolerance1, float tolerance2, - Math::Point ts, Math::Point ti, - Math::Point *pExclu=0, float shift=0.0f, bool hSV=false); - bool OpenImage(char *name); - bool CopyImage(); - bool LoadImage(); - bool ScrollImage(int dx, int dy); - bool SetDot(int x, int y, Gfx::Color color); - bool CloseImage(); - bool WriteScreenShot(char *filename, int width, int height); - //bool GetRenderDC(HDC &hDC); - //bool ReleaseRenderDC(HDC &hDC); - //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp); - //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC); + //! Resets the projection matrix after changes + void UpdateMatProj(); -protected: + //! Updates the scene after a change of parameters + void ApplyChange(); - void SetUp3DView(); - bool Draw3DScene(); +protected: + //! Prepares the interface for 3D scene + void Draw3DScene(); + //! Draws the user interface over the scene + void DrawInterface(); - void SetUpInterfaceView(); - bool DrawInterface(); + //! Updates the textures used for drawing ground spot + void UpdateGroundSpotTextures(); - void DrawGroundSpot(); + //! Draws shadows void DrawShadow(); + //! Draws the gradient background void DrawBackground(); - void DrawBackgroundGradient(Gfx::Color up, Gfx::Color down); - void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name); + //! Draws the gradient background + void DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down); + //! Draws a portion of the image background + void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name); + //! Draws the image background void DrawBackgroundImage(); + //! Draws all the planets void DrawPlanet(); - void DrawFrontsize(); + //! Draws the image foreground + void DrawForegroundImage(); + //! Draws the foreground color void DrawOverColor(); - void DrawHilite(); + //! Draws the rectangle of the object highlighted + void DrawHighlight(); + //! Draws the mouse cursor void DrawMouse(); + //! Draw part of mouse cursor sprite void DrawMouseSprite(Math::Point pos, Math::Point dim, int icon); - /* - Gfx::ObjLevel2* AddLevel1(Gfx::ObjLevel1 *&p1, char* texName1, char* texName2); - Gfx::ObjLevel3* AddLevel2(Gfx::ObjLevel2 *&p2, int objRank); - Gfx::ObjLevel4* AddLevel3(Gfx::ObjLevel3 *&p3, float min, float max); - Gfx::ObjLevel5* AddLevel4(Gfx::ObjLevel4 *&p4, int reserve); - Gfx::ObjLevel6* AddLevel5(Gfx::ObjLevel5 *&p5, Gfx::TriangleType type, const Gfx::Material &mat, int state, int nb);*/ - + //! Tests whether the given object is visible bool IsVisible(int objRank); + + //! Detects whether an object is affected by the mouse bool DetectBBox(int objRank, Math::Point mouse); - bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max); - bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2 *triangle, int objRank, float &dist); - bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D); + + //! Compute and return the 2D box on screen of any object + bool GetBBox2D(int objRank, Math::Point& min, Math::Point& max); + + //! Detects the target object that is selected with the mouse + /** Returns the rank of the object or -1. */ + int DetectObject(Math::Point mouse); + + //! Detects whether the mouse is in a triangle. + bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2* triangle, int objRank, float& dist); + + //! Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window + /** The coordinated p2D.z gives the distance. */ + bool TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D); + + //! Calculates the distances between the viewpoint and the origin of different objects void ComputeDistance(); + + //! Updates all the geometric parameters of objects void UpdateGeometry(); protected: CInstanceManager* m_iMan; CApplication* m_app; - CSound* m_sound; + CSoundInterface* m_sound; Gfx::CDevice* m_device; Gfx::CText* m_text; Gfx::CLightManager* m_lightMan; @@ -892,7 +1056,7 @@ protected: Gfx::CPlanet* m_planet; Gfx::CTerrain* m_terrain; - bool m_wasInit; + //! Last encountered error std::string m_error; //! Whether to show stats (FPS, etc) @@ -926,9 +1090,9 @@ protected: bool m_render; bool m_movieLock; - //! Current size of viewport + //! Current size of viewport window Math::IntSize m_size; - //! Previous size of viewport + //! Previous size of viewport window Math::IntSize m_lastSize; std::vector m_objectTree; @@ -950,7 +1114,6 @@ protected: Gfx::Color m_waterAddColor; int m_statisticTriangle; bool m_updateGeometry; - //char m_infoText[10][200]; int m_alphaMode; bool m_stateColor; bool m_forceStateColor; @@ -970,11 +1133,11 @@ protected: bool m_overFront; Gfx::Color m_overColor; int m_overMode; - std::string m_frontsizeName; + std::string m_foregroundImageName; bool m_drawWorld; bool m_drawFront; float m_limitLOD[2]; - float m_particuleDensity; + float m_particleDensity; float m_clippingDistance; float m_lastClippingDistance; float m_objectDetail; @@ -993,10 +1156,10 @@ protected: int m_editIndentValue; float m_tracePrecision; - int m_hiliteRank[100]; - bool m_hilite; - Math::Point m_hiliteP1; - Math::Point m_hiliteP2; + int m_highlightRank[100]; + bool m_highlight; + Math::Point m_highlightP1; + Math::Point m_highlightP2; int m_lastState; Gfx::Color m_lastColor; @@ -1015,12 +1178,6 @@ protected: Gfx::EngineMouseType m_mouseType; Math::Point m_mousePos; bool m_mouseVisible; - - //LPDIRECTDRAWSURFACE7 m_imageSurface; - //DDSURFACEDESC2 m_imageDDSD; - //WORD* m_imageCopy; - //int m_imageDX; - //int m_imageDY; }; }; // namespace Gfx -- cgit v1.2.3-1-g7c22 From 7f80ca297154809523cd533edf1842ab1ae391aa Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 11 Aug 2012 17:17:04 +0200 Subject: Render mode setting, refactoring - finished SetState in CEngine - refactored Size and IntSize back to Point and IntPoint - other minor changes in CEngine --- src/graphics/core/device.h | 6 +- src/graphics/core/texture.h | 4 +- src/graphics/engine/engine.cpp | 367 +++++++++++++++++++-------------------- src/graphics/engine/engine.h | 114 ++++++------ src/graphics/engine/text.cpp | 64 +++---- src/graphics/engine/text.h | 7 +- src/graphics/opengl/gldevice.cpp | 6 +- 7 files changed, 287 insertions(+), 281 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 3ab86dd..d4fcd26 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -25,7 +25,7 @@ #include "graphics/core/material.h" #include "graphics/core/texture.h" #include "graphics/core/vertex.h" -#include "math/intsize.h" +#include "math/intpoint.h" #include "math/matrix.h" #include @@ -46,7 +46,7 @@ namespace Gfx { struct DeviceConfig { //! Screen size - Math::IntSize size; + Math::IntPoint size; //! Bits per pixel int bpp; //! Full screen @@ -64,7 +64,7 @@ struct DeviceConfig //! Loads the default values inline void LoadDefault() { - size = Math::IntSize(800, 600); + size = Math::IntPoint(800, 600); bpp = 32; fullScreen = false; resizeable = false; diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h index 8d6b082..bb5b52f 100644 --- a/src/graphics/core/texture.h +++ b/src/graphics/core/texture.h @@ -18,7 +18,7 @@ #pragma once -#include "math/intsize.h" +#include "math/intpoint.h" namespace Gfx { @@ -194,7 +194,7 @@ struct Texture //! ID of the texture in graphics engine unsigned int id; //! Size of texture - Math::IntSize size; + Math::IntPoint size; //! Whether the texture has alpha channel bool alpha; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 4244fb2..0461636 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -80,9 +80,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_terrain = nullptr; m_focus = 0.75f; - m_baseTime = 0; - m_lastTime = 0; - m_absTime = 0.0f; + m_rankView = 0; m_ambientColor[0] = Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f); @@ -147,15 +145,6 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_forceStateColor = true; m_stateColor = false; - m_blackSrcBlend[0] = 0; - m_blackDestBlend[0] = 0; - m_whiteSrcBlend[0] = 0; - m_whiteDestBlend[0] = 0; - m_diffuseSrcBlend[0] = 0; - m_diffuseDestBlend[0] = 0; - m_alphaSrcBlend[0] = 0; - m_alphaDestBlend[0] = 0; - m_updateGeometry = false; m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 1.0f, 1.0f)); @@ -188,8 +177,8 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_objectTree.reserve(LEVEL1_PREALLOCATE_COUNT); m_objects.reserve(OBJECT_PREALLOCATE_COUNT); - m_shadow.reserve(SHADOW_PREALLOCATE_COUNT); - m_groundSpot.reserve(GROUNDSPOT_PREALLOCATE_COUNT); + m_shadows.reserve(SHADOW_PREALLOCATE_COUNT); + m_groundSpots.reserve(GROUNDSPOT_PREALLOCATE_COUNT); } Gfx::CEngine::~CEngine() @@ -372,38 +361,6 @@ void Gfx::CEngine::StepSimulation(float rTime) m_app->StepSimulation(rTime); } -void Gfx::CEngine::TimeInit() -{ - /* TODO! - m_baseTime = timeGetTime(); - m_lastTime = 0; - m_absTime = 0.0f;*/ -} - -void Gfx::CEngine::TimeEnterGel() -{ - /* TODO! - m_stopTime = timeGetTime();*/ -} - -void Gfx::CEngine::TimeExitGel() -{ - /* TODO! - m_baseTime += timeGetTime() - m_stopTime;*/ -} - -float Gfx::CEngine::TimeGet() -{ - /* TODO! - float aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms - float rTime = (aTime - m_lastTime)*m_speed; - m_absTime += rTime; - m_lastTime = aTime; - - return rTime;*/ - return 0.0f; -} - bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height) { // TODO! @@ -457,38 +414,38 @@ void Gfx::CEngine::SetRenderEnable(bool enable) m_render = enable; } -Math::IntSize Gfx::CEngine::GetWindowSize() +Math::IntPoint Gfx::CEngine::GetWindowSize() { return m_size; } -Math::IntSize Gfx::CEngine::GetLastWindowSize() +Math::IntPoint Gfx::CEngine::GetLastWindowSize() { return m_lastSize; } Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) { - return Math::Point( static_cast(pos.x) / static_cast(m_size.w), - 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); + return Math::Point( static_cast(pos.x) / static_cast(m_size.x), + 1.0f - static_cast(pos.y) / static_cast(m_size.y) ); } Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) { - return Math::IntPoint(static_cast(pos.x * m_size.w), - static_cast((1.0f - pos.y) * m_size.h)); + return Math::IntPoint(static_cast(pos.x * m_size.x), + static_cast((1.0f - pos.y) * m_size.y)); } -Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +Math::Point Gfx::CEngine::WindowToInterfaceSize(Math::IntPoint size) { - return Math::Size( static_cast(size.w) / static_cast(m_size.w), - static_cast(size.h) / static_cast(m_size.h) ); + return Math::Point(static_cast(size.x) / static_cast(m_size.x), + static_cast(size.y) / static_cast(m_size.y)); } -Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +Math::IntPoint Gfx::CEngine::InterfaceToWindowSize(Math::Point size) { - return Math::IntSize(static_cast(size.w * m_size.w), - static_cast(size.h * m_size.h)); + return Math::IntPoint(static_cast(size.x * m_size.x), + static_cast(size.y * m_size.y)); } std::string Gfx::CEngine::GetTextureDir() @@ -874,7 +831,18 @@ bool Gfx::CEngine::IsVisible(int objRank) bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D) { - // TODO! + p3D = Math::Transform(m_objects[objRank].transform, p3D); + p3D = Math::Transform(m_matView, p3D); + + if (p3D.z < 2.0f) return false; // behind? + + p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1); + p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2); + p2D.z = p3D.z; + + p2D.x = (p2D.x+1.0f)/2.0f; // [-1..1] -> [0..1] + p2D.y = (p2D.y+1.0f)/2.0f; + return true; } @@ -888,13 +856,13 @@ bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p void Gfx::CEngine::SetState(int state, const Gfx::Color& color) { - if ( state == m_lastState && color == m_lastColor ) + if (state == m_lastState && color == m_lastColor) return; m_lastState = state; m_lastColor = color; - if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) ) + if (m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA)) { state &= ~Gfx::ENG_RSTATE_ALPHA; @@ -902,133 +870,150 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK; } - // TODO other modes & thorough testing - if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture? + if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // transparent black texture? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); - m_device->SetTextureEnabled(0, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureFactor(color); Gfx::TextureStageParams params; params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + + m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); } - else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture? + else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // transparent white texture? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); - m_device->SetTextureEnabled(0, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureFactor(color.Inverse()); Gfx::TextureStageParams params; params.colorOperation = Gfx::TEX_MIX_OPER_ADD; params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + + m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); } - else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color? + else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // transparent black color? { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); - - m_device->SetTextureFactor(color); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); } - else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color? + else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // transparent white color? { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); - - m_device->SetTextureFactor(color.Inverse()); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); } else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]); - - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ - } - else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128)); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]); - - m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color); - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ - } - else if (state & Gfx::ENG_RSTATE_TEXT) { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_DST_ALPHA); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_REPLACE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + m_device->SetTextureStageParams(0, params); + } + else if (state & Gfx::ENG_RSTATE_TEXT) // font rendering? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); // TODO: depth test setting elsewhere! + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; // default modulate operation + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // default modulate operation + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, params); } - else // normal ? + else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? { + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, true); + + m_device->SetAlphaTestFunc(Gfx::COMP_FUNC_GREATER, 0.5f); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureFactor(color); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_SRC_COLOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_REPLACE; + params.alphaArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + m_device->SetTextureStageParams(0, params); + } + else // normal ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; // default modulate + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? - /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, params); } if (state & Gfx::ENG_RSTATE_FOG) @@ -1040,21 +1025,25 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false; if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false; - if ( (state & ENG_RSTATE_DUAL_BLACK) && second ) + if ((state & ENG_RSTATE_DUAL_BLACK) && second) { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: ??? + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(1, params); } - else if ( (state & ENG_RSTATE_DUAL_WHITE) && second ) + else if ((state & ENG_RSTATE_DUAL_WHITE) && second) { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_ADD; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: ??? + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(1, params); } else { @@ -1063,18 +1052,25 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) if (state & Gfx::ENG_RSTATE_WRAP) { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/ - } - else if (state & Gfx::ENG_RSTATE_CLAMP) - { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + // TODO: separate function for setting wrap mode? + + Gfx::TextureStageParams p1 = m_device->GetTextureStageParams(0); + p1.wrapS = p1.wrapT = Gfx::TEX_WRAP_REPEAT; + m_device->SetTextureStageParams(0, p1); + + Gfx::TextureStageParams p2 = m_device->GetTextureStageParams(1); + p2.wrapS = p2.wrapT = Gfx::TEX_WRAP_REPEAT; + m_device->SetTextureStageParams(1, p2); } - else + else // if (state & Gfx::ENG_RSTATE_CLAMP) or otherwise { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + Gfx::TextureStageParams p1 = m_device->GetTextureStageParams(0); + p1.wrapS = p1.wrapT = Gfx::TEX_WRAP_CLAMP; + m_device->SetTextureStageParams(0, p1); + + Gfx::TextureStageParams p2 = m_device->GetTextureStageParams(1); + p2.wrapS = p2.wrapT = Gfx::TEX_WRAP_CLAMP; + m_device->SetTextureStageParams(1, p2); } if (state & Gfx::ENG_RSTATE_2FACE) @@ -1197,13 +1193,13 @@ float Gfx::CEngine::GetLimitLOD(int rank, bool last) if (last) { limit = m_limitLOD[rank]; - limit *= m_lastSize.w/640.0f; // limit further if large window! + limit *= m_lastSize.x/640.0f; // limit further if large window! limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f); } else { limit = m_limitLOD[rank]; - limit *= m_size.w/640.0f; // limit further if large window! + limit *= m_size.x/640.0f; // limit further if large window! limit += m_limitLOD[0]*(m_objectDetail*2.0f); } @@ -1222,7 +1218,7 @@ void Gfx::CEngine::SetFocus(float focus) m_focus = focus; m_size = m_app->GetVideoConfig().size; - float aspect = (static_cast(m_size.h)) / m_size.w; + float aspect = (static_cast(m_size.y)) / m_size.x; Math::LoadProjectionMatrix(m_matProj, m_focus, aspect, 0.5f, m_deepView[0]); } @@ -1698,15 +1694,6 @@ void Gfx::CEngine::ApplyChange() viewport, and renders the scene. */ void Gfx::CEngine::Render() { - /* TODO! - D3DObjLevel1* p1; - D3DObjLevel2* p2; - D3DObjLevel3* p3; - D3DObjLevel4* p4; - D3DObjLevel5* p5; - D3DVERTEX2* pv; - int l1, l2, l3, l4, l5, objRank;*/ - if (! m_render) return; m_statisticTriangle = 0; @@ -1729,19 +1716,27 @@ void Gfx::CEngine::Render() if (m_drawWorld) - { Draw3DScene(); - } DrawInterface(); + // End the scene m_device->EndScene(); } void Gfx::CEngine::Draw3DScene() { + /* TODO! + D3DObjLevel1* p1; + D3DObjLevel2* p2; + D3DObjLevel3* p3; + D3DObjLevel4* p4; + D3DObjLevel5* p5; + D3DVERTEX2* pv; + int l1, l2, l3, l4, l5, objRank;*/ + if (m_groundSpotVisible) UpdateGroundSpotTextures(); @@ -2153,11 +2148,11 @@ void Gfx::CEngine::DrawShadow() float endDeepView = m_deepView[m_rankView]; float lastIntensity = -1.0f; - for (int i = 0; i < static_cast( m_shadow.size() ); i++) + for (int i = 0; i < static_cast( m_shadows.size() ); i++) { - if (m_shadow[i].hide) continue; + if (m_shadows[i].hide) continue; - Math::Vector pos = m_shadow[i].pos; // pos = center of the shadow on the ground + Math::Vector pos = m_shadows[i].pos; // pos = center of the shadow on the ground if (m_eyePt.y == pos.y) continue; // camera at the same level? @@ -2169,7 +2164,7 @@ void Gfx::CEngine::DrawShadow() if (m_eyePt.y > pos.y) // camera on? { float height = m_eyePt.y-pos.y; - float h = m_shadow[i].radius; + float h = m_shadows[i].radius; float max = height*0.5f; if ( h > max ) h = max; if ( h > 4.0f ) h = 4.0f; @@ -2185,7 +2180,7 @@ void Gfx::CEngine::DrawShadow() else // camera underneath? { float height = pos.y-m_eyePt.y; - float h = m_shadow[i].radius; + float h = m_shadows[i].radius; float max = height*0.1f; if ( h > max ) h = max; if ( h > 4.0f ) h = 4.0f; @@ -2201,20 +2196,20 @@ void Gfx::CEngine::DrawShadow() // The hFactor decreases the intensity and size increases more // the object is high relative to the ground. - float hFactor = m_shadow[i].height/20.0f; + float hFactor = m_shadows[i].height/20.0f; if ( hFactor < 0.0f ) hFactor = 0.0f; if ( hFactor > 1.0f ) hFactor = 1.0f; hFactor = powf(1.0f-hFactor, 2.0f); if ( hFactor < 0.2f ) hFactor = 0.2f; - float radius = m_shadow[i].radius*1.5f; + float radius = m_shadows[i].radius*1.5f; radius *= 2.0f-hFactor; // greater if high radius *= 1.0f-d/D; // smaller if close Math::Vector corner[4]; - if (m_shadow[i].type == Gfx::ENG_SHADOW_NORM) + if (m_shadows[i].type == Gfx::ENG_SHADOW_NORM) { corner[0].x = +radius; corner[0].z = +radius; @@ -2239,27 +2234,27 @@ void Gfx::CEngine::DrawShadow() { Math::Point rot; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(radius, radius)); corner[0].x = rot.x; corner[0].z = rot.y; corner[0].y = 0.0f; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(-radius, radius)); corner[1].x = rot.x; corner[1].z = rot.y; corner[1].y = 0.0f; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(radius, -radius)); corner[2].x = rot.x; corner[2].z = rot.y; corner[2].y = 0.0f; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(-radius, -radius)); corner[3].x = rot.x; corner[3].z = rot.y; corner[3].y = 0.0f; - if (m_shadow[i].type == Gfx::ENG_SHADOW_WORM) + if (m_shadows[i].type == Gfx::ENG_SHADOW_WORM) { ts.x = 96.0f/256.0f; ti.x = 128.0f/256.0f; @@ -2271,10 +2266,10 @@ void Gfx::CEngine::DrawShadow() } } - corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal); - corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal); - corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal); - corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal); + corner[0] = Math::CrossProduct(corner[0], m_shadows[i].normal); + corner[1] = Math::CrossProduct(corner[1], m_shadows[i].normal); + corner[2] = Math::CrossProduct(corner[2], m_shadows[i].normal); + corner[3] = Math::CrossProduct(corner[3], m_shadows[i].normal); corner[0] += pos; corner[1] += pos; @@ -2292,7 +2287,7 @@ void Gfx::CEngine::DrawShadow() Gfx::Vertex(corner[2], n, Math::Point(ti.x, ti.y)) }; - float intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor; + float intensity = (0.5f+m_shadows[i].intensity*0.5f)*hFactor; // Decreases the intensity of the shade if you're in the area // between the beginning and the end of the fog. diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index d01a679..8f9338a 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -19,17 +19,15 @@ #pragma once - +#include "app/system.h" #include "common/event.h" #include "graphics/core/color.h" #include "graphics/core/material.h" #include "graphics/core/texture.h" #include "graphics/core/vertex.h" #include "math/intpoint.h" -#include "math/intsize.h" #include "math/matrix.h" #include "math/point.h" -#include "math/size.h" #include "math/vector.h" @@ -567,15 +565,6 @@ public: //! Evolved throughout the game void StepSimulation(float rTime); - //! Initialize timestamps at the beginning of animation - void TimeInit(); - //! Suspend animation - void TimeEnterGel(); - //! Resume animation - void TimeExitGel(); - //! Returns the relative time since last animation update - float TimeGet(); - //! Writes a screenshot containing the current frame bool WriteScreenShot(const std::string& fileName, int width, int height); @@ -608,22 +597,24 @@ public: void SetRenderEnable(bool enable); //! Returns current size of viewport window - Math::IntSize GetWindowSize(); + Math::IntPoint GetWindowSize(); //! Returns the last size of viewport window - Math::IntSize GetLastWindowSize(); + Math::IntPoint GetLastWindowSize(); - //! Converts window coords to interface coords - /** Conversion of the position of the mouse from window coords to interface coords: - - x: 0=left, 1=right - - y: 0=down, 1=up */ + //@{ + //! Conversion functions between window and interface coordinates + /** Window coordinates are from top-left (0,0) to bottom-right (w,h) - size of window + Interface cords are from bottom-left (0,0) to top-right (1,1) - and do not depend on window size */ Math::Point WindowToInterfaceCoords(Math::IntPoint pos); - //! Converts interface coords to window coords Math::IntPoint InterfaceToWindowCoords(Math::Point pos); + //@} - //! Converts window size to interface size - Math::Size WindowToInterfaceSize(Math::IntSize size); - //! Converts interface size to window size - Math::IntSize InterfaceToWindowSize(Math::Size size); + //@{ + //! Conversion functions between window and interface sizes + /** Unlike coordinate conversions, this is only scale conversion, not translation and scale. */ + Math::Point WindowToInterfaceSize(Math::IntPoint size); + Math::IntPoint InterfaceToWindowSize(Math::Point size); + //@} //! Returns the name of directory with textures std::string GetTextureDir(); @@ -1062,46 +1053,48 @@ protected: //! Whether to show stats (FPS, etc) bool m_showStats; - int m_blackSrcBlend[2]; - int m_blackDestBlend[2]; - int m_whiteSrcBlend[2]; - int m_whiteDestBlend[2]; - int m_diffuseSrcBlend[2]; - int m_diffuseDestBlend[2]; - int m_alphaSrcBlend[2]; - int m_alphaDestBlend[2]; + //! Speed of animation + float m_speed; + //! Pause mode + bool m_pause; + //! Rendering enabled? + bool m_render; + //! Lock for duration of movie? + bool m_movieLock; + //! Projection matrix for 3D scene Math::Matrix m_matProj; - Math::Matrix m_matLeftView; - Math::Matrix m_matRightView; + //! View matrix for 3D scene Math::Matrix m_matView; + //! Camera angle for 3D scene float m_focus; + //! World matrix for 2D interface Math::Matrix m_matWorldInterface; + //! Projection matrix for 2D interface Math::Matrix m_matProjInterface; + //! View matrix for 2D interface Math::Matrix m_matViewInterface; - long m_baseTime; - long m_stopTime; - float m_absTime; - float m_lastTime; - float m_speed; - bool m_pause; - bool m_render; - bool m_movieLock; - //! Current size of viewport window - Math::IntSize m_size; + Math::IntPoint m_size; //! Previous size of viewport window - Math::IntSize m_lastSize; + Math::IntPoint m_lastSize; + //! Root of tree object structure (level 1 list) std::vector m_objectTree; + //! Object parameters std::vector m_objects; - std::vector m_shadow; - std::vector m_groundSpot; + //! Shadow list + std::vector m_shadows; + //! Ground spot list + std::vector m_groundSpots; + //! Ground mark Gfx::EngineGroundMark m_groundMark; + //! Location of camera Math::Vector m_eyePt; + //! Camera target Math::Vector m_lookatPt; float m_eyeDirH; float m_eyeDirV; @@ -1156,28 +1149,47 @@ protected: int m_editIndentValue; float m_tracePrecision; + //! Ranks of highlighted objects int m_highlightRank[100]; + //! Highlight visible? bool m_highlight; + //@{ + //! Highlight rectangle points Math::Point m_highlightP1; Math::Point m_highlightP2; + //@} - int m_lastState; - Gfx::Color m_lastColor; - char m_lastTexture[2][50]; - Gfx::Material m_lastMaterial; - + //! Texture directory name std::string m_texPath; + //! Default texture create params Gfx::TextureCreateParams m_defaultTexParams; + //! Map of loaded textures (by name) std::map m_texNameMap; + //! Reverse map of loaded textures (by texture) std::map m_revTexNameMap; + //! Mouse cursor definitions Gfx::EngineMouse m_mice[Gfx::ENG_MOUSE_COUNT]; + //! Texture with mouse cursors Gfx::Texture m_miceTexture; + //! Size of mouse cursor Math::Point m_mouseSize; + //! Type of mouse cursor Gfx::EngineMouseType m_mouseType; + //! Position of mouse in interface coords Math::Point m_mousePos; + //! Is mouse visible? bool m_mouseVisible; + + //! Last engine render state (-1 at the beginning of frame) + int m_lastState; + //! Last color set with render state + Gfx::Color m_lastColor; + //! Last texture names for 2 used texture stages + std::string m_lastTexture[2]; + //! Last material + Gfx::Material m_lastMaterial; }; }; // namespace Gfx diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index 77515ad..0a57026 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -245,10 +245,10 @@ float Gfx::CText::GetAscent(Gfx::FontType font, float size) Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - wndSize.h = TTF_FontAscent(cf->font); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.h; + Math::IntPoint wndSize; + wndSize.y = TTF_FontAscent(cf->font); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.y; } float Gfx::CText::GetDescent(Gfx::FontType font, float size) @@ -257,10 +257,10 @@ float Gfx::CText::GetDescent(Gfx::FontType font, float size) Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - wndSize.h = TTF_FontDescent(cf->font); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.h; + Math::IntPoint wndSize; + wndSize.y = TTF_FontDescent(cf->font); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.y; } float Gfx::CText::GetHeight(Gfx::FontType font, float size) @@ -269,10 +269,10 @@ float Gfx::CText::GetHeight(Gfx::FontType font, float size) Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - wndSize.h = TTF_FontHeight(cf->font); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.h; + Math::IntPoint wndSize; + wndSize.y = TTF_FontHeight(cf->font); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.y; } @@ -315,10 +315,10 @@ float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, fl Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.w, &wndSize.h); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.w; + Math::IntPoint wndSize; + TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.x, &wndSize.y); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.x; } float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset) @@ -339,7 +339,7 @@ float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, else tex = CreateCharTexture(ch, cf); - return tex.charSize.w; + return tex.charSize.x; } @@ -539,9 +539,9 @@ void Gfx::CText::DrawString(const std::string &text, const std::vector(format[fmtIndex] & Gfx::FONT_MASK_HIGHLIGHT); if (hl != Gfx::FONT_HIGHLIGHT_NONE) { - Math::Size charSize; - charSize.w = GetCharWidth(ch, font, size, offset); - charSize.h = GetHeight(font, size); + Math::Point charSize; + charSize.x = GetCharWidth(ch, font, size, offset); + charSize.y = GetHeight(font, size); DrawHighlight(hl, pos, charSize); } @@ -580,7 +580,7 @@ void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, } } -void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size) +void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Point size) { // Gradient colors Gfx::Color grad[4]; @@ -622,16 +622,16 @@ void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Siz return; } - Math::IntSize vsize = m_engine->GetWindowSize(); + Math::IntPoint vsize = m_engine->GetWindowSize(); float h = 0.0f; - if (vsize.h <= 768.0f) // 1024x768 or less? - h = 1.01f / vsize.h; // 1 pixel + if (vsize.y <= 768.0f) // 1024x768 or less? + h = 1.01f / vsize.y; // 1 pixel else // more than 1024x768? - h = 2.0f / vsize.h; // 2 pixels + h = 2.0f / vsize.y; // 2 pixels Math::Point p1, p2; p1.x = pos.x; - p2.x = pos.x + size.w; + p2.x = pos.x + size.x; if (hl == Gfx::FONT_HIGHLIGHT_LINK) { @@ -641,7 +641,7 @@ void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Siz else { p1.y = pos.y; - p2.y = pos.y + size.h; + p2.y = pos.y + size.y; } m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); @@ -690,8 +690,8 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); - Math::Point p1(pos.x, pos.y + tex.charSize.h - tex.texSize.h); - Math::Point p2(pos.x + tex.texSize.w, pos.y + tex.charSize.h); + Math::Point p1(pos.x, pos.y + tex.charSize.y - tex.texSize.y); + Math::Point p2(pos.x + tex.texSize.x, pos.y + tex.charSize.y); Math::Vector n(0.0f, 0.0f, -1.0f); // normal @@ -707,7 +707,7 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); m_engine->AddStatisticTriangle(2); - pos.x += tex.charSize.w; + pos.x += tex.charSize.x; } Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) @@ -797,8 +797,8 @@ Gfx::CharTexture Gfx::CText::CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont } texture.id = tex.id; - texture.texSize = m_engine->WindowToInterfaceSize(Math::IntSize(textureSurface->w, textureSurface->h)); - texture.charSize = m_engine->WindowToInterfaceSize(Math::IntSize(textSurface->w, textSurface->h)); + texture.texSize = m_engine->WindowToInterfaceSize(Math::IntPoint(textureSurface->w, textureSurface->h)); + texture.charSize = m_engine->WindowToInterfaceSize(Math::IntPoint(textSurface->w, textSurface->h)); return texture; } diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 6209c39..7e2f84b 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -20,7 +20,6 @@ #pragma once #include "math/point.h" -#include "math/size.h" #include #include @@ -168,8 +167,8 @@ struct UTF8Char struct CharTexture { unsigned int id; - Math::Size texSize; - Math::Size charSize; + Math::Point texSize; + Math::Point charSize; CharTexture() : id(0) {} }; @@ -277,7 +276,7 @@ protected: float size, Math::Point pos, float width, int eol); void DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol); - void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size); + void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Point size); void DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos); protected: diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index cef372f..4c36053 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -122,7 +122,7 @@ bool Gfx::CGLDevice::Create() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glViewport(0, 0, m_config.size.w, m_config.size.h); + glViewport(0, 0, m_config.size.x, m_config.size.y); m_lights = std::vector(GL_MAX_LIGHTS, Gfx::Light()); @@ -390,8 +390,8 @@ Gfx::Texture Gfx::CGLDevice::CreateTexture(ImageData *data, const Gfx::TextureCr Gfx::Texture result; result.valid = true; - result.size.w = data->surface->w; - result.size.h = data->surface->h; + result.size.x = data->surface->w; + result.size.y = data->surface->h; // Use & enable 1st texture stage glActiveTexture(GL_TEXTURE0); -- cgit v1.2.3-1-g7c22 From 1996507fd3d4d9de90de99845b71a6bf3fbe62da Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 11 Aug 2012 18:39:16 +0200 Subject: Documentation update - updated Doxyfile - added/changed file, dir and namespace descriptions - fixed some errors in doxygen tags --- src/graphics/README.txt | 13 +++++++++++-- src/graphics/core/README.txt | 13 +++++++------ src/graphics/core/color.h | 5 ++++- src/graphics/core/device.h | 5 ++++- src/graphics/core/light.h | 5 ++++- src/graphics/core/material.h | 5 ++++- src/graphics/core/texture.h | 5 ++++- src/graphics/core/vertex.h | 5 ++++- src/graphics/d3d/README.txt | 7 ++++--- src/graphics/engine/README.txt | 17 +++++++++-------- src/graphics/engine/camera.h | 5 ++++- src/graphics/engine/cloud.h | 5 ++++- src/graphics/engine/engine.h | 5 ++++- src/graphics/engine/lightman.h | 5 ++++- src/graphics/engine/lightning.h | 5 ++++- src/graphics/engine/modelfile.h | 5 ++++- src/graphics/engine/particle.h | 5 ++++- src/graphics/engine/planet.h | 5 ++++- src/graphics/engine/pyro.h | 5 ++++- src/graphics/engine/terrain.h | 5 ++++- src/graphics/engine/text.h | 5 ++++- src/graphics/engine/water.h | 5 ++++- src/graphics/opengl/README.txt | 13 +++++++------ src/graphics/opengl/gldevice.h | 5 ++++- 24 files changed, 114 insertions(+), 44 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/README.txt b/src/graphics/README.txt index 3ec3871..479747b 100644 --- a/src/graphics/README.txt +++ b/src/graphics/README.txt @@ -1,3 +1,12 @@ -src/graphics +/** + * \dir graphics + * \brief Graphics engine + */ -Graphics engine +/** + * \namespace Gfx + * \brief Namespace for (new) graphics code + * + * This namespace was created to avoid clashing with old code, but now it still serves, + * defining a border between pure graphics engine and other parts of application. + */ \ No newline at end of file diff --git a/src/graphics/core/README.txt b/src/graphics/core/README.txt index 12beef9..ca3768c 100644 --- a/src/graphics/core/README.txt +++ b/src/graphics/core/README.txt @@ -1,6 +1,7 @@ -src/graphics/core - -Abstract core of graphics engine - -Core types, enums, structs and CDevice abstract class that define -the abstract graphics device used in graphics engine +/** + * \dir graphics/core + * \brief Abstract core of graphics engine + * + * Core types, enums, structs and CDevice abstract class that define + * the abstract graphics device used in graphics engine + */ \ No newline at end of file diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h index 0e08de3..ff8a2eb 100644 --- a/src/graphics/core/color.h +++ b/src/graphics/core/color.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// color.h +/** + * \file graphics/core/color.h + * \brief Color structs and related functions + */ #pragma once diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index d4fcd26..a829c81 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// device.h +/** + * \file graphics/core/device.h + * \brief Abstract graphics device - Gfx::CDevice class and related structs/enums + */ #pragma once diff --git a/src/graphics/core/light.h b/src/graphics/core/light.h index b787cb2..a39d1f5 100644 --- a/src/graphics/core/light.h +++ b/src/graphics/core/light.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// light.h +/** + * \file graphics/core/light.h + * \brief Light struct and related enums + */ #pragma once diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h index 31b42f3..eb73c50 100644 --- a/src/graphics/core/material.h +++ b/src/graphics/core/material.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// material.h +/** + * \file graphics/core/material.h + * \brief Material struct + */ #pragma once diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h index bb5b52f..c36b6c6 100644 --- a/src/graphics/core/texture.h +++ b/src/graphics/core/texture.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// texture.h +/** + * \file graphics/core/texture.h + * \brief Texture struct and related enums + */ #pragma once diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h index b7fab1c..53dd642 100644 --- a/src/graphics/core/vertex.h +++ b/src/graphics/core/vertex.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// vertex.h +/** + * \file graphics/core/vertex.h + * \brief Vertex structs + */ #pragma once diff --git a/src/graphics/d3d/README.txt b/src/graphics/d3d/README.txt index 8388120..524ae7b 100644 --- a/src/graphics/d3d/README.txt +++ b/src/graphics/d3d/README.txt @@ -1,3 +1,4 @@ -src/graphics/d3d - -Possible future DirectX implementation of graphics engine +/** + * \dir graphics/d3d + * \brief Possible future DirectX implementation of graphics engine + */ \ No newline at end of file diff --git a/src/graphics/engine/README.txt b/src/graphics/engine/README.txt index 308b601..f64d3dd 100644 --- a/src/graphics/engine/README.txt +++ b/src/graphics/engine/README.txt @@ -1,8 +1,9 @@ -src/graphics/engine - -Graphics engine - -CEngine class and various other classes implementing the main features -of graphics engine from model loading to decorative particles - -Graphics operations are done on abstract interface from src/graphics/core +/** + * \dir graphics/engine + * \brief Graphics engine + * + * CEngine class and various other classes implementing the main features + * of graphics engine from model loading to decorative particles + * + * Graphics operations are done on abstract interface from src/graphics/core + */ \ No newline at end of file diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h index ec6afcb..1a82f9f 100644 --- a/src/graphics/engine/camera.h +++ b/src/graphics/engine/camera.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// camera.h +/** + * \file graphics/engine/camera.h + * \brief Camera handling - Gfx::CCamera class + */ #pragma once diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index 676dfe8..881a598 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// cloud.h +/** + * \file graphics/engine/cloud.h + * \brief Cloud rendering - Gfx::CCloud class + */ #pragma once diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 8f9338a..c7ff084 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// engine.h +/** + * \file graphics/engine/engine.h + * \brief Main graphics engine - Gfx::CEngine class + */ #pragma once diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h index 8272125..52058c8 100644 --- a/src/graphics/engine/lightman.h +++ b/src/graphics/engine/lightman.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// lightman.h +/** + * \file graphics/engine/lightman.h + * \brief Dynamic light manager - Gfx::CLightManager class + */ #pragma once diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h index 9e854be..3b4e2cf 100644 --- a/src/graphics/engine/lightning.h +++ b/src/graphics/engine/lightning.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// lightning.h (aka blitz.h) +/** + * \file graphics/engine/lightning.h + * \brief Lightning rendering - Gfx::CLightning class (aka blitz) + */ #pragma once diff --git a/src/graphics/engine/modelfile.h b/src/graphics/engine/modelfile.h index 6a30487..fab190f 100644 --- a/src/graphics/engine/modelfile.h +++ b/src/graphics/engine/modelfile.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// modelfile.h (aka modfile.h) +/** + * \file graphics/engine/modelfile.h + * \brief Model loading - Gfx::CModelFile class (aka modfile) + */ #include "graphics/engine/engine.h" #include "graphics/core/vertex.h" diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index 89e2c5b..45396d2 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// particle.h (aka particule.h) +/** + * \file graphics/engine/particle.h + * \brief Particle rendering - Gfx::CParticle class (aka particule) + */ #pragma once diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 5ba318b..54d8b55 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// planet.h +/** + * \file graphics/engine/planet.h + * \brief Planet rendering - Gfx::CPlanet class + */ #pragma once diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h index 35b5c5f..768abf8 100644 --- a/src/graphics/engine/pyro.h +++ b/src/graphics/engine/pyro.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// pyro.h +/** + * \file graphics/engine/pyro.h + * \brief Fire effect rendering - Gfx::CPyro class + */ #pragma once diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index a198590..41d4bbb 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// terrain.h +/** + * \file graphics/engine/terrain.h + * \brief Terrain rendering - Gfx::CTerrain class + */ #pragma once diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 7e2f84b..24251ab 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// text.h +/** + * \file graphics/engine/text.h + * \brief Text rendering - Gfx::CText class + */ #pragma once diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index 245baf7..b051889 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// water.h +/** + * \file graphics/engine/water.h + * \brief Water rendering - Gfx::CWater class + */ #pragma once diff --git a/src/graphics/opengl/README.txt b/src/graphics/opengl/README.txt index 0aba0ed..596871d 100644 --- a/src/graphics/opengl/README.txt +++ b/src/graphics/opengl/README.txt @@ -1,6 +1,7 @@ -src/graphics/opengl - -OpenGL engine implementation - -Contains the concrete implementation using OpenGL of abstract CDevice class -from src/graphics/core +/** + * \dir graphics/opengl + * \brief OpenGL engine implementation + * + * Contains the concrete implementation using OpenGL of abstract CDevice class + * from src/graphics/core + */ \ No newline at end of file diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index a41c41c..dbe9a52 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// gldevice.h +/** + * \file graphics/opengl/gldevice.h + * \brief OpenGL implementation - Gfx::CGLDevice class + */ #pragma once -- cgit v1.2.3-1-g7c22 From b4b74c30e9aa93ae736db73df5cb0c5d508ec6ed Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 12 Aug 2012 10:45:04 +0200 Subject: Fixes & testing in CEngine - fixed bugs in settings modes, etc. - some additions and minor refactoring --- src/graphics/core/device.h | 7 +- src/graphics/engine/cloud.cpp | 5 +- src/graphics/engine/engine.cpp | 358 +++++++++++++++++++++++++++++---------- src/graphics/engine/engine.h | 35 +++- src/graphics/engine/text.cpp | 6 +- src/graphics/engine/water.cpp | 5 +- src/graphics/opengl/gldevice.cpp | 19 ++- src/graphics/opengl/gldevice.h | 2 + 8 files changed, 315 insertions(+), 122 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index a829c81..a3d0208 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -153,9 +153,9 @@ enum FogMode \brief Culling mode for polygons */ enum CullMode { - //! Cull clockwise side + //! Cull clockwise faces CULL_CW, - //! Cull counter-clockwise side + //! Cull counter-clockwise faces CULL_CCW }; @@ -278,6 +278,9 @@ class CDevice public: virtual ~CDevice() {} + //! Provides a hook to debug graphics code (implementation-specific) + virtual void DebugHook() = 0; + //! Initializes the device, setting the initial state virtual bool Create() = 0; //! Destroys the device, releasing every acquired resource diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index 71dd969..f3c0002 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -231,10 +231,7 @@ void Gfx::CCloud::Create(const std::string& fileName, m_fileName = fileName; if (! m_fileName.empty()) - { - m_engine->LoadTexture(m_fileName, 0); - m_engine->LoadTexture(m_fileName, 1); - } + m_engine->LoadTexture(m_fileName); if (m_terrain == nullptr) m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 0461636..644ecaf 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -115,6 +115,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_overColor = 0; m_overMode = ENG_RSTATE_TCOLOR_BLACK; m_highlightRank[0] = -1; // empty list + m_highlightTime = 0.0f; m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f); m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f); m_drawWorld = true; @@ -133,7 +134,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_lensMode = true; m_waterMode = true; m_skyMode = true; - m_backForce = true; + m_backForce = false; // TODO: change to true? m_planetMode = true; m_lightMode = true; m_editIndentMode = true; @@ -147,22 +148,22 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_updateGeometry = false; - m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 1.0f, 1.0f)); - m_mice[Gfx::ENG_MOUSE_WAIT] = Gfx::EngineMouse( 2, 3, 33, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 8.0f, 12.0f)); - m_mice[Gfx::ENG_MOUSE_HAND] = Gfx::EngineMouse( 4, 5, 34, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 7.0f, 2.0f)); - m_mice[Gfx::ENG_MOUSE_NO] = Gfx::EngineMouse( 6, 7, 35, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point(10.0f, 10.0f)); - m_mice[Gfx::ENG_MOUSE_EDIT] = Gfx::EngineMouse( 8, 9, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 6.0f, 10.0f)); - m_mice[Gfx::ENG_MOUSE_CROSS] = Gfx::EngineMouse(10, 11, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(10.0f, 10.0f)); - m_mice[Gfx::ENG_MOUSE_MOVEV] = Gfx::EngineMouse(12, 13, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 5.0f, 11.0f)); - m_mice[Gfx::ENG_MOUSE_MOVEH] = Gfx::EngineMouse(14, 15, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(11.0f, 5.0f)); - m_mice[Gfx::ENG_MOUSE_MOVED] = Gfx::EngineMouse(16, 17, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_MOVEI] = Gfx::EngineMouse(18, 19, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_MOVE] = Gfx::EngineMouse(20, 21, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(11.0f, 11.0f)); - m_mice[Gfx::ENG_MOUSE_TARGET] = Gfx::EngineMouse(22, 23, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(15.0f, 15.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLL] = Gfx::EngineMouse(24, 25, 43, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 2.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLR] = Gfx::EngineMouse(26, 27, 44, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(17.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLU] = Gfx::EngineMouse(28, 29, 45, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 2.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLD] = Gfx::EngineMouse(30, 31, 46, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 17.0f)); + m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 1.0f, 1.0f)); + m_mice[Gfx::ENG_MOUSE_WAIT] = Gfx::EngineMouse( 2, 3, 33, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 8.0f, 12.0f)); + m_mice[Gfx::ENG_MOUSE_HAND] = Gfx::EngineMouse( 4, 5, 34, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 7.0f, 2.0f)); + m_mice[Gfx::ENG_MOUSE_NO] = Gfx::EngineMouse( 6, 7, 35, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point(10.0f, 10.0f)); + m_mice[Gfx::ENG_MOUSE_EDIT] = Gfx::EngineMouse( 8, 9, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 6.0f, 10.0f)); + m_mice[Gfx::ENG_MOUSE_CROSS] = Gfx::EngineMouse(10, 11, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(10.0f, 10.0f)); + m_mice[Gfx::ENG_MOUSE_MOVEV] = Gfx::EngineMouse(12, 13, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 5.0f, 11.0f)); + m_mice[Gfx::ENG_MOUSE_MOVEH] = Gfx::EngineMouse(14, 15, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(11.0f, 5.0f)); + m_mice[Gfx::ENG_MOUSE_MOVED] = Gfx::EngineMouse(16, 17, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_MOVEI] = Gfx::EngineMouse(18, 19, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_MOVE] = Gfx::EngineMouse(20, 21, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(11.0f, 11.0f)); + m_mice[Gfx::ENG_MOUSE_TARGET] = Gfx::EngineMouse(22, 23, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(15.0f, 15.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLL] = Gfx::EngineMouse(24, 25, 43, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 2.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLR] = Gfx::EngineMouse(26, 27, 44, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(17.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLU] = Gfx::EngineMouse(28, 29, 45, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 2.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLD] = Gfx::EngineMouse(30, 31, 46, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 17.0f)); m_mouseSize = Math::Point(0.04f, 0.04f * (800.0f / 600.0f)); m_mousePos = Math::Point(0.5f, 0.5f); @@ -170,7 +171,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_mouseVisible = false; m_texPath = "textures/"; - m_defaultTexParams.format = Gfx::TEX_IMG_RGBA; + m_defaultTexParams.format = Gfx::TEX_IMG_RGB; m_defaultTexParams.mipmap = true; m_defaultTexParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR; m_defaultTexParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR; @@ -190,11 +191,6 @@ Gfx::CEngine::~CEngine() m_terrain = nullptr; } -std::string Gfx::CEngine::GetError() -{ - return m_error; -} - void Gfx::CEngine::SetDevice(Gfx::CDevice *device) { m_device = device; @@ -230,12 +226,12 @@ bool Gfx::CEngine::Create() m_text->SetDevice(m_device); if (! m_text->Create()) { - m_error = std::string("Error creating CText: ") + m_text->GetError(); + std::string error = m_text->GetError(); + GetLogger()->Error("Error creating CText: %s\n", error.c_str()); return false; } m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); m_device->SetShadeModel(Gfx::SHADE_SMOOTH); m_device->SetFillMode(Gfx::FILL_FILL); @@ -289,11 +285,7 @@ void Gfx::CEngine::ResetAfterDeviceChanged() bool Gfx::CEngine::ProcessEvent(const Event &event) { - if (event.type == EVENT_MOUSE_MOVE) - { - m_mousePos = event.mouseMove.pos; - } - else if (event.type == EVENT_KEY_DOWN) + if (event.type == EVENT_KEY_DOWN) { // !! Debug, to be removed later !! @@ -307,6 +299,37 @@ bool Gfx::CEngine::ProcessEvent(const Event &event) int index = static_cast(m_mouseType); m_mouseType = static_cast( (index + 1) % Gfx::ENG_MOUSE_COUNT ); } + else if (event.key.key == KEY(F3)) + { + m_backgroundQuarter = !m_backgroundQuarter; + if (m_backgroundQuarter) + { + m_backgroundFull = true; + m_backgroundName = "geneda.png"; + } + else + { + m_backgroundFull = false; + m_backgroundName = ""; + } + } + else if (event.key.key == KEY(F4)) + { + m_backForce = !m_backForce; + if (m_backForce) + { + m_backgroundColorDown = Gfx::Color(0.2f, 0.2f, 0.2f); + m_backgroundColorUp = Gfx::Color(0.8f, 0.8f, 0.8f); + } + else + { + m_backgroundColorDown = m_backgroundColorUp = Gfx::Color(0.0f, 0.0f, 0.0f); + } + } + } + else if (event.type == EVENT_FRAME) + { + m_highlightTime += event.rTime; } // By default, pass on all events @@ -954,10 +977,28 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); } + else if (state & Gfx::ENG_RSTATE_OPAQUE_TEXTURE) // opaque texture ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); // default operation + } + else if (state & Gfx::ENG_RSTATE_OPAQUE_COLOR) // opaque color ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + } else if (state & Gfx::ENG_RSTATE_TEXT) // font rendering? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); // TODO: depth test setting elsewhere! m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); @@ -1091,6 +1132,7 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) { + m_lastMaterial = mat; m_device->SetMaterial(mat); } @@ -1112,12 +1154,18 @@ void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) { + if (m_texBlacklist.find(texName) != m_texBlacklist.end()) + return Gfx::Texture(); // invalid texture + + // TODO: detect alpha channel? + CImage img; if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << img.GetError(); - m_error = str.str(); + std::string error = img.GetError(); + GetLogger()->Error("Couldn't load texture '%s': %s\n", texName.c_str(), error.c_str()); + GetLogger()->Error("Blacklisting texture '%s'\n", texName.c_str()); + m_texBlacklist.insert(texName); return Gfx::Texture(); // invalid texture } @@ -1125,9 +1173,10 @@ Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx:: if (! result.valid) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); - m_error = str.str(); + std::string error = m_device->GetError(); + GetLogger()->Error("Couldn't load texture '%s': %s\n", texName.c_str(), error.c_str()); + GetLogger()->Error("Blacklisting texture '%s'\n", texName.c_str()); + m_texBlacklist.insert(texName); return result; } @@ -1156,29 +1205,115 @@ void Gfx::CEngine::DestroyTexture(const std::string &texName) m_texNameMap.erase(it); } -bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +bool Gfx::CEngine::LoadTexture(const std::string& name) { + if (m_texBlacklist.find(name) != m_texBlacklist.end()) + return false; + std::map::iterator it = m_texNameMap.find(name); if (it != m_texNameMap.end()) - { - m_device->SetTexture(stage, (*it).second); return true; + + Gfx::Texture tex = CreateTexture(name); + return tex.valid; +} + +// TODO: create separate variables for 4 quarter names +void QuarterName(std::string& buffer, const std::string& name, int quarter) +{ + size_t pos = name.find('.'); + if (pos == std::string::npos) + { + buffer = name; + return; } - // TODO if not present... - return false; + buffer = name.substr(0, pos) + std::string(1, static_cast('a' + quarter)) + name.substr(pos); } bool Gfx::CEngine::LoadAllTextures() { - // TODO! - return true; + LoadTexture("text.png"); + LoadTexture("mouse.png"); + LoadTexture("button1.png"); + LoadTexture("button2.png"); + LoadTexture("button3.png"); + LoadTexture("effect00.png"); + LoadTexture("effect01.png"); + LoadTexture("effect02.png"); + LoadTexture("map.png"); + + if (! m_backgroundName.empty()) + { + if (m_backgroundQuarter) // image into 4 pieces? + { + for (int i = 0; i < 4; i++) + { + std::string name; + QuarterName(name, m_backgroundName, i); + LoadTexture(name); + } + } + else + { + LoadTexture(m_backgroundName); + } + } + + if (! m_foregroundName.empty()) + LoadTexture(m_foregroundName); + + m_planet->LoadTexture(); + + bool ok = true; + + /* TODO + D3DObjLevel1* p1; + D3DObjLevel2* p2; + int l1; + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + + if ( p2 == 0 || p2->texName1[0] != 0 ) + { + if ( !LoadTexture(p2->texName1) ) ok = false; + } + + if ( p2 == 0 || p2->texName2[0] != 0 ) + { + if ( !LoadTexture(p2->texName2) ) ok = false; + } + }*/ + + return ok; } bool Gfx::CEngine::SetTexture(const std::string& name, int stage) { - // TODO! - return true; + auto it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; + } + + if (! LoadTexture(name)) + { + m_device->SetTexture(stage, 0); // invalid texture + return false; + } + + it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; + } + + m_device->SetTexture(stage, 0); // invalid texture + return false; // should not happen normally } void Gfx::CEngine::SetLimitLOD(int rank, float limit) @@ -1364,7 +1499,6 @@ float Gfx::CEngine::GetFogStart(int rank) return m_fogStart[rank]; } - void Gfx::CEngine::SetBackground(const std::string& name, Gfx::Color up, Gfx::Color down, Gfx::Color cloudUp, Gfx::Color cloudDown, bool full, bool quarter) @@ -1391,12 +1525,12 @@ void Gfx::CEngine::GetBackground(std::string& name, Gfx::Color& up, Gfx::Color& quarter = m_backgroundQuarter; } -void Gfx::CEngine::SetForegroundImageName(const std::string& name) +void Gfx::CEngine::SetForegroundName(const std::string& name) { - if (! m_foregroundImageName.empty()) - DestroyTexture(m_foregroundImageName); + if (! m_foregroundName.empty()) + DestroyTexture(m_foregroundName); - m_foregroundImageName = name; + m_foregroundName = name; } void Gfx::CEngine::SetOverFront(bool front) @@ -1714,14 +1848,11 @@ void Gfx::CEngine::Render() // Begin the scene m_device->BeginScene(); - if (m_drawWorld) Draw3DScene(); - DrawInterface(); - // End the scene m_device->EndScene(); } @@ -2113,7 +2244,8 @@ void Gfx::CEngine::DrawInterface() void Gfx::CEngine::UpdateGroundSpotTextures() { - // TODO! + // TODO the original code modifying the textures is very complex, so stub for now + GetLogger()->Info("CEngine::UpdateGroundSpotTextures(): stub!\n"); } void Gfx::CEngine::DrawShadow() @@ -2131,7 +2263,7 @@ void Gfx::CEngine::DrawShadow() material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f); SetMaterial(material); - // TODO: wtf? + // TODO: create a separate texture SetTexture("text.png"); Math::Point ts, ti; @@ -2310,6 +2442,7 @@ void Gfx::CEngine::DrawShadow() m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); } +// STATUS: TESTED, VERIFIED void Gfx::CEngine::DrawBackground() { if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ? @@ -2323,12 +2456,13 @@ void Gfx::CEngine::DrawBackground() DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown); } - if (m_backForce || (m_skyMode && m_backgroundName[0] != 0) ) + if (m_backForce || (m_skyMode && !m_backgroundName.empty()) ) { DrawBackgroundImage(); // image } } +// STATUS: TESTED void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down) { Math::Point p1(0.0f, 0.5f); @@ -2341,12 +2475,7 @@ void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) }; - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - - SetState(Gfx::ENG_RSTATE_NORMAL); + SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR); m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); @@ -2364,6 +2493,7 @@ void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color AddStatisticTriangle(2); } +// Status: PART_TESTED void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name) { Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal @@ -2399,12 +2529,8 @@ void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, co v2 = v1+h; } - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - SetTexture(name); - SetState(Gfx::ENG_RSTATE_WRAP); + SetState(Gfx::ENG_RSTATE_OPAQUE_TEXTURE | Gfx::ENG_RSTATE_WRAP); m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); @@ -2422,18 +2548,7 @@ void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, co AddStatisticTriangle(2); } -void QuarterName(std::string& buffer, const std::string& name, int quarter) -{ - size_t pos = name.find('.'); - if (pos == std::string::npos) - { - buffer = name; - return; - } - - buffer = name.substr(0, pos) + std::string(1, static_cast('a' + quarter)) + name.substr(pos); -} - +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawBackgroundImage() { Math::Point p1, p2; @@ -2494,9 +2609,10 @@ void Gfx::CEngine::DrawPlanet() m_planet->Draw(); // draws the planets } +// Status: PART_TESTED void Gfx::CEngine::DrawForegroundImage() { - if (m_foregroundImageName.empty()) return; + if (m_foregroundName.empty()) return; Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal @@ -2518,11 +2634,7 @@ void Gfx::CEngine::DrawForegroundImage() Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) }; - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false ); - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - - SetTexture(m_foregroundImageName); + SetTexture(m_foregroundName); SetState(Gfx::ENG_RSTATE_CLAMP | Gfx::ENG_RSTATE_TTEXTURE_BLACK); m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); @@ -2533,6 +2645,7 @@ void Gfx::CEngine::DrawForegroundImage() AddStatisticTriangle(2); } +// Status: PART_TESTED void Gfx::CEngine::DrawOverColor() { if (! m_stateColor) return; @@ -2551,29 +2664,31 @@ void Gfx::CEngine::DrawOverColor() Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) }; + SetState(m_overMode); + + // TODO: set also with m_overMode ? m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - SetState(m_overMode); - m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); Gfx::VertexCol vertex[4] = { - Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1],color[2]), - Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0],color[2]), - Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1],color[2]), - Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0],color[2]) + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0], color[2]) }; m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); AddStatisticTriangle(2); } +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawHighlight() { Math::Point min, max; @@ -2609,9 +2724,63 @@ void Gfx::CEngine::DrawHighlight() m_highlight = true; } - // TODO: draw highlight! + if (! m_highlight) + return; + + Math::Point p1 = m_highlightP1; + Math::Point p2 = m_highlightP2; + + int nbOut = 0; + if (p1.x < 0.0f || p1.x > 1.0f) nbOut++; + if (p1.y < 0.0f || p1.y > 1.0f) nbOut++; + if (p2.x < 0.0f || p2.x > 1.0f) nbOut++; + if (p2.y < 0.0f || p2.y > 1.0f) nbOut++; + if (nbOut > 2) + return; + + SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR); + + float d = 0.5f+sinf(m_highlightTime*6.0f)*0.5f; + d *= (p2.x-p1.x)*0.1f; + p1.x += d; + p1.y += d; + p2.x -= d; + p2.y -= d; + + Gfx::Color color(1.0f, 1.0f, 0.0f); // yellow + + Gfx::VertexCol line[3] = + { + Gfx::VertexCol(Math::Vector(), color), + Gfx::VertexCol(Math::Vector(), color), + Gfx::VertexCol(Math::Vector(), color) + }; + + float dx = (p2.x - p1.x) / 5.0f; + float dy = (p2.y - p1.y) / 5.0f; + + line[0].coord = Math::Vector(p1.x, p1.y + dy, 0.0f); + line[1].coord = Math::Vector(p1.x, p1.y, 0.0f); + line[2].coord = Math::Vector(p1.x + dx, p1.y, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); + + line[0].coord = Math::Vector(p2.x - dx, p1.y, 0.0f); + line[1].coord = Math::Vector(p2.x, p1.y, 0.0f); + line[2].coord = Math::Vector(p2.x, p1.y + dy, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); + + line[0].coord = Math::Vector(p2.x, p2.y - dy, 0.0f); + line[1].coord = Math::Vector(p2.x, p2.y, 0.0f); + line[2].coord = Math::Vector(p2.x - dx, p2.y, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); + + line[0].coord = Math::Vector(p1.x + dx, p2.y, 0.0f); + line[1].coord = Math::Vector(p1.x, p2.y, 0.0f); + line[2].coord = Math::Vector(p1.x, p2.y - dy, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); } +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawMouse() { if (! m_mouseVisible) @@ -2647,6 +2816,7 @@ void Gfx::CEngine::DrawMouse() DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2); } +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) { if (icon == -1) @@ -2671,8 +2841,8 @@ void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) Gfx::Vertex vertex[4] = { Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), normal, Math::Point(u1, v2)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), normal, Math::Point(u2, v2)), Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), normal, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), normal, Math::Point(u2, v2)), Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), normal, Math::Point(u2, v1)) }; diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index c7ff084..5a64e4e 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -37,6 +37,7 @@ #include #include #include +#include class CApplication; @@ -78,7 +79,7 @@ struct EngineTriangle Gfx::VertexTex2 triangle[3]; //! Material Gfx::Material material; - //! Render state (TODO: ?) + //! Render state int state; //! 1st texture Gfx::Texture tex1; @@ -425,7 +426,11 @@ enum EngineRenderState //! The transparent color (white = no) ENG_RSTATE_TCOLOR_WHITE = (1<<17), //! Mode for rendering text - ENG_RSTATE_TEXT = (1<<18) + ENG_RSTATE_TEXT = (1<<18), + //! Only opaque texture, no blending, etc. + ENG_RSTATE_OPAQUE_TEXTURE = (1<<19), + //! Only opaque color, no texture, blending, etc. + ENG_RSTATE_OPAQUE_COLOR = (1<<20) }; @@ -532,9 +537,6 @@ public: CEngine(CInstanceManager* iMan, CApplication* app); ~CEngine(); - //! Returns the last error encountered - std::string GetError(); - //! Sets the device to be used void SetDevice(Gfx::CDevice* device); //! Returns the current device @@ -715,12 +717,21 @@ public: void SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, const Math::Vector& upVec, float eyeDistance); + //! Creates texture with the specified params Gfx::Texture CreateTexture(const std::string& texName, const Gfx::TextureCreateParams& params); + //! Creates texture Gfx::Texture CreateTexture(const std::string& texName); + + //! Destroys texture, unloading it and removing from cache void DestroyTexture(const std::string& texName); - bool LoadTexture(const std::string& name, int stage = 0); + + //! Loads texture, creating it if not already present + bool LoadTexture(const std::string& name); + //! Loads all necessary textures bool LoadAllTextures(); + + //! Sets texture for given stage; if not present in cache, the texture is loaded bool SetTexture(const std::string& name, int stage = 0); //@{ @@ -831,8 +842,8 @@ public: bool& full, bool& quarter); //@} - //! Specifies the foreground image - void SetForegroundImageName(const std::string& name); + //! Specifies the name of foreground texture + void SetForegroundName(const std::string& name); //! Specifies whether to draw the foreground void SetOverFront(bool front); //! Sets the foreground overlay color @@ -1129,7 +1140,7 @@ protected: bool m_overFront; Gfx::Color m_overColor; int m_overMode; - std::string m_foregroundImageName; + std::string m_foregroundName; bool m_drawWorld; bool m_drawFront; float m_limitLOD[2]; @@ -1156,6 +1167,8 @@ protected: int m_highlightRank[100]; //! Highlight visible? bool m_highlight; + //! Time counter for highlight animation + float m_highlightTime; //@{ //! Highlight rectangle points Math::Point m_highlightP1; @@ -1171,6 +1184,10 @@ protected: std::map m_texNameMap; //! Reverse map of loaded textures (by texture) std::map m_revTexNameMap; + //! Blacklist map of textures + /** Textures on this list were not successful in first loading, + * so are disabled for subsequent load calls. */ + std::set m_texBlacklist; //! Mouse cursor definitions Gfx::EngineMouse m_mice[Gfx::ENG_MOUSE_COUNT]; diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index 0a57026..82abd62 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -649,8 +649,8 @@ void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Poi Gfx::VertexCol quad[] = { Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), grad[3]), - Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), grad[0]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), grad[1]) }; @@ -688,8 +688,6 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math cf->cache[ch] = tex; } - m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); - Math::Point p1(pos.x, pos.y + tex.charSize.y - tex.texSize.y); Math::Point p2(pos.x + tex.texSize.x, pos.y + tex.charSize.y); @@ -698,8 +696,8 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math Gfx::Vertex quad[4] = { Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(0.0f, 1.0f)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(1.0f, 0.0f)) }; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 0ec52eb..8fbd1ae 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -519,10 +519,7 @@ void Gfx::CWater::Create(Gfx::WaterType type1, Gfx::WaterType type2, const std:: VaporFlush(); if (! m_fileName.empty()) - { - m_engine->LoadTexture(m_fileName, 0); - m_engine->LoadTexture(m_fileName, 1); - } + m_engine->LoadTexture(m_fileName); if (m_terrain == nullptr) m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 4c36053..caa79ee 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -73,6 +73,13 @@ Gfx::CGLDevice::~CGLDevice() { } +void Gfx::CGLDevice::DebugHook() +{ + /* This function is only called here, so it can be used + * as a breakpoint when debugging using gDEBugger */ + glColor3i(0, 0, 0); +} + std::string Gfx::CGLDevice::GetError() { return m_error; @@ -1172,17 +1179,19 @@ void Gfx::CGLDevice::GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float & void Gfx::CGLDevice::SetCullMode(Gfx::CullMode mode) { - if (mode == Gfx::CULL_CW) glCullFace(GL_CW); - else if (mode == Gfx::CULL_CCW) glCullFace(GL_CCW); + // Cull clockwise back faces, so front face is the opposite + // (assuming GL_CULL_FACE is GL_BACK) + if (mode == Gfx::CULL_CW ) glFrontFace(GL_CCW); + else if (mode == Gfx::CULL_CCW) glFrontFace(GL_CW); else assert(false); } Gfx::CullMode Gfx::CGLDevice::GetCullMode() { GLint flag = 0; - glGetIntegerv(GL_CULL_FACE, &flag); - if (flag == GL_CW) return Gfx::CULL_CW; - else if (flag == GL_CCW) return Gfx::CULL_CCW; + glGetIntegerv(GL_FRONT_FACE, &flag); + if (flag == GL_CW) return Gfx::CULL_CCW; + else if (flag == GL_CCW) return Gfx::CULL_CW; else assert(false); return Gfx::CULL_CW; } diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index dbe9a52..3daea8a 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -76,6 +76,8 @@ public: CGLDevice(const Gfx::GLDeviceConfig &config); virtual ~CGLDevice(); + virtual void DebugHook(); + virtual std::string GetError(); virtual bool Create(); -- cgit v1.2.3-1-g7c22