Skip to content

Commit

Permalink
Initial skybox
Browse files Browse the repository at this point in the history
  • Loading branch information
Lyuu17 committed Jun 27, 2024
1 parent 4498756 commit 495015c
Show file tree
Hide file tree
Showing 20 changed files with 4,263 additions and 24 deletions.
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ target_sources(${PROJECT_NAME}
PRIVATE
"SWBF2/Native/Chunks/ChunkHeader.cpp"
"SWBF2/Native/Chunks/ChunkProcessor.cpp"
"SWBF2/Native/Chunks/ConfigReader.cpp"
"SWBF2/Native/Chunks/LevelChunk.cpp"
"SWBF2/Native/Chunks/LoclChunk.cpp"
"SWBF2/Native/Chunks/ModelChunk.cpp"
"SWBF2/Native/Chunks/ModelSegmentChunk.cpp"
"SWBF2/Native/Chunks/SkyChunk.cpp"
"SWBF2/Native/Chunks/StreamReader.cpp"
"SWBF2/Native/Chunks/TextureChunk.cpp"
"SWBF2/Native/Chunks/UcfbChunk.cpp"
"SWBF2/Native/Chunks/WorldChunk.cpp"
"SWBF2/Native/Models/Model.cpp"
"SWBF2/Native/Texture/Texture.cpp"
"SWBF2/Native/Texture/TextureUtils.cpp"
"SWBF2/Native/Hashes.cpp"
"SWBF2/Native/Level.cpp"
"SWBF2/Native/SWBF2.cpp"
"SWBF2/Native/World.cpp"
Expand Down
6 changes: 3 additions & 3 deletions src/SWBF2/FNVHash.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

namespace SWBF2
namespace SWBF2::Native
{
typedef uint32_t FNVHash;
enum class FNVHash : uint32_t;

constexpr FNVHash FNVGenerateHash(const std::string &str)
{
Expand All @@ -21,7 +21,7 @@ namespace SWBF2
hash *= FNV_prime;
}

return hash;
return (FNVHash)hash;
}

constexpr FNVHash operator""_fnv(const char *str, const std::size_t length)
Expand Down
29 changes: 28 additions & 1 deletion src/SWBF2/Level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#include <godot_cpp/classes/mesh_instance3d.hpp>
#include <godot_cpp/classes/image_texture.hpp>
#include <godot_cpp/classes/standard_material3d.hpp>
#include <godot_cpp/classes/environment.hpp>
#include <godot_cpp/classes/world_environment.hpp>
#include <godot_cpp/classes/sky.hpp>
#include <godot_cpp/classes/procedural_sky_material.hpp>
#include <godot_cpp/variant/color.hpp>

#include "Native/Chunks/ChunkProcessor.hpp"
Expand All @@ -17,9 +21,11 @@ namespace SWBF2
{
set_name("Level");

Native::SWBF2::LoadLevelWithGamemode("yav/yav1", "ctf");
if (!Native::SWBF2::LoadLevelWithGamemode("cor/cor1", "ctf"))
throw std::runtime_error{ "failed to load the game level" };

LoadLevelInstances();
LoadSkybox();
}

godot::MeshInstance3D *Level::LoadModel(const std::string &id)
Expand Down Expand Up @@ -133,6 +139,27 @@ namespace SWBF2
}
}

void Level::LoadSkybox()
{
godot::WorldEnvironment *worldEnv = memnew(godot::WorldEnvironment);
godot::Environment *env = memnew(godot::Environment);
godot::Sky *sky = memnew(godot::Sky);

auto &texture = Native::SWBF2::m_tex[Native::SWBF2::m_skyDome.m_texture].m_formats[0].m_faceLevels[0].m_gdTexture;
godot::ProceduralSkyMaterial *procSkyMaterial = memnew(godot::ProceduralSkyMaterial);
procSkyMaterial->set_sky_cover(texture);

sky->set_material(procSkyMaterial);

env->set_background(godot::Environment::BG_SKY);
env->set_sky(sky);
worldEnv->set_environment(env);

add_child(worldEnv);

worldEnv->set_owner(this->get_parent());
}

void Level::_process(double delta_time)
{
}
Expand Down
1 change: 1 addition & 0 deletions src/SWBF2/Level.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace SWBF2

godot::MeshInstance3D *LoadModel(const std::string &id);
void LoadLevelInstances();
void LoadSkybox();

void _process(double delta_time) override;

Expand Down
4 changes: 3 additions & 1 deletion src/SWBF2/Native/Chunks/ChunkProcessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "LoclChunk.hpp"
#include "TextureChunk.hpp"
#include "LevelChunk.hpp"
#include "SkyChunk.hpp"

namespace SWBF2::Native
{
Expand All @@ -25,7 +26,8 @@ namespace SWBF2::Native
{ "modl"_m, ModelChunk::ProcessChunk },
{ "Locl"_m, LoclChunk::ProcessChunk },
{ "tex_"_m, TextureChunk::ProcessChunk },
{ "lvl_"_m, LevelChunk::ProcessChunk }
{ "lvl_"_m, LevelChunk::ProcessChunk },
{ "sky_"_m, SkyChunk::ProcessChunk }
};

static void ProcessChunk(StreamReader &streamReader, StreamReader &parentReader);
Expand Down
120 changes: 120 additions & 0 deletions src/SWBF2/Native/Chunks/ConfigReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* Mostly code from swbf2-unmunge, as everything is */

#include <godot_cpp/variant/utility_functions.hpp>

#include "Native/Hashes.hpp"

#include "Native/Chunks/ConfigReader.hpp"

namespace SWBF2::Native
{
ConfigReader::ConfigReader(StreamReader &streamReader)
: m_data({})
{
auto nameReaderChild = streamReader.ReadChildWithHeader<"NAME"_m>();

if (nameReaderChild.has_value())
{
uint32_t nameHash;
*nameReaderChild >> nameHash;

m_name = GameHashes.contains(nameHash) ? GameHashes.at(nameHash) : "unknown";
}

while (streamReader.IsNextHeader<"DATA"_m>())
{
ReadData(streamReader, m_data);
}
}

void ConfigReader::ReadData(StreamReader &streamReader, ConfigNode &parentConfigNode)
{
auto dataReaderChild = streamReader.ReadChildWithHeader<"DATA"_m>();
{
FNVHash hash;
*dataReaderChild >> hash;

auto scopReaderChild = streamReader.ReadChildWithHeader<"SCOP"_m>();
{
ReadDataScop(*scopReaderChild, parentConfigNode.createNode(hash));
}
}
}

void ConfigReader::ReadDataScop(StreamReader &streamReader, ConfigNode &parentConfigNode)
{
while (streamReader.IsNextHeader<"DATA"_m>())
{
if (streamReader.IsNextHeader2<"DATA"_m, "SCOP"_m>())
{
ReadData(streamReader, parentConfigNode);

continue;
}

auto scopDataReaderChild = streamReader.ReadChildWithHeader<"DATA"_m>();
if (!scopDataReaderChild.has_value())
throw std::runtime_error{ "wait, thats illegal" };

StreamReader r{ *scopDataReaderChild };
ReadDataElementInfo(r, parentConfigNode);
}
}

void ConfigReader::ReadDataElementInfo(StreamReader &streamReader, ConfigNode &parentConfigNode)
{
#pragma pack(push, 1)
struct {
FNVHash tag;
uint8_t count;
} data;
#pragma pack(pop)

streamReader >> data;

if (data.count > 0)
ReadDataElements(streamReader, parentConfigNode.createNode(data.tag), data.count);
}

void ConfigReader::ReadDataElements(StreamReader &streamReader, ConfigNode &parentConfigNode, uint8_t count)
{
#pragma pack(push, 1)
struct
{
float floatValue;
uint32_t stringSize;
} data_element;
#pragma pack(pop)

streamReader >> data_element;

if (count == 1)
{
if (data_element.stringSize > 0)
{
parentConfigNode.m_dataType = ConfigDataType::STRING;

streamReader >> parentConfigNode.m_string;
}
else
{
parentConfigNode.m_dataType = ConfigDataType::FLOAT;
parentConfigNode.m_float = data_element.floatValue;
}
}
else
{
parentConfigNode.m_dataType = ConfigDataType::FLOAT_VECTOR;
parentConfigNode.m_vecFloat.push_back(data_element.floatValue);

for (int i = 1; i < count; i++)
{
float elementValue;
streamReader >> elementValue;

parentConfigNode.m_dataType = ConfigDataType::FLOAT_VECTOR;
parentConfigNode.m_vecFloat.push_back(elementValue);
}
}
}
}
55 changes: 55 additions & 0 deletions src/SWBF2/Native/Chunks/ConfigReader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once

