diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index dad8abc..55e5f64 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -58,6 +58,7 @@ void CWorld::Render() { CRect rect; CGWorldFrame::s_currentWorldFrame->GetRect(&rect); CGWorldFrame::GetActiveCamera()->SetGxProjectionAndView(rect); + DayNight::Update(); DayNight::RenderSky(); GxRsPop(); } diff --git a/src/world/daynight/DNInfo.cpp b/src/world/daynight/DNInfo.cpp new file mode 100644 index 0000000..24ca7f5 --- /dev/null +++ b/src/world/daynight/DNInfo.cpp @@ -0,0 +1 @@ +#include "world/daynight/DNInfo.hpp" diff --git a/src/world/daynight/DNInfo.hpp b/src/world/daynight/DNInfo.hpp new file mode 100644 index 0000000..33d3c4b --- /dev/null +++ b/src/world/daynight/DNInfo.hpp @@ -0,0 +1,148 @@ +#ifndef WORLD_DAY_NIGHT_INFO_HPP +#define WORLD_DAY_NIGHT_INFO_HPP + +#include +#include + +class CM2Scene; +class CM2Model; + +namespace DayNight { + +class DNInfo { + public: + + uint32_t unk0; + float dayProgression = 0.0f; + float day = 0.0f; + uint32_t unk3; + uint32_t unk4; + uint32_t unk5; + C3Vector cameraPos; + uint32_t unk9; + uint32_t unk10; + uint32_t unk11; + C3Vector cameraDir; + float faceAngle = 0.0f; + uint32_t unk16; + uint32_t unk17; + uint32_t unk18; + uint32_t unk19; + uint32_t unk20; + uint32_t unk21; + uint32_t unk22; + uint32_t unk23; + uint32_t unk24; + uint32_t unk25; + uint32_t unk26; + uint32_t unk27; + uint32_t unk28; + uint32_t unk29; + uint32_t unk30; + uint32_t unk31; + uint32_t unk32; + uint32_t unk33; + uint32_t unk34; + uint32_t unk35; + uint32_t unk36; + uint32_t unk37; + uint32_t unk38; + uint32_t unk39; + uint32_t unk40; + uint32_t unk41; + uint32_t unk42; + uint32_t unk43; + uint32_t unk44; + uint32_t unk45; + uint32_t unk46; + uint32_t unk47; + uint32_t unk48; + uint32_t unk49; + uint32_t unk50; + uint32_t unk51; + uint32_t unk52; + uint32_t unk53; + uint32_t unk54; + uint32_t unk55; + uint32_t unk56; + uint32_t unk57; + uint32_t unk58; + uint32_t unk59; + uint32_t unk60; + uint32_t unk61; + uint32_t unk62; + uint32_t unk63; + uint32_t unk64; + uint32_t unk65; + uint32_t unk66; + uint32_t unk67; + uint32_t unk68; + uint32_t unk69; + uint32_t unk70; + uint32_t unk71; + uint32_t unk72; + uint32_t unk73; + uint32_t unk74; + uint32_t unk75; + uint32_t unk76; + uint32_t unk77; + uint32_t unk78; + uint32_t unk79; + uint32_t unk80; + uint32_t unk81; + uint32_t unk82; + uint32_t unk83; + uint32_t unk84; + uint32_t unk85; + uint32_t unk86; + uint32_t unk87; + uint32_t unk88; + uint32_t unk89; + uint32_t unk90; + uint32_t unk91; + uint32_t unk92; + uint32_t unk93; + uint32_t unk94; + uint32_t unk95; + uint32_t unk96; + uint32_t unk97; + uint32_t unk98; + uint32_t unk99; + uint32_t unk100; + uint32_t unk101; + uint32_t unk102; + uint32_t unk103; + uint32_t unk104; + uint32_t unk105; + uint32_t unk106; + uint32_t unk107; + uint32_t unk108; + uint32_t unk109; + uint32_t unk110; + uint32_t unk111; + uint32_t unk112; + uint32_t unk113; + uint32_t unk114; + uint32_t showSky = 0; + uint32_t unk116; + uint32_t unk117; + float sunMoonPath = 0.0f; + uint32_t unk119; + uint32_t unk120; + uint32_t unk121; + uint32_t unk122; + uint32_t unk123; + uint32_t unk124; + uint32_t unk125; + uint32_t unk126; + uint32_t unk127; + uint32_t unk128; + uint32_t unk129; + uint32_t unk130; + uint32_t unk131; + uint32_t unk132; +}; + +} // namespace DayNight + +#endif diff --git a/src/world/daynight/DNSky.cpp b/src/world/daynight/DNSky.cpp new file mode 100644 index 0000000..7202988 --- /dev/null +++ b/src/world/daynight/DNSky.cpp @@ -0,0 +1,101 @@ +#include "world/daynight/DNSky.hpp" +#include "gx/Device.hpp" +#include "gx/Transform.hpp" +#include "gx/RenderState.hpp" +#include "gx/Draw.hpp" +#include +#include + +namespace DayNight { + +float DNSky::m_stripSizes[SKY_NUMBANDS] = { 0.0f, 0.17f, 0.2f, 0.23f, 0.23999999f, 0.25f, 1.0f }; +float DNSky::m_fadeAngle[SKY_NUMBANDS]; +float DNSky::m_darkAngle[SKY_NUMBANDS]; + +void DNSky::Render() { + C44Matrix worldScale; + worldScale.Scale(6.6666665f); + GxXformPush(GxXform_World, worldScale); + GxRsPush(); + GxRsSet(GxRs_Lighting, 0); + GxRsSet(GxRs_Fog, 0); + GxRsSet(GxRs_Culling, 0); + GxRsSet(GxRs_DepthWrite, 0); + GxRsSet(GxRs_BlendingMode, GxBlend_Add); + GxRsSetAlphaRef(); + GxPrimVertexPtr( + this->m_nVerts, this->m_geoVerts.Ptr(), 12, + nullptr, 0, + this->m_clrVerts.Ptr(), 4, + nullptr, 0, + nullptr, 0); + GxDrawLockedElements(GxPrim_TriangleStrip, this->m_nIndices, this->m_indices.Ptr()); + GxXformPop(GxXform_World); + GxRsPop(); +} + +void DNSky::GenSphere(float sphRadius) { + const int32_t geoSize = 24; + const int32_t idxSize = 25 * 2; + + this->m_sphThetaTess = geoSize; + this->m_geoVerts.SetCount(SKY_NUMBANDS * geoSize); // 168 + this->m_clrVerts.SetCount(SKY_NUMBANDS * geoSize); // 168 + this->m_indices.SetCount(idxSize * (SKY_NUMBANDS - 1)); // 300 + + uint16_t lastGeoIndex = 0; + uint16_t lastIndex = 0; + + for (int32_t i = 0; i < SKY_NUMBANDS; ++i) { + float phi = DNSky::m_stripSizes[i] * CMath::PI; + + float v10 = 0.31830987f * phi; + int64_t v11 = static_cast(v10); + if (v10 <= 0.0f) { + v11 -= 1; + } + + float v12 = 1.0f - (v10 - v11) * ((6.0f - (v10 - v11) * 4.0f) * (v10 - v11)); + if (v11 & 1) { + v12 = -v12; + } + + float v13 = 0.31830987f * phi - 0.5f; + int64_t v14 = static_cast(v13); + if (v13 <= 0.0f) { + v14 -= 1; + } + + float v16 = 1.0f - (6.0f - 4.0f * (v13 - v14)) * (v13 - v14) * (v13 - v14); + if (v14 & 1) { + v16 = -v16; + } + + for (int32_t j = 0; j < geoSize; ++j) { + auto& vertex = this->m_geoVerts[lastGeoIndex++]; + + float v19 = static_cast(j) * 0.041666668f * 6.2831855f; + vertex.x = CMath::sinf(v19) * v16 * sphRadius; + vertex.y = v16 * CMath::cosf(v19) * sphRadius0; + vertex.z = sphRadius * v12 - CMath::cosf(0.7853981852531433f); + + if (CMath::fequal(phi, 0.0f) || CMath::fequal(phi, CMath::PI)) { + break; + } + } + + if (i > 0) { + for (uint16_t k = 0; k < 25; ++k) { + uint16_t idx1 = CMath::fequal(phi, 0.0f) ? 0 : (k % 24); + uint16_t idx2 = CMath::fequal(phi, CMath::PI) ? 0 : (k % 24); + this->m_indices[lastIndex++] = idx1 + lastGeoIndex; + this->m_indices[lastIndex++] = idx2 + lastGeoIndex; + } + } + } + + this->m_nVerts = lastGeoIndex; + this->m_nIndices = lastIndex; // Should be always equal to 300 +} + +} // namespace DayNight diff --git a/src/world/daynight/DNSky.hpp b/src/world/daynight/DNSky.hpp new file mode 100644 index 0000000..fee85a9 --- /dev/null +++ b/src/world/daynight/DNSky.hpp @@ -0,0 +1,34 @@ +#ifndef WORLD_DAY_NIGHT_SKY_HPP +#define WORLD_DAY_NIGHT_SKY_HPP + +#include +#include +#include + +namespace DayNight { + +class DNSky { + public: + enum { + SKY_NUMBANDS = 7 + }; + + void Render(); + void GenSphere(float sphRadius); + + static float m_stripSizes[SKY_NUMBANDS]; + static float m_fadeAngle[SKY_NUMBANDS]; + static float m_darkAngle[SKY_NUMBANDS]; + + TSFixedArray m_geoVerts; + TSFixedArray m_clrVerts; + TSFixedArray m_indices; + int32_t m_sphThetaTess = 0; + uint16_t m_nVerts = 0; + uint16_t m_nIndices = 0; + float m_sphRadius = 0.0f; +}; + +} // namespace DayNight + +#endif diff --git a/src/world/daynight/DNStars.cpp b/src/world/daynight/DNStars.cpp index 25e8391..a22763d 100644 --- a/src/world/daynight/DNStars.cpp +++ b/src/world/daynight/DNStars.cpp @@ -1,9 +1,18 @@ #include "world/daynight/DNStars.hpp" +#include "world/daynight/DayNight.hpp" +#include "world/daynight/DNInfo.hpp" #include "model/Model2.hpp" #include namespace DayNight { +C2Vector DNStars::m_fadeTable[4] = { + { 0.1250f, 1.0f }, + { 0.1875f, 0.0f }, + { 0.9375f, 0.0f }, + { 1.0000f, 1.0f } +}; + void DNStars::Initialize() { this->m_scene = M2CreateScene(); this->m_model = this->m_scene->CreateModel("Environments\\Stars\\stars.mdl", 0); @@ -23,12 +32,17 @@ void DNStars::Destroy() { } void DNStars::Update() { - // TODO + auto info = DayNight::GetInfo(); + + this->m_pos = info->cameraPos; + + auto fade = DayNight::InterpTable(DNStars::m_fadeTable, 4, info->dayProgression); + this->m_color.a = static_cast(fade * 254.0 + 1.0); } void DNStars::Render() { if (this->m_color.a < 2) { - //return; + return; } this->m_model->SetAnimating(1); @@ -36,6 +50,9 @@ void DNStars::Render() { // TODO: this->m_model->SetSomething(1); + float alpha = static_cast(this->m_color.a); + // TODO: this->m_model->SetAlpha(alpha * 0.0039215689f) + uint32_t elapsed = OsGetAsyncTimeMs() - this->m_time; this->m_time += elapsed; this->m_scene->AdvanceTime(elapsed); diff --git a/src/world/daynight/DNStars.hpp b/src/world/daynight/DNStars.hpp index 0bd8da1..db4c4b1 100644 --- a/src/world/daynight/DNStars.hpp +++ b/src/world/daynight/DNStars.hpp @@ -19,6 +19,8 @@ class DNStars { void Update(); void Render(); + static C2Vector m_fadeTable[4]; + CM2Scene* m_scene = nullptr; CM2Model* m_model = nullptr; CImVector m_color { 0 }; diff --git a/src/world/daynight/DayNight.cpp b/src/world/daynight/DayNight.cpp index 419a389..8cfa967 100644 --- a/src/world/daynight/DayNight.cpp +++ b/src/world/daynight/DayNight.cpp @@ -1,20 +1,72 @@ #include "world/daynight/DayNight.hpp" +#include "world/daynight/DNInfo.hpp" #include "world/daynight/DNStars.hpp" +#include "world/daynight/DNSky.hpp" #include "gx/Transform.hpp" #include "gx/RenderState.hpp" #include "gx/Draw.hpp" +#include "storm/Error.hpp" namespace DayNight { +static DNInfo g_dnInfo; static DNStars g_stars; +static DNSky g_sky; +float InterpTable(const C2Vector* table, uint32_t size, float key) { + STORM_ASSERT(size); + + uint32_t i = 0; + uint32_t j = 0; + + for (i = 0; i < size; ++i) { + if (key <= table[i].x) { + break; + } + } + + if (i == size) { + i = 0; + j = size - 1; + } else if (i > 0) { + j = i - 1; + } else { + j = size - 1; + } + + float v5 = table[i].x - table[j].x; + if (v5 < 0.0) { + v5 = v5 + 1.0; + } + + float v6 = key - table[j].x; + if (v6 < 0.0) { + v6 = v6 + 1.0; + } + + float v7 = v6 / v5; + + if (table[i].y < table[j].y) { + return table[j].y - v7 * (table[j].y - table[i].y); + } else { + return table[j].y + v7 * (table[i].y - table[j].y); + } +} + void LoadMap(int32_t zoneID) { // TODO + g_sky.GenSphere(1.0f); g_stars.Initialize(); } +void Update() { + // TODO + g_stars.Update(); + g_sky.Render(); +} + void RenderSky() { // TODO @@ -36,4 +88,8 @@ void RenderSky() { g_stars.Render(); } +DNInfo* GetInfo() { + return &g_dnInfo; +} + } // namespace DayNight diff --git a/src/world/daynight/DayNight.hpp b/src/world/daynight/DayNight.hpp index ffdcbd5..fb07180 100644 --- a/src/world/daynight/DayNight.hpp +++ b/src/world/daynight/DayNight.hpp @@ -3,10 +3,17 @@ #include +class C2Vector; + namespace DayNight { +class DNInfo; + +float InterpTable(const C2Vector* table, uint32_t size, float key); void LoadMap(int32_t zoneID); +void Update(); void RenderSky(); +DNInfo* GetInfo(); } // namespace DayNight