diff options
Diffstat (limited to 'src/graphics/engine/engine.cpp')
-rw-r--r-- | src/graphics/engine/engine.cpp | 2718 |
1 files changed, 2413 insertions, 305 deletions
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index e544ee3..644ecaf 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -25,7 +25,19 @@ #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" +#include "sound/sound.h" + // Initial size of various vectors const int OBJECT_PREALLOCATE_COUNT = 1200; @@ -40,32 +52,35 @@ 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; 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; - m_lastTime = 0; - m_absTime = 0.0f; + m_rankView = 0; m_ambientColor[0] = Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f); @@ -99,15 +114,15 @@ 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_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; 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; @@ -119,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; @@ -131,33 +146,24 @@ 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)); - 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); @@ -165,185 +171,721 @@ 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; 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() { - m_iMan = NULL; - m_app = NULL; - m_device = NULL; + m_iMan = nullptr; + m_app = nullptr; + m_device = nullptr; + m_sound = nullptr; + m_terrain = nullptr; +} - m_sound = NULL; - m_terrain = NULL; +void Gfx::CEngine::SetDevice(Gfx::CDevice *device) +{ + m_device = device; } -bool Gfx::CEngine::GetWasInit() +Gfx::CDevice* Gfx::CEngine::GetDevice() +{ + return m_device; +} + +void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) { - return m_wasInit; + m_terrain = terrain; } -std::string Gfx::CEngine::GetError() +Gfx::CText* Gfx::CEngine::GetText() { - return m_error; + return m_text; } 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); 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()) + { + 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->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); + 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; 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_planet = nullptr; +} - m_wasInit = false; +void Gfx::CEngine::ResetAfterDeviceChanged() +{ + // TODO reload textures, reset device state, etc. } -void Gfx::CEngine::SetDevice(Gfx::CDevice *device) +bool Gfx::CEngine::ProcessEvent(const Event &event) { - m_device = device; + 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<int>(m_mouseType); + m_mouseType = static_cast<Gfx::EngineMouseType>( (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 + return true; } -Gfx::CDevice* Gfx::CEngine::GetDevice() +void Gfx::CEngine::FrameMove(float rTime) { - return m_device; + m_lightMan->UpdateProgression(rTime); + m_particle->FrameParticle(rTime); + ComputeDistance(); + UpdateGeometry(); + + if (m_groundMark.draw) + { + 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; + } + } + } + + if (m_sound == nullptr) + m_sound = static_cast<CSoundInterface*>( m_iMan->SearchInstance(CLASS_SOUND) ); + + m_sound->FrameMove(rTime); } -bool Gfx::CEngine::AfterDeviceSetInit() +void Gfx::CEngine::StepSimulation(float rTime) { - m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); + m_app->StepSimulation(rTime); +} - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); +bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height) +{ + // TODO! + return true; +} - 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); +bool Gfx::CEngine::ReadSettings() +{ + // TODO! + return true; +} +bool Gfx::CEngine::WriteSettings() +{ + // TODO! return true; } -void Gfx::CEngine::ResetAfterDeviceChanged() +void Gfx::CEngine::SetPause(bool pause) { - // TODO + m_pause = pause; } +bool Gfx::CEngine::GetPause() +{ + return m_pause; +} -Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) +void Gfx::CEngine::SetMovieLock(bool lock) { - CImage img; - if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) + 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::IntPoint Gfx::CEngine::GetWindowSize() +{ + return m_size; +} + +Math::IntPoint 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.x), + 1.0f - static_cast<float>(pos.y) / static_cast<float>(m_size.y) ); +} + +Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +{ + return Math::IntPoint(static_cast<int>(pos.x * m_size.x), + static_cast<int>((1.0f - pos.y) * m_size.y)); +} + +Math::Point Gfx::CEngine::WindowToInterfaceSize(Math::IntPoint size) +{ + return Math::Point(static_cast<float>(size.x) / static_cast<float>(m_size.x), + static_cast<float>(size.y) / static_cast<float>(m_size.y)); +} + +Math::IntPoint Gfx::CEngine::InterfaceToWindowSize(Math::Point size) +{ + return Math::IntPoint(static_cast<int>(size.x * m_size.x), + static_cast<int>(size.y * m_size.y)); +} + +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; +} + +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 ) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << img.GetError(); - m_error = str.str(); - return Gfx::Texture(); // invalid texture + m_highlightRank[i++] = *rankList++; } + m_highlightRank[i] = -1; // terminator +} - Gfx::Texture result = m_device->CreateTexture(&img, params); +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; - if (! result.valid) + for (int i = 0; i < 8; i++) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); - m_error = str.str(); - return result; + 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; + } } - m_texNameMap[texName] = result; - m_revTexNameMap[result] = texName; + if ( min.x == 1000000.0f || + min.y == 1000000.0f || + max.x == -1000000.0f || + max.y == -1000000.0f ) return false; - return result; + return true; } -Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName) +void Gfx::CEngine::GroundSpotFlush() { - return CreateTexture(texName, m_defaultTexParams); + // TODO } -void Gfx::CEngine::DestroyTexture(const std::string &texName) +int Gfx::CEngine::GroundSpotCreate() { - std::map<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(texName); - if (it == m_texNameMap.end()) - return; + // TODO! + return 0; +} - std::map<Gfx::Texture, std::string>::iterator revIt = m_revTexNameMap.find((*it).second); +void Gfx::CEngine::GroundSpotDelete(int rank) +{ + // TODO! +} - m_device->DestroyTexture((*it).second); +bool Gfx::CEngine::SetObjectGroundSpotPos(int rank, const Math::Vector& pos) +{ + // TODO! + return true; +} - m_revTexNameMap.erase(revIt); - m_texNameMap.erase(it); +bool Gfx::CEngine::SetObjectGroundSpotRadius(int rank, float radius) +{ + // TODO! + return true; } -void Gfx::CEngine::SetTexture(const std::string &name, int stage) +bool Gfx::CEngine::SetObjectGroundSpotColor(int rank, const Gfx::Color& color) { - 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::SetObjectGroundSpotMinMax(int rank, float min, float max) +{ + // TODO! + return true; } -void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) +bool Gfx::CEngine::SetObjectGroundSpotSmooth(int rank, float smooth) { - m_device->SetMaterial(mat); + // 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; } -void Gfx::CEngine::SetState(int state, Gfx::Color color) +bool Gfx::CEngine::IsVisible(int objRank) { - if ( state == m_lastState && color == m_lastColor ) + // TODO! + return true; +} + +bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D) +{ + 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; +} + + + +/******************************************************* + 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) ) + if (m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA)) { state &= ~Gfx::ENG_RSTATE_ALPHA; @@ -351,120 +893,168 @@ void Gfx::CEngine::SetState(int state, 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); + } + else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? + { + 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, 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->SetTextureFactor(color.Inverse()); m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + m_device->SetTextureStageParams(0, params); } - else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? + else if (state & Gfx::ENG_RSTATE_OPAQUE_TEXTURE) // opaque texture ? { - /*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->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->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + 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_ALPHA) // image with alpha channel? + else if (state & Gfx::ENG_RSTATE_OPAQUE_COLOR) // opaque color ? { - /*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);*/ + 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 // normal ? + else if (state & Gfx::ENG_RSTATE_TEXT) // font rendering? + { + 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, 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 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->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->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->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, params); } if (state & Gfx::ENG_RSTATE_FOG) @@ -476,21 +1066,25 @@ void Gfx::CEngine::SetState(int state, 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 { @@ -499,18 +1093,25 @@ void Gfx::CEngine::SetState(int state, 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) @@ -529,90 +1130,1657 @@ 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_lastMaterial = 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<CSoundInterface*>( m_iMan->SearchInstance(CLASS_SOUND) ); + + m_sound->SetListener(eyePt, lookatPt); +} + +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))) { - m_mousePos = event.mouseMove.pos; + 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 } - else if (event.type == EVENT_KEY_DOWN) + + Gfx::Texture result = m_device->CreateTexture(&img, params); + + if (! result.valid) { - // !! Debug, to be removed later !! + 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; + } - if (event.key.key == KEY(F1)) + 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) +{ + if (m_texBlacklist.find(name) != m_texBlacklist.end()) + return false; + + std::map<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + 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; + } + + buffer = name.substr(0, pos) + std::string(1, static_cast<char>('a' + quarter)) + name.substr(pos); +} + +bool Gfx::CEngine::LoadAllTextures() +{ + 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? { - m_mouseVisible = !m_mouseVisible; - m_app->SetSystemMouseVisible(! m_app->GetSystemMouseVisibile()); + for (int i = 0; i < 4; i++) + { + std::string name; + QuarterName(name, m_backgroundName, i); + LoadTexture(name); + } } - else if (event.key.key == KEY(F2)) + else { - int index = static_cast<int>(m_mouseType); - m_mouseType = static_cast<Gfx::EngineMouseType>( (index + 1) % Gfx::ENG_MOUSE_COUNT ); + LoadTexture(m_backgroundName); } } - // By default, pass on all events - return true; + 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 ; l1<p1->totalUsed ; 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::Render() +bool Gfx::CEngine::SetTexture(const std::string& name, int stage) { - m_statisticTriangle = 0; + 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) +{ + 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.x/640.0f; // limit further if large window! + limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f); + } + else + { + limit = m_limitLOD[rank]; + limit *= m_size.x/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<float>(m_size.y)) / m_size.x; + 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::SetForegroundName(const std::string& name) +{ + if (! m_foregroundName.empty()) + DestroyTexture(m_foregroundName); + + m_foregroundName = 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; +} + +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() +{ + if (! m_render) return; + + m_statisticTriangle = 0; m_lastState = -1; - SetState(Gfx::ENG_RSTATE_NORMAL); + m_lastColor = 999; + m_lastMaterial = Gfx::Material(); - m_device->BeginScene(); + m_lightMan->UpdateLights(); - SetUp3DView(); + Gfx::Color color; + if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds? + color = m_backgroundCloudDown; + else + color = m_backgroundColorDown; - if (! Draw3DScene() ) - return false; + m_device->SetClearColor(color); + + // Begin the scene + m_device->BeginScene(); - SetUpInterfaceView(); + if (m_drawWorld) + Draw3DScene(); - if (! DrawInterface() ) - return false; + DrawInterface(); + // End the scene m_device->EndScene(); +} - return true; +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(); + + 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 } -void Gfx::CEngine::SetUp3DView() +void Gfx::CEngine::DrawInterface() { - // TODO + 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(); } -bool Gfx::CEngine::Draw3DScene() +void Gfx::CEngine::UpdateGroundSpotTextures() { - // TODO - return true; + // TODO the original code modifying the textures is very complex, so stub for now + GetLogger()->Info("CEngine::UpdateGroundSpotTextures(): stub!\n"); } -void Gfx::CEngine::SetUpInterfaceView() +void Gfx::CEngine::DrawShadow() { - 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); + + 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: create a separate texture + 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_shadows.size() ); i++) + { + if (m_shadows[i].hide) continue; + + 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? + + 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_shadows[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_shadows[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_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_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_shadows[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_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_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_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_shadows[i].angle, Math::Point(-radius, -radius)); + corner[3].x = rot.x; + corner[3].z = rot.y; + corner[3].y = 0.0f; + + if (m_shadows[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_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; + 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_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. + 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); +} + +// STATUS: TESTED, VERIFIED +void Gfx::CEngine::DrawBackground() +{ + 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.empty()) ) + { + DrawBackgroundImage(); // image + } +} + +// STATUS: TESTED +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] = + { + up, + down, + Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) + }; + + SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR); + + 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::DrawInterface() +// Status: PART_TESTED +void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name) { - Gfx::VertexCol vertices[3] = + 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 { - 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)) + 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; + } + + SetTexture(name); + 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); + 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_TRIANGLES, vertices, 3); + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); +} - DrawMouse(); +// Status: TESTED, VERIFIED +void Gfx::CEngine::DrawBackgroundImage() +{ + Math::Point p1, p2; + std::string name; - return true; + 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); + } +} + +void Gfx::CEngine::DrawPlanet() +{ + 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 +} + +// Status: PART_TESTED +void Gfx::CEngine::DrawForegroundImage() +{ + if (m_foregroundName.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)) + }; + + SetTexture(m_foregroundName); + 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); +} + +// Status: PART_TESTED +void Gfx::CEngine::DrawOverColor() +{ + 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) + }; + + 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); + + 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); +} + +// Status: TESTED, VERIFIED +void Gfx::CEngine::DrawHighlight() +{ + 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; + } + + 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) @@ -648,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) @@ -672,72 +2841,11 @@ 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)) }; 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; -} - |