#include "Native/Chunks/StreamReader.hpp"

#include "Native/Hashes.hpp"

namespace SWBF2::Native
{
enum class ConfigDataType
{
FLOAT,
STRING,
FLOAT_VECTOR
};

class ConfigData {
public:
ConfigDataType m_dataType;

float m_float;
std::string m_string;
std::vector<float> m_vecFloat;
};

class ConfigNode : public ConfigData {
protected:
std::unordered_multimap<FNVHash, std::unique_ptr<ConfigNode>> m_childs;
public:
ConfigNode &createNode(FNVHash hash) {
auto it = m_childs.emplace(hash, std::make_unique<ConfigNode>());
if (it == m_childs.end())
throw std::runtime_error{ "failed to create node " };
return *it->second;
}

auto &getNodes() {
return m_childs;
}
};

class ConfigReader : public StreamReader {
public:
ConfigReader(StreamReader &streamReader);

std::string m_name;

ConfigNode m_data;

private:
void ReadData(StreamReader &streamReader, ConfigNode &parentConfigNode);
void ReadDataScop(StreamReader &streamReader, ConfigNode &parentConfigNode);
void ReadDataElementInfo(StreamReader &streamReader, ConfigNode &parentConfigNode);
void ReadDataElements(StreamReader &streamReader, ConfigNode &parentConfigNode, uint8_t count);
};
}
18 changes: 10 additions & 8 deletions src/SWBF2/Native/Chunks/LevelChunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Native/Chunks/LevelChunk.hpp"
#include "Native/Chunks/WorldChunk.hpp"

#include "Native/Hashes.hpp"
#include "Native/SWBF2.hpp"

namespace SWBF2::Native
Expand All @@ -12,7 +13,11 @@ namespace SWBF2::Native
{
Level lvl{};

streamReader.SkipBytes(sizeof(uint32_t)); // hash?
uint32_t hash;
streamReader >> hash;

// std::string lvlName{ GameHashes.at(hash) };

streamReader.SkipBytes(sizeof(uint32_t)); // lvl_ size left

std::optional<StreamReader> readerChild;
Expand All @@ -36,13 +41,10 @@ namespace SWBF2::Native
}
}

const auto gamemodes = { "ctf", "conquest", "centerflag", "campaign", "tdm" };
for (const auto &[id, world] : lvl.m_worlds)
{
std::string type = id.substr(id.find_first_of('_') + 1);
/*const auto gamemodes = {"ctf", "conquest", "centerflag", "campaign", "tdm"};
std::string type = lvlName.substr(lvlName.find_first_of('_') + 1);
if (std::find(gamemodes.begin(), gamemodes.end(), type) != gamemodes.end())
SWBF2::m_levels.insert_or_assign(type, lvl);
}
if (std::find(gamemodes.begin(), gamemodes.end(), type) != gamemodes.end())
SWBF2::m_levels.insert_or_assign(type, lvl);*/
}
}
29 changes: 29 additions & 0 deletions src/SWBF2/Native/Chunks/SkyChunk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <godot_cpp/variant/utility_functions.hpp>

#include "Native/Chunks/ConfigReader.hpp"
#include "Native/Chunks/StreamReader.hpp"
#include "Native/Chunks/SkyChunk.hpp"
#include "Native/SWBF2.hpp"

namespace SWBF2::Native
{
void SkyChunk::ProcessChunk(StreamReader &streamReader)
{
ConfigReader configReader{ streamReader };

for (auto const &[idhead, headnode] : configReader.m_data.getNodes())
{
for (auto const &[attr, val] : headnode->getNodes())
{
switch (attr)
{
case "Texture"_fnv:
{
SWBF2::m_skyDome.m_texture = val->m_string;
break;
}
}
}
}
}
}
12 changes: 12 additions & 0 deletions src/SWBF2/Native/Chunks/SkyChunk.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "StreamReader.hpp"

namespace SWBF2::Native
{
class SkyChunk {
public:
static void ProcessChunk(StreamReader &streamReader);
};

}
Loading

0 comments on commit 495015c

Please sign in to comment.