diff options
author | Piotr Dziwinski <piotrdz@gmail.com> | 2012-08-10 23:31:42 +0200 |
---|---|---|
committer | Piotr Dziwinski <piotrdz@gmail.com> | 2012-08-10 23:31:42 +0200 |
commit | 63257034c946d40fb3ecc73a9ee3dc9d1e0a1e34 (patch) | |
tree | aa1fcf2928e2c9d5f89022242fbe3ff6d7d64bbb /src/graphics/engine/engine.cpp | |
parent | c3ab23ac9dc02d59180f2f1af5f3aa5b50f9f8d8 (diff) | |
download | colobot-63257034c946d40fb3ecc73a9ee3dc9d1e0a1e34.tar.gz colobot-63257034c946d40fb3ecc73a9ee3dc9d1e0a1e34.tar.bz2 colobot-63257034c946d40fb3ecc73a9ee3dc9d1e0a1e34.zip |
Partial CEngine implementation
- added rewritten implementation for basic modesetting in CEngine
- started rewriting proper rendering and object handling in CEngine
Diffstat (limited to 'src/graphics/engine/engine.cpp')
-rw-r--r-- | src/graphics/engine/engine.cpp | 2236 |
1 files changed, 1996 insertions, 240 deletions
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,70 +295,598 @@ 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<int>(m_mouseType); + m_mouseType = static_cast<Gfx::EngineMouseType>( (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<CSoundInterface*>( 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<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(texName); - if (it == m_texNameMap.end()) - return; + /* TODO! + m_baseTime = timeGetTime(); + m_lastTime = 0; + m_absTime = 0.0f;*/ +} - std::map<Gfx::Texture, std::string>::iterator revIt = m_revTexNameMap.find((*it).second); +void Gfx::CEngine::TimeEnterGel() +{ + /* TODO! + m_stopTime = timeGetTime();*/ +} - m_device->DestroyTexture((*it).second); +void Gfx::CEngine::TimeExitGel() +{ + /* TODO! + m_baseTime += timeGetTime() - m_stopTime;*/ +} - m_revTexNameMap.erase(revIt); - m_texNameMap.erase(it); +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; } -void Gfx::CEngine::SetTexture(const std::string &name, int stage) +bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height) { - std::map<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(name); - if (it != m_texNameMap.end()) - m_device->SetTexture(stage, (*it).second); + // TODO! + return true; +} - // TODO if not present... +bool Gfx::CEngine::ReadSettings() +{ + // TODO! + return true; } -void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) +bool Gfx::CEngine::WriteSettings() { - m_device->SetMaterial(mat); + // TODO! + return true; +} + +void Gfx::CEngine::SetPause(bool pause) +{ + m_pause = pause; +} + +bool Gfx::CEngine::GetPause() +{ + return m_pause; +} + +void Gfx::CEngine::SetMovieLock(bool lock) +{ + m_movieLock = lock; +} + +bool Gfx::CEngine::GetMovieLock() +{ + return m_movieLock; +} + +void Gfx::CEngine::SetShowStats(bool show) +{ + m_showStats = show; +} + +bool Gfx::CEngine::GetShowStats() +{ + return m_showStats; +} + +void Gfx::CEngine::SetRenderEnable(bool enable) +{ + m_render = enable; +} + +Math::IntSize Gfx::CEngine::GetWindowSize() +{ + return m_size; +} + +Math::IntSize Gfx::CEngine::GetLastWindowSize() +{ + return m_lastSize; +} + +Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) +{ + return Math::Point( static_cast<float>(pos.x) / static_cast<float>(m_size.w), + 1.0f - static_cast<float>(pos.y) / static_cast<float>(m_size.h) ); +} + +Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +{ + return Math::IntPoint(static_cast<int>(pos.x * m_size.w), + static_cast<int>((1.0f - pos.y) * m_size.h)); +} + +Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +{ + return Math::Size( static_cast<float>(size.w) / static_cast<float>(m_size.w), + static_cast<float>(size.h) / static_cast<float>(m_size.h) ); +} + +Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +{ + return Math::IntSize(static_cast<int>(size.w * m_size.w), + static_cast<int>(size.h * m_size.h)); +} + +std::string Gfx::CEngine::GetTextureDir() +{ + return m_texPath; +} + +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; } -void Gfx::CEngine::SetState(int state, Gfx::Color color) +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; @@ -545,227 +1093,519 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color) m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); } -bool Gfx::CEngine::ProcessEvent(const Event &event) +void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) { - if (event.type == EVENT_MOUSE_MOVE) + 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<CSoundInterface*>( 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))) { - m_mousePos = event.mouseMove.pos; + std::stringstream str; + str << "Couldn't load texture '" << texName << "': " << img.GetError(); + m_error = str.str(); + return Gfx::Texture(); // invalid texture } - else if (event.type == EVENT_KEY_DOWN) + + Gfx::Texture result = m_device->CreateTexture(&img, params); + + if (! result.valid) { - // !! Debug, to be removed later !! + std::stringstream str; + str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); + m_error = str.str(); + return result; + } - 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<int>(m_mouseType); - m_mouseType = static_cast<Gfx::EngineMouseType>( (index + 1) % Gfx::ENG_MOUSE_COUNT ); - } + 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<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(texName); + if (it == m_texNameMap.end()) + return; + + std::map<Gfx::Texture, std::string>::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<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; } - // By default, pass on all events + // TODO if not present... + return false; +} + +bool Gfx::CEngine::LoadAllTextures() +{ + // TODO! return true; } -bool Gfx::CEngine::Render() +bool Gfx::CEngine::SetTexture(const std::string& name, int stage) { - m_statisticTriangle = 0; + // TODO! + return true; +} - m_lastState = -1; - SetState(Gfx::ENG_RSTATE_NORMAL); +void Gfx::CEngine::SetLimitLOD(int rank, float limit) +{ + m_limitLOD[rank] = limit; +} - m_device->BeginScene(); +float Gfx::CEngine::GetLimitLOD(int rank, bool last) +{ + float limit = 0.0f; - SetUp3DView(); + 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 (! Draw3DScene() ) - return false; + if (limit < 0.0f) limit = 0.0f; - SetUpInterfaceView(); + return limit; +} - if (! DrawInterface() ) - return false; +void Gfx::CEngine::SetTerrainVision(float vision) +{ + m_terrainVision = vision; +} - m_device->EndScene(); +void Gfx::CEngine::SetFocus(float focus) +{ + m_focus = focus; + m_size = m_app->GetVideoConfig().size; - return true; + float aspect = (static_cast<float>(m_size.h)) / m_size.w; + Math::LoadProjectionMatrix(m_matProj, m_focus, aspect, 0.5f, m_deepView[0]); } -void Gfx::CEngine::SetUp3DView() +float Gfx::CEngine::GetFocus() { - // TODO + return m_focus; } -bool Gfx::CEngine::Draw3DScene() +void Gfx::CEngine::SetGroundSpot(bool mode) { - // TODO - return true; + m_groundSpotVisible = mode; } -void Gfx::CEngine::SetUpInterfaceView() +bool Gfx::CEngine::GetGroundSpot() { - m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); - m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); - m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + return m_groundSpotVisible; } -bool Gfx::CEngine::DrawInterface() +void Gfx::CEngine::SetShadow(bool mode) { - 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)) - }; + m_shadowVisible = mode; +} + +bool Gfx::CEngine::GetShadow() +{ + return m_shadowVisible; +} - m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, vertices, 3); +void Gfx::CEngine::SetDirty(bool mode) +{ + m_dirty = mode; +} - DrawMouse(); +bool Gfx::CEngine::GetDirty() +{ + return m_dirty; +} - std::vector<Gfx::FontMetaChar> 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); +void Gfx::CEngine::SetFog(bool mode) +{ + m_fog = mode; +} - 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); +bool Gfx::CEngine::GetFog() +{ + return m_fog; +} - return true; +bool Gfx::CEngine::GetStateColor() +{ + return m_stateColor; } -Math::IntSize Gfx::CEngine::GetWindowSize() +void Gfx::CEngine::SetSecondTexture(int texNum) { - return m_size; + m_secondTexNum = texNum; } -Math::IntSize Gfx::CEngine::GetLastWindowSize() +int Gfx::CEngine::GetSecondTexture() { - return m_lastSize; + return m_secondTexNum; } -/** 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) +void Gfx::CEngine::SetRankView(int rank) { - return Math::Point( static_cast<float>(pos.x) / static_cast<float>(m_size.w), - 1.0f - static_cast<float>(pos.y) / static_cast<float>(m_size.h) ); + 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; } -Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +int Gfx::CEngine::GetRankView() { - return Math::IntPoint(static_cast<int>(pos.x * m_size.w), - static_cast<int>((1.0f - pos.y) * m_size.h)); + return m_rankView; } -Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +void Gfx::CEngine::SetDrawWorld(bool draw) { - return Math::Size( static_cast<float>(size.w) / static_cast<float>(m_size.w), - static_cast<float>(size.h) / static_cast<float>(m_size.h) ); + m_drawWorld = draw; } -Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +void Gfx::CEngine::SetDrawFront(bool draw) { - return Math::IntSize(static_cast<int>(size.w * m_size.w), - static_cast<int>(size.h * m_size.h)); + m_drawFront = draw; } -std::string Gfx::CEngine::GetTextureDir() +void Gfx::CEngine::SetAmbientColor(const Gfx::Color& color, int rank) { - return m_texPath; + m_ambientColor[rank] = color; } -void Gfx::CEngine::DrawMouse() +Gfx::Color Gfx::CEngine::GetAmbientColor(int rank) { - if (! m_mouseVisible) - return; + return m_ambientColor[rank]; +} - if (m_app->GetSystemMouseVisibile()) - return; +void Gfx::CEngine::SetWaterAddColor(const Gfx::Color& color) +{ + m_waterAddColor = color; +} - Gfx::Material material; - material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); - material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f); +Gfx::Color Gfx::CEngine::GetWaterAddColor() +{ + return m_waterAddColor; +} - m_device->SetMaterial(material); - m_device->SetTexture(0, m_miceTexture); +void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) +{ + m_fogColor[rank] = color; +} - int index = static_cast<int>(m_mouseType); +Gfx::Color Gfx::CEngine::GetFogColor(int rank) +{ + return m_fogColor[rank]; +} - Math::Point pos = m_mousePos; - pos.x = m_mousePos.x - (m_mice[index].hotPoint.x * m_mouseSize.x) / 32.0f; - pos.y = m_mousePos.y - ((32.0f - m_mice[index].hotPoint.y) * m_mouseSize.y) / 32.0f; +void Gfx::CEngine::SetDeepView(float length, int rank, bool ref) +{ + if (ref) + length *= m_clippingDistance; - Math::Point shadowPos; - shadowPos.x = pos.x + (4.0f/800.0f); - shadowPos.y = pos.y - (3.0f/600.0f); + m_deepView[rank] = length; +} - SetState(Gfx::ENG_RSTATE_TCOLOR_WHITE); - DrawMouseSprite(shadowPos, m_mouseSize, m_mice[index].iconShadow); +float Gfx::CEngine::GetDeepView(int rank) +{ + return m_deepView[rank]; +} - SetState(m_mice[index].mode1); - DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon1); +void Gfx::CEngine::SetFogStart(float start, int rank) +{ + m_fogStart[rank] = start; +} - SetState(m_mice[index].mode2); - DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2); +float Gfx::CEngine::GetFogStart(int rank) +{ + return m_fogStart[rank]; } -void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) + +void Gfx::CEngine::SetBackground(const std::string& name, Gfx::Color up, Gfx::Color down, + Gfx::Color cloudUp, Gfx::Color cloudDown, + bool full, bool quarter) { - if (icon == -1) - return; + m_backgroundName = name; + m_backgroundColorUp = up; + m_backgroundColorDown = down; + m_backgroundCloudUp = cloudUp; + m_backgroundCloudDown = cloudDown; + m_backgroundFull = full; + m_backgroundQuarter = quarter; +} - Math::Point p1 = pos; - Math::Point p2 = p1 + size; +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; +} - float u1 = (32.0f / 256.0f) * (icon % 8); - float v1 = (32.0f / 256.0f) * (icon / 8); - float u2 = u1 + (32.0f / 256.0f); - float v2 = v1 + (32.0f / 256.0f); +void Gfx::CEngine::SetForegroundImageName(const std::string& name) +{ + if (! m_foregroundImageName.empty()) + DestroyTexture(m_foregroundImageName); - float dp = 0.5f / 256.0f; - u1 += dp; - v1 += dp; - u2 -= dp; - v2 -= dp; + m_foregroundImageName = name; +} - Math::Vector normal(0.0f, 0.0f, -1.0f); +void Gfx::CEngine::SetOverFront(bool front) +{ + m_overFront = front; +} - Gfx::Vertex vertex[4] = +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) { - 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, p2.y, 0.0f), normal, Math::Point(u2, v1)) - }; + m_textureQuality = value; + LoadAllTextures(); + } +} - m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); - AddStatisticTriangle(2); +int Gfx::CEngine::GetTextureQuality() +{ + return m_textureQuality; } -bool Gfx::CEngine::GetPause() +void Gfx::CEngine::SetTotoMode(bool present) { - return m_pause; + m_totoMode = present; } -Math::Vector Gfx::CEngine::GetLookatPt() +bool Gfx::CEngine::GetTotoMode() { - return m_lookatPt; + return m_totoMode; } -Math::Vector Gfx::CEngine::GetEyePt() +void Gfx::CEngine::SetLensMode(bool present) { - return m_eyePt; + 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) @@ -798,133 +1638,1049 @@ Gfx::EngineMouseType Gfx::CEngine::GetMouseType() return m_mouseType; } -void Gfx::CEngine::AddStatisticTriangle(int count) +const Math::Matrix& Gfx::CEngine::GetMatView() { - m_statisticTriangle += count; + return m_matView; } -void Gfx::CEngine::SetShowStat(bool show) +Math::Vector Gfx::CEngine::GetEyePt() { - m_showStats = show; + return m_eyePt; } -bool Gfx::CEngine::GetShowStat() +Math::Vector Gfx::CEngine::GetLookatPt() { - return m_showStats; + return m_lookatPt; } -void Gfx::CEngine::SetFocus(float focus) +float Gfx::CEngine::GetEyeDirH() { - m_focus = focus; + return m_eyeDirH; } - -void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) +float Gfx::CEngine::GetEyeDirV() { - // TODO! + return m_eyeDirV; } -void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) +bool Gfx::CEngine::IsVisiblePoint(const Math::Vector &pos) { - // TODO! + return Math::Distance(m_eyePt, pos) <= m_deepView[0]; } -Gfx::Color Gfx::CEngine::GetFogColor(int rank) +void Gfx::CEngine::UpdateMatProj() { - // TODO! - return Gfx::Color(); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); } -void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, - const Math::Vector& upVec, float eyeDistance) +void Gfx::CEngine::ApplyChange() { - // TODO! + m_deepView[0] /= m_lastClippingDistance; + m_deepView[1] /= m_lastClippingDistance; + + SetFocus(m_focus); + ChangeLOD(); + + m_deepView[0] *= m_clippingDistance; + m_deepView[1] *= m_clippingDistance; } -void Gfx::CEngine::SetRankView(int rank) + + +/******************************************************* + Rendering + *******************************************************/ + + + +/** + This function sets up render states, clears the + viewport, and renders the scene. */ +void Gfx::CEngine::Render() { - m_rankView = rank; + /* 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(); + } + + + DrawInterface(); + + // End the scene + m_device->EndScene(); } -float Gfx::CEngine::GetEyeDirH() +void Gfx::CEngine::Draw3DScene() { - return m_eyeDirH; + 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) + { + // Draw the field + // TODO! + /* + p1 = m_objectPointer; + for ( l1=0 ; l1<p1->totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2<p2->totalUsed ; 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 ; l3<p3->totalUsed ; 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 ; l4<p4->totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5<p5->totalUsed ; 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(); + } + + // Draw objects + bool transparent = false; + /* TODO! + p1 = m_objectPointer; + for ( l1=0 ; l1<p1->totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2<p2->totalUsed ; 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 ; l3<p3->totalUsed ; 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 ; l4<p4->totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5<p5->totalUsed ; 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; + } + } + } + } + } + }*/ + + 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 ; l1<p1->totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2<p2->totalUsed ; 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 ; l3<p3->totalUsed ; 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 ; l4<p4->totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5<p5->totalUsed ; 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; + } + } + } + } + } + } */ + } + + 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 } -float Gfx::CEngine::GetEyeDirV() +void Gfx::CEngine::DrawInterface() { - return m_eyeDirV; + 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<CInterface*>( 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); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matView); + + // 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 ; l2<p2->totalUsed ; 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 ; l3<p3->totalUsed ; 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 ; l4<p4->totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5<p5->totalUsed ; 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); + + 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(); } -float Gfx::CEngine::GetClippingDistance() +void Gfx::CEngine::UpdateGroundSpotTextures() { - return m_clippingDistance; + // TODO! } -bool Gfx::CEngine::GetGroundSpot() +void Gfx::CEngine::DrawShadow() { - return m_groundSpotVisible; + 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<int>( m_shadow.size() ); i++) + { + 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); + } + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); } -void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) +void Gfx::CEngine::DrawBackground() { - m_terrain = terrain; + if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ? + { + if (m_backgroundCloudUp != m_backgroundCloudDown) // degraded? + DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown); + } + else + { + if (m_backgroundColorUp != m_backgroundColorDown) // degraded? + DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown); + } + + if (m_backForce || (m_skyMode && m_backgroundName[0] != 0) ) + { + DrawBackgroundImage(); // image + } } -void Gfx::CEngine::SetTerrainVision(float vision) +void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down) { - // TODO! + Math::Point p1(0.0f, 0.5f); + Math::Point p2(1.0f, 1.0f); + + Gfx::Color color[3] = + { + 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] = + { + 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); } -bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name) { - // TODO! - return true; + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal + + float u1, u2, v1, v2; + if (m_backgroundFull) + { + 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 + { + 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; + } + + 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); } -float Gfx::CEngine::ParticleAdapt(float factor) +void QuarterName(std::string& buffer, const std::string& name, int quarter) { - // TODO! - return 0.0f; + size_t pos = name.find('.'); + if (pos == std::string::npos) + { + buffer = name; + return; + } + + buffer = name.substr(0, pos) + std::string(1, static_cast<char>('a' + quarter)) + name.substr(pos); } -bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) +void Gfx::CEngine::DrawBackgroundImage() { - // TODO! - return true; + 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); + } } -bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) +void Gfx::CEngine::DrawPlanet() { - // TODO! - return true; + if (! m_planet->PlanetExist()) return; + + 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->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + m_planet->Draw(); // draws the planets } -int Gfx::CEngine::CreateObject() +void Gfx::CEngine::DrawForegroundImage() { - // TODO! - return 0; + if (m_foregroundImageName.empty()) return; + + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal + + Math::Point p1(0.0f, 0.0f); + Math::Point p2(1.0f, 1.0f); + + float u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f; + float u2 = u1+0.50f; + + float v1 = 0.2f; + float v2 = 1.0f; + + + 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->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::DeleteObject(int objRank) +void Gfx::CEngine::DrawOverColor() { - // TODO! - return true; + if (! m_stateColor) return; + + // 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; + + Math::Point p1(0.0f, 0.0f); + Math::Point p2(1.0f, 1.0f); + + Gfx::Color color[3] = + { + m_overColor, + m_overColor, + 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(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]) + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table) +void Gfx::CEngine::DrawHighlight() { - // TODO! - return 0; + 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); + } + } + + 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; + } + + // TODO: draw highlight! } -bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate) +void Gfx::CEngine::DrawMouse() { - // TODO! - return false; + if (! m_mouseVisible) + return; + + if (m_app->GetSystemMouseVisibile()) + return; + + Gfx::Material material; + material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); + material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f); + + m_device->SetMaterial(material); + m_device->SetTexture(0, m_miceTexture); + + int index = static_cast<int>(m_mouseType); + + Math::Point pos = m_mousePos; + pos.x = m_mousePos.x - (m_mice[index].hotPoint.x * m_mouseSize.x) / 32.0f; + pos.y = m_mousePos.y - ((32.0f - m_mice[index].hotPoint.y) * m_mouseSize.y) / 32.0f; + + Math::Point shadowPos; + shadowPos.x = pos.x + (4.0f/800.0f); + shadowPos.y = pos.y - (3.0f/600.0f); + + SetState(Gfx::ENG_RSTATE_TCOLOR_WHITE); + DrawMouseSprite(shadowPos, m_mouseSize, m_mice[index].iconShadow); + + SetState(m_mice[index].mode1); + DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon1); + + SetState(m_mice[index].mode2); + DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2); } -void Gfx::CEngine::Update() +void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) { - // TODO! + if (icon == -1) + return; + + Math::Point p1 = pos; + Math::Point p2 = p1 + size; + + float u1 = (32.0f / 256.0f) * (icon % 8); + float v1 = (32.0f / 256.0f) * (icon / 8); + float u2 = u1 + (32.0f / 256.0f); + float v2 = v1 + (32.0f / 256.0f); + + float dp = 0.5f / 256.0f; + u1 += dp; + v1 += dp; + u2 -= dp; + v2 -= dp; + + Math::Vector normal(0.0f, 0.0f, -1.0f); + + 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, p2.y, 0.0f), normal, Math::Point(u2, v1)) + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } |