Reorganized client code to be ready for isometrics

Preparing the namespacing for multi-dementional/isometric renderers
and the like. Just some fancy formatting for the moment.
This commit is contained in:
Rebekah 2024-02-19 07:04:11 -05:00
parent 639e867fd4
commit a9bc6895ed
Signed by: oneechanhax
GPG Key ID: 183EB7902964DAE5

View File

@ -222,7 +222,7 @@ enum CardinalDirections {
kDown*/
};
class FalseChunk {
class FalseChunk { // TODO, Hurry and figure out how to render a 3x3 of chunks, then move it around to a different area. Get the whole "Treadmilling" correct! we need to hurry to deprecate this or at least figure out its purpose with the server/client code interactions.
public:
// "typedefs" or templates go here lol
static constexpr std::size_t _chunk_array_size = cChunkDef::Width * cChunkDef::Width;
@ -502,7 +502,7 @@ public:
BlockType GetVoxelType(std::size_t v) const {
return raw_chunk_data[v];
}
class AxisIterator {
class AxisIterator { // missing the y axis
bool end_flagged = false;
ChunkVecType cur;
@ -598,7 +598,7 @@ public:
glez::color::black // bedrock
};
static constexpr bool gfx_mesher_debuglog = false;
std::vector<ChunkMeshedQuad> MeshChunk(MesherComplexity cmplxity) const {
std::vector<ChunkMeshedQuad> MeshSingleDepthLayerOfChunk(MesherComplexity cmplxity, int depth = 0) const { // Only good for the TOP/BOTTOM face of the bottom row. Doesnt check if air is in front of the face.
bool is_chunk_only_air = this->IsEmpty();
if (is_chunk_only_air)
return {}; // Your fault you didnt check it first...
@ -780,14 +780,14 @@ public:
}
};
} // namespace qubel
namespace test {
class QubelMeshingTestWindow : public CBaseWindow {
class WindowSettings : public CBaseWindow {
public:
CCheckbox* activate;
CCheckbox* wireframe;
CDropdown* dropdown;
QubelMeshingTestWindow(IWidget* parent)
WindowSettings(IWidget* parent)
: CBaseWindow(parent, "qubelmesh_test_settings") {
this->always_visible = false;
this->hover = false;
@ -819,45 +819,255 @@ public:
this->Add<CCheckbox>("binary_meshing", false);
}
};
} // namespace test
namespace two_d {
class SkyRenderer : public CBaseWidget {
static constexpr bool debug_log = false;
using namespace qubel;
class QubelMeshingTestRenderingWindow : public CBaseWindow {
public:
SkyRenderer(IWidget* parent)
: CBaseWidget("qubelmesh_test_renderer_skybox", parent) {
this->SetPositionMode(FLOATING);
this->zindex = -999;
this->UpdateTime(23000);
if (debug_log)
PrintDebug();
}
virtual void Update() override {
this->CBaseWidget::Update();
const auto psize = this->GetParent()->GetSize();
this->SetSize(psize.first, psize.second);
this->UpdateTime(this->curtime + 1);
if (debug_log)
PrintDebug();
}
virtual void Draw(ICanvas* the_drawing_machine) override {
this->CBaseWidget::Draw(the_drawing_machine);
the_drawing_machine->Rect({ { 0, 0 }, this->GetSize() }, this->GetAtmosphereColor());
}
void UpdateTime(int time_of_day) {
this->curtime = time_of_day;
this->cur_external_planetary_rotation_angle = CalcCelestialAngle(time_of_day);
this->brightness_modifier = CalcBrightnessModifier(this->GetCelestialAngle());
this->base_color = CalcBaseColor(this->GetBrightnessModifier());
this->fog_color = CalcFogColor(this->GetCelestialAngle());
this->atmosphere_color = this->CalcAtmosphereColor();
}
void PrintDebug() const {
auto PrintColor = [](const glez::rgba& clr) {
std::cout << "{ " << clr.r << ", " << clr.g << ", " << clr.b << ", " << clr.a << " }";
};
std::cout << "SkyboxDebug: "
<< "\n Curtime: " << this->curtime
<< "\n CelestialAngle: " << this->GetCelestialAngle()
<< "\n BrightnessModifier: " << this->GetBrightnessModifier();
std::cout << "\n FogColor: ";
PrintColor(this->GetWorldFogColor());
std::cout << "\n Base/SkyColor: ";
PrintColor(this->GetWorldSkyColor());
std::cout << "\n AirColor: ";
PrintColor(this->GetAtmosphereColor());
std::cout << std::endl;
}
float GetBrightnessModifier() const { return this->brightness_modifier; }
const glez::rgba& GetWorldSkyColor() const { return this->base_color; }
const glez::rgba& GetWorldFogColor() const { return this->fog_color; }
const glez::rgba& GetAtmosphereColor() const { return this->atmosphere_color; }
private:
float GetCelestialAngle() const { return this->cur_external_planetary_rotation_angle; }
int curtime;
float cur_external_planetary_rotation_angle;
float brightness_modifier;
glez::rgba base_color; // worldskycolor
glez::rgba fog_color;
glez::rgba atmosphere_color;
// Thank you very much for these foundational findings TrueCraft <3
// These algorithms are kinda hard to recreate and not rip out as is, its MIT so its supposidly safe to add.
// Please Please Please!!! Be sure to keep these credits as they put the impressive work in.
// https://github.com/ddevault/TrueCraft/blob/master/TrueCraft.Client/Modules/SkyModule.cs
static float CalcCelestialAngle(int time_of_day) {
float x = (time_of_day % 24000) / 24000.0f - 0.25f;
if (debug_log)
std::cout << "First X: " << x << std::endl;
if (x < 0)
x = 0;
if (x > 1)
x = 1;
return x + ((1 - (cos(x * glm::pi<float>()) + 1) / 2) - x) / 3;
}
static glez::rgba CalcBaseColor(float brightness_modifier) {
constexpr float temp = 0.8f / 3;
const auto raw_color = glm::rgbColor(glm::vec3(0.6222222f - temp * 0.05f, 0.5f + temp * 0.1f, brightness_modifier));
glez::rgba ret;
ret.r = raw_color.r;
ret.g = raw_color.g;
ret.b = raw_color.b;
ret.a = 1.0f;
return ret;
}
static float CalcBrightnessModifier(float celestial_angle) {
float mod = cos(celestial_angle * glm::two_pi<float>()) * 2 + 0.5f;
if (mod < 0)
mod = 0;
if (mod > 1)
mod = 1;
return mod;
}
static glez::rgba CalcFogColor(float celestial_angle) {
const float y = cos(celestial_angle * glm::two_pi<float>()) * 2 + 0.5f;
if (debug_log)
std::cout << "fog color y: " << y << std::endl;
glez::rgba fog_color;
fog_color.r = 0.7529412f * y * 0.94f + 0.06f;
fog_color.g = 0.8470588f * y * 0.94f + 0.06f;
fog_color.b = 1.0f * y * 0.91f + 0.09f;
fog_color.a = 1.0f;
return fog_color;
// TODO, Nether at a constant (0.2, 0.03, 0.03)
}
glez::rgba CalcAtmosphereColor() const {
constexpr float blend_factor = 0.29f; // TODO: Compute based on view distance
const auto blend = [&](float src, float dest) -> float {
return dest + (src - dest) * blend_factor;
};
const auto &fog = this->GetWorldFogColor(), sky = this->GetWorldSkyColor();
glez::rgba air_color;
air_color.r = blend(sky.r, fog.r);
air_color.g = blend(sky.g, fog.g);
air_color.b = blend(sky.b, fog.b);
air_color.a = 1.0f;
return air_color;
}
};
} // namespace two_d
namespace topdown {
class ChunkRenderer : public CBaseWidget {
public:
static constexpr std::pair<int, int> min_size = { 856, 480 };
const FalseChunk* world_slice;
const test::WindowSettings* settings;
ChunkRenderer(IWidget* parent, test::WindowSettings* settings, FalseChunk* world_slice)
: CBaseWidget("qubelmesh_test_renderer_sceneoutput", parent)
, world_slice(world_slice)
, settings(settings) {
assert(settings && world_slice);
settings->dropdown->SetCallback([&](CDropdown*, int value) {
current_render_quads.clear();
});
this->SetSize(ChunkRenderer::min_size.first, ChunkRenderer::min_size.second);
}
std::vector<FalseChunk::ChunkMeshedQuad> current_render_quads;
virtual void Draw(ICanvas* the_drawing_machine) override {
this->CBaseWidget::Draw(the_drawing_machine);
const auto ConvertGLMVecToSTDPairVec = [](const geo::Vec2& vec_in) -> std::pair<int, int> {
return std::pair<int, int>(vec_in.x, vec_in.y);
};
const auto ConvertGLMQuadToSTDPairQuad = [&](const geo::Box<geo::Vec2>& box_in) -> Canvas::TranslationMatrix {
return Canvas::TranslationMatrix(ConvertGLMVecToSTDPairVec(box_in.origin), ConvertGLMVecToSTDPairVec(box_in.GetSize()));
};
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads)
the_drawing_machine->Rect(ConvertGLMQuadToSTDPairQuad(kinda_a_vert.quad), kinda_a_vert.clr);
if (this->settings->wireframe->Value()) {
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) {
the_drawing_machine->Rect({ ConvertGLMQuadToSTDPairQuad(kinda_a_vert.quad) }, glez::color::black, Canvas::RectType::Outline);
the_drawing_machine->Line({ ConvertGLMQuadToSTDPairQuad(kinda_a_vert.quad) }, glez::color::black);
}
}
}
virtual void Update() override {
this->CBaseWidget::Update();
if (current_render_quads.empty()) {
if (world_slice->IsEmpty())
return;
current_render_quads = world_slice->MeshSingleDepthLayerOfChunk(FalseChunk::MesherComplexity(settings->dropdown->Value()));
if (FalseChunk::gfx_mesher_debuglog) {
std::pair<int, int> found_size;
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) {
const auto max_coord = kinda_a_vert.quad.GetMax();
if (max_coord.x > found_size.first)
found_size.first = max_coord.x;
if (max_coord.y > found_size.second)
found_size.second = max_coord.y;
}
std::cout << "Created mesh with pixel size: " << found_size.first << ", " << found_size.second << std::endl;
}
}
}
};
class RenderingWindow : public CBaseWindow {
public:
const CTitleBar* titlebar;
const QubelMeshingTestWindow* settings;
const test::WindowSettings* settings;
FalseChunk world_slice;
class ChunkRenderer : public CBaseWidget {
two_d::SkyRenderer* skybox;
public:
RenderingWindow(IWidget* parent, test::WindowSettings* settings)
: CBaseWindow(parent, "qubelmesh_test_renderer_frame")
, settings(settings) {
assert(settings);
this->always_visible = false;
this->hover = false;
this->SetPositionMode(PositionMode::FLOATING);
this->SetMaxSize(1270, 1000);
this->zindex = -999;
titlebar = this->Add<CTitleBar>("QubelWorld Mesh Test uwu~");
/*render_scene =*/this->Add<ChunkRenderer>(settings, &world_slice);
skybox = this->Add<two_d::SkyRenderer>();
}
~RenderingWindow() { }
virtual bool AlwaysVisible() const override {
return this->settings->activate->Value();
}
virtual bool IsVisible() const override {
return this->settings->activate->Value() && this->CBaseWindow::IsVisible();
}
};
} // namespace topdown
// Isometric needs some extra stuff to make it work at all. We need a way to render block textures to a isometric block represented as a texture.
// Once we have textures with these isoblocks, it should be a matter of positioning the texture in the correct spot for each block..
// We will require this eventually for the block selector as well as a potential isometric renderer should we want to impliment it.
/*namespace isometric {
class RenderingWindow : public CBaseWindow {
public:
const CTitleBar* titlebar;
const test::WindowSettings* settings;
class IsometricBlockRenderer : public CBaseWidget {
public:
static constexpr std::pair<int, int> min_size = { 856, 480 };
const FalseChunk* world_slice;
const QubelMeshingTestWindow* settings;
ChunkRenderer(IWidget* parent, QubelMeshingTestWindow* settings, FalseChunk* world_slice)
: CBaseWidget("qubelmesh_test_renderer_sceneoutput", parent)
, world_slice(world_slice)
const QubelTestWindowSettings* settings;
glez::texture texture;
IsometricBlockRenderer(IWidget* parent, QubelTestWindowSettings* settings)
: CBaseWidget("qubelmesh_test_renderer_isometric_block_test", parent)
, settings(settings) {
assert(settings && world_slice);
settings->dropdown->SetCallback([&](CDropdown*, int value) {
current_render_quads.clear();
});
this->SetSize(ChunkRenderer::min_size.first, ChunkRenderer::min_size.second);
this->texture = glez::texture::loadFromMemory(embeded_logo_png_rgba.data.begin, embeded_logo_png_rgba.data.size, embeded_logo_png_rgba.width, embeded_logo_png_rgba.height);
this->SetSize(500, 500);
}
std::vector<FalseChunk::ChunkMeshedQuad> current_render_quads;
virtual void Draw(ICanvas* the_drawing_machine) override {
this->CBaseWidget::Draw(the_drawing_machine);
const auto ConvertGLMVecToSTDPairVec = [](const geo::Vec2& vec_in) -> std::pair<int, int> {
return std::pair<int, int>(vec_in.x, vec_in.y);
};
const auto ConvertGLMQuadToSTDPairQuad = [&](const geo::Box<geo::Vec2>& box_in) -> Canvas::TranslationMatrix {
return Canvas::TranslationMatrix(ConvertGLMVecToSTDPairVec(box_in.origin), ConvertGLMVecToSTDPairVec(box_in.GetSize()));
};
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads)
the_drawing_machine->Rect(ConvertGLMQuadToSTDPairQuad(kinda_a_vert.quad), kinda_a_vert.clr);
if (this->settings->wireframe->Value()) {
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) {
the_drawing_machine->Rect({ ConvertGLMQuadToSTDPairQuad(kinda_a_vert.quad) }, glez::color::black, Canvas::RectType::Outline);
the_drawing_machine->Line({ ConvertGLMQuadToSTDPairQuad(kinda_a_vert.quad) }, glez::color::black);
}
o
TranslationMatrix
Offset(TranslationMatrix tm) {
return { this->offset + tm.first, tm.second };
// virtual void Rect(TranslationMatrix tm, glez::rgba color, glez::texture& tx) override {
this->parent->Rect({ tm->GetOffset() + tm.first, tm.second }, color, tx);
}
}
virtual void Update() override {
@ -881,134 +1091,12 @@ public:
}
}
};
ChunkRenderer* render_scene;
class SkyRenderer : public CBaseWidget {
static constexpr bool debug_log = false;
IsometricBlockRenderer* renderer_isometric_block;
public:
SkyRenderer(IWidget* parent)
: CBaseWidget("qubelmesh_test_renderer_skybox", parent) {
this->SetPositionMode(FLOATING);
this->zindex = -999;
this->UpdateTime(23000);
if (debug_log)
PrintDebug();
}
virtual void Update() override {
this->CBaseWidget::Update();
const auto psize = this->GetParent()->GetSize();
this->SetSize(psize.first, psize.second);
this->UpdateTime(this->curtime + 1);
if (debug_log)
PrintDebug();
}
virtual void Draw(ICanvas* the_drawing_machine) override {
this->CBaseWidget::Draw(the_drawing_machine);
the_drawing_machine->Rect({ { 0, 0 }, this->GetSize() }, this->GetAtmosphereColor());
}
void UpdateTime(int time_of_day) {
this->curtime = time_of_day;
this->cur_external_planetary_rotation_angle = CalcCelestialAngle(time_of_day);
this->brightness_modifier = CalcBrightnessModifier(this->GetCelestialAngle());
this->base_color = CalcBaseColor(this->GetBrightnessModifier());
this->fog_color = CalcFogColor(this->GetCelestialAngle());
this->atmosphere_color = this->CalcAtmosphereColor();
}
void PrintDebug() const {
auto PrintColor = [](const glez::rgba& clr) {
std::cout << "{ " << clr.r << ", " << clr.g << ", " << clr.b << ", " << clr.a << " }";
};
std::cout << "SkyboxDebug: "
<< "\n Curtime: " << this->curtime
<< "\n CelestialAngle: " << this->GetCelestialAngle()
<< "\n BrightnessModifier: " << this->GetBrightnessModifier();
std::cout << "\n FogColor: ";
PrintColor(this->GetWorldFogColor());
std::cout << "\n Base/SkyColor: ";
PrintColor(this->GetWorldSkyColor());
std::cout << "\n AirColor: ";
PrintColor(this->GetAtmosphereColor());
std::cout << std::endl;
}
float GetBrightnessModifier() const { return this->brightness_modifier; }
const glez::rgba& GetWorldSkyColor() const { return this->base_color; }
const glez::rgba& GetWorldFogColor() const { return this->fog_color; }
const glez::rgba& GetAtmosphereColor() const { return this->atmosphere_color; }
private:
float GetCelestialAngle() const { return this->cur_external_planetary_rotation_angle; }
int curtime;
float cur_external_planetary_rotation_angle;
float brightness_modifier;
glez::rgba base_color; // worldskycolor
glez::rgba fog_color;
glez::rgba atmosphere_color;
// Thank you very much for these foundational findings TrueCraft <3
// These algorithms are kinda hard to recreate and not rip out as is, its MIT so its supposidly safe to add.
// Please Please Please!!! Be sure to keep these credits as they put the impressive work in.
// https://github.com/ddevault/TrueCraft/blob/master/TrueCraft.Client/Modules/SkyModule.cs
static float CalcCelestialAngle(int time_of_day) {
float x = (time_of_day % 24000) / 24000.0f - 0.25f;
if (debug_log)
std::cout << "First X: " << x << std::endl;
if (x < 0)
x = 0;
if (x > 1)
x = 1;
return x + ((1 - (cos(x * glm::pi<float>()) + 1) / 2) - x) / 3;
}
static glez::rgba CalcBaseColor(float brightness_modifier) {
constexpr float temp = 0.8f / 3;
const auto raw_color = glm::rgbColor(glm::vec3(0.6222222f - temp * 0.05f, 0.5f + temp * 0.1f, brightness_modifier));
glez::rgba ret;
ret.r = raw_color.r;
ret.g = raw_color.g;
ret.b = raw_color.b;
ret.a = 1.0f;
return ret;
}
static float CalcBrightnessModifier(float celestial_angle) {
float mod = cos(celestial_angle * glm::two_pi<float>()) * 2 + 0.5f;
if (mod < 0)
mod = 0;
if (mod > 1)
mod = 1;
return mod;
}
static glez::rgba CalcFogColor(float celestial_angle) {
const float y = cos(celestial_angle * glm::two_pi<float>()) * 2 + 0.5f;
if (debug_log)
std::cout << "fog color y: " << y << std::endl;
glez::rgba fog_color;
fog_color.r = 0.7529412f * y * 0.94f + 0.06f;
fog_color.g = 0.8470588f * y * 0.94f + 0.06f;
fog_color.b = 1.0f * y * 0.91f + 0.09f;
fog_color.a = 1.0f;
return fog_color;
// TODO, Nether at a constant (0.2, 0.03, 0.03)
}
glez::rgba CalcAtmosphereColor() const {
constexpr float blend_factor = 0.29f; // TODO: Compute based on view distance
const auto blend = [&](float src, float dest) -> float {
return dest + (src - dest) * blend_factor;
};
const auto &fog = this->GetWorldFogColor(), sky = this->GetWorldSkyColor();
glez::rgba air_color;
air_color.r = blend(sky.r, fog.r);
air_color.g = blend(sky.g, fog.g);
air_color.b = blend(sky.b, fog.b);
air_color.a = 1.0f;
return air_color;
}
};
SkyRenderer* skybox;
SkyRenderer* renderer_skybox;
public:
QubelMeshingTestRenderingWindow(IWidget* parent, QubelMeshingTestWindow* settings)
MeshingTestRenderingWindow(IWidget* parent, QubelMeshingTestWindow* settings)
: CBaseWindow(parent, "qubelmesh_test_renderer_frame")
, settings(settings) {
assert(settings);
@ -1029,10 +1117,10 @@ public:
virtual bool IsVisible() const override {
return this->settings->activate->Value() && this->CBaseWindow::IsVisible();
}
public:
// std::chrono::time_point<std::chrono::system_clock> last_update;
};
} // namespace isometric*/
} // namespace qubel
int start_nyqubel_client() {
auto client_rendering_thread = std::thread([&]() {
@ -1057,13 +1145,13 @@ int start_nyqubel_client() {
canvas->Add<ncc::Logo>()->SetOffset(500, 525);
auto mesh_test_settings_window = canvas->Add<QubelMeshingTestWindow>();
auto mesh_test_rendering_window = canvas->Add<QubelMeshingTestRenderingWindow>(mesh_test_settings_window);
mesh_test_settings_window->SetOffset(2000, 400);
mesh_test_rendering_window->SetOffset(3000, 800);
auto test_settings_window = canvas->Add<qubel::test::WindowSettings>();
auto rendering_window = canvas->Add<qubel::topdown::RenderingWindow>(test_settings_window);
test_settings_window->SetOffset(2000, 400);
rendering_window->SetOffset(3000, 800);
bool client_exiting = false;
mesh_test_settings_window->Add<CBaseButton>("exit_button", "Press to Quit-rite", [&](CBaseButton*) {
test_settings_window->Add<CBaseButton>("exit_button", "Press to Quit-rite", [&](CBaseButton*) {
client_exiting = true;
std::cout << "User Requested Client quit." << std::endl;
});