Skip to content

Commit

Permalink
Partial terrain support
Browse files Browse the repository at this point in the history
  • Loading branch information
Lyuu17 committed Jul 4, 2024
1 parent 8612b1f commit 66c710b
Show file tree
Hide file tree
Showing 12 changed files with 415 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ target_sources(${PROJECT_NAME}
"SWBF2/Native/Chunks/ObjectDefinitionChunk.cpp"
"SWBF2/Native/Chunks/SkyChunk.cpp"
"SWBF2/Native/Chunks/StreamReader.cpp"
"SWBF2/Native/Chunks/TerrainChunk.cpp"
"SWBF2/Native/Chunks/TextureChunk.cpp"
"SWBF2/Native/Chunks/UcfbChunk.cpp"
"SWBF2/Native/Chunks/WorldChunk.cpp"
Expand All @@ -22,9 +23,11 @@ target_sources(${PROJECT_NAME}
"SWBF2/Native/Hashes.cpp"
"SWBF2/Native/Level.cpp"
"SWBF2/Native/SWBF2.cpp"
"SWBF2/Native/Terrain.cpp"
"SWBF2/Native/World.cpp"
"SWBF2/Core.cpp"
"SWBF2/Level.cpp"
"SWBF2/Terrain.cpp"
"SWBF2/MaterialPools.cpp"

"RegisterExtension.cpp"
Expand Down
7 changes: 7 additions & 0 deletions src/SWBF2/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "Core.hpp"
#include "Level.hpp"
#include "Terrain.hpp"
#include "Version.h"

namespace SWBF2
Expand All @@ -29,6 +30,7 @@ namespace SWBF2
if (mapName.is_empty())
{
remove_child(find_child("Level", false));
remove_child(find_child("Terrain", false));

SWBF2::Native::SWBF2::Reset();
return;
Expand All @@ -38,6 +40,11 @@ namespace SWBF2
add_child(lvl);
lvl->set_owner(this);
lvl->LoadLevel(mapName);

Terrain *terr = memnew(Terrain);
add_child(terr);
terr->set_owner(this);
terr->LoadTerrain();
}

void Core::_bind_methods()
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 @@ -14,6 +14,7 @@
#include "SkyChunk.hpp"
#include "LightChunk.hpp"
#include "ObjectDefinitionChunk.hpp"
#include "TerrainChunk.hpp"

namespace SWBF2::Native
{
Expand All @@ -31,7 +32,8 @@ namespace SWBF2::Native
{ "lvl_"_m, LevelChunk::ProcessChunk },
{ "sky_"_m, SkyChunk::ProcessChunk },
{ "lght"_m, LightChunk::ProcessChunk },
{ "entc"_m, ObjectDefinitionChunk::ProcessChunk }
{ "entc"_m, ObjectDefinitionChunk::ProcessChunk },
{ "tern"_m, TerrainChunk::ProcessChunk }
};

static void ProcessChunk(StreamReader &streamReader, StreamReader &parentReader);
Expand Down
2 changes: 2 additions & 0 deletions src/SWBF2/Native/Chunks/StreamReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ namespace SWBF2::Native

value = std::string_view(str, len);

m_head += len + 1;

return *this;
}

Expand Down
212 changes: 212 additions & 0 deletions src/SWBF2/Native/Chunks/TerrainChunk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#include <godot_cpp/variant/utility_functions.hpp>

#include "Native/Chunks/StreamReader.hpp"
#include "Native/Chunks/TerrainChunk.hpp"
#include "Native/Terrain.hpp"
#include "Native/SWBF2.hpp"

namespace SWBF2::Native
{
enum class VBufType : uint32_t {
GEOMETRY = 290,
TEXTURE = 20770,
TEXTURE_EXTRA = 130
};

void TerrainChunk::ProcessChunk(StreamReader &streamReader)
{
Terrain tern{};

auto nameReaderChild = streamReader.ReadChildWithHeader<"NAME"_m>();
{
*nameReaderChild >> tern.m_name;
}

if (streamReader.IsEof())
return; // No terrain

auto infoReaderChild = streamReader.ReadChildWithHeader<"INFO"_m>();
{
*infoReaderChild >> tern.m_gridUnitSize;
*infoReaderChild >> tern.m_heightScale;
*infoReaderChild >> tern.m_heightFloor;
*infoReaderChild >> tern.m_heightCeiling;
*infoReaderChild >> tern.m_gridSize;
*infoReaderChild >> tern.m_heightPatches;
*infoReaderChild >> tern.m_texturePatches;
*infoReaderChild >> tern.m_textureCount;
*infoReaderChild >> tern.m_maxTextureLayers;
*infoReaderChild >> tern.m_unknown;
}

auto ltexChild = streamReader.ReadChildWithHeader<"LTEX"_m>();
{
for (int i = 0; i < tern.m_textureCount; i++)
{
std::string texName;
*ltexChild >> texName;

tern.m_textures.push_back(texName);
}
}

auto dtexReaderChild = streamReader.ReadChildWithHeader<"DTEX"_m>();
{
// unused?
dtexReaderChild->SkipBytes((uint32_t)dtexReaderChild->RemainingBytes());
}

auto dtlxReaderChild = streamReader.ReadChildWithHeader<"DTLX"_m>();
{
*dtlxReaderChild >> tern.m_detailTexture;
}

auto scalChild = streamReader.ReadChildWithHeader<"SCAL"_m>();
{
for (int i = 0; i < tern.m_textureCount; i++)
{
float scal;
*scalChild >> scal;

tern.m_textureScales.push_back(scal);
}
}

auto axisChild = streamReader.ReadChildWithHeader<"AXIS"_m>();
{
for (int i = 0; i < tern.m_textureCount; i++)
{
uint8_t axis;
*axisChild >> axis;

tern.m_textureAxis.push_back(axis);
}
}

auto rotnChild = streamReader.ReadChildWithHeader<"ROTN"_m>();
{
for (int i = 0; i < tern.m_textureCount; i++)
{
float rotn;
*rotnChild >> rotn;

tern.m_textureRotn.push_back(rotn);
}
}

std::optional<StreamReader> readerChild;
while ((readerChild = streamReader.ReadChild()).has_value())
{
switch (readerChild->GetHeader().m_Magic)
{
case "PCHS"_m:
{
StreamReader r{ *readerChild };
ReadPatches(r, tern);
break;
}
case "WATR"_m:
// todo
break;
}
}

SWBF2::m_tern = tern;
}

void TerrainChunk::ReadPatches(StreamReader &streamReader, Terrain &tern)
{
auto comnReaderChild = streamReader.ReadChildWithHeader<"COMN"_m>();
{
// whats this
comnReaderChild->SkipBytes((uint32_t)comnReaderChild->RemainingBytes());
}

std::optional<StreamReader> ptchReaderChild;
while ((ptchReaderChild = streamReader.ReadChildWithHeader<"PTCH"_m>()).has_value())
{
StreamReader r{ *ptchReaderChild };
ReadPatch(r, tern);
}
}

void TerrainChunk::ReadPatch(StreamReader &streamReader, Terrain &tern)
{
TerrainPatch ptch;

auto infoReaderChild = streamReader.ReadChildWithHeader<"INFO"_m>();
{}

std::optional<StreamReader> readerChild;
while ((readerChild = streamReader.ReadChildWithHeader<"VBUF"_m>()).has_value())
{
uint32_t elementCount;
*readerChild >> elementCount;

uint32_t elementSize;
*readerChild >> elementSize;

VBufType elementType;
*readerChild >> elementType;

if (elementType == VBufType::TEXTURE_EXTRA)
{
std::vector<TerrainTextureVBufExtraEntry> vbuf;
vbuf.resize(elementCount);

*readerChild >> vbuf;

ptch.m_vertices.m_texturesExtra = vbuf;

if (streamReader.IsNextHeader<"IBUF"_m>())
{
readerChild = streamReader.ReadChildWithHeader<"IBUF"_m>();
*readerChild >> elementCount;

ptch.m_indices.m_textureExtra.resize(elementCount);

*readerChild >> ptch.m_indices.m_textureExtra;
}
}
else if (elementType == VBufType::TEXTURE)
{
std::vector<TerrainTextureVBufEntry> vbuf;
vbuf.resize(elementCount);

*readerChild >> vbuf;

ptch.m_vertices.m_textures = vbuf;

if (streamReader.IsNextHeader<"IBUF"_m>())
{
throw std::runtime_error{ "not implemented" };
}
}
else if (elementType == VBufType::GEOMETRY)
{
std::vector<TerrainGeometryVBufEntry> vbuf;
vbuf.resize(elementCount);

*readerChild >> vbuf;

ptch.m_vertices.m_geometry = vbuf;

if (streamReader.IsNextHeader<"IBUF"_m>())
{
readerChild = streamReader.ReadChildWithHeader<"IBUF"_m>();
*readerChild >> elementCount;

ptch.m_indices.m_geometry.resize(elementCount);

*readerChild >> ptch.m_indices.m_geometry;
}
}
else
{
throw std::runtime_error{ "Unknown VBUF type encountered in terrain." };
}
}

tern.m_patches.push_back(ptch);
}
}
16 changes: 16 additions & 0 deletions src/SWBF2/Native/Chunks/TerrainChunk.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "StreamReader.hpp"

namespace SWBF2::Native
{
class Terrain;

class TerrainChunk {
public:
static void ProcessChunk(StreamReader &streamReader);
static void ReadPatches(StreamReader &streamReader, Terrain &tern);
static void ReadPatch(StreamReader &streamReader, Terrain &tern);
};

}
2 changes: 2 additions & 0 deletions src/SWBF2/Native/SWBF2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace SWBF2::Native
std::string SWBF2::m_curMapName;
LevelGamemode SWBF2::m_curLevel;

Terrain SWBF2::m_tern;

std::unordered_map<LevelGamemode, Level> SWBF2::m_levels;
std::unordered_map<std::string, World> SWBF2::m_worlds;
std::unordered_map<std::string, Light> SWBF2::m_lights;
Expand Down
3 changes: 3 additions & 0 deletions src/SWBF2/Native/SWBF2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Native/Level.hpp"
#include "Native/SkyDome.hpp"
#include "Native/Light.hpp"
#include "Native/Terrain.hpp"

namespace SWBF2::Native
{
Expand Down Expand Up @@ -34,6 +35,8 @@ namespace SWBF2::Native
static std::string m_curMapName;
static LevelGamemode m_curLevel;

static Terrain m_tern;

static std::unordered_map<LevelGamemode, Level> m_levels;
static std::unordered_map<std::string, World> m_worlds;
static std::unordered_map<std::string, Light> m_lights;
Expand Down
9 changes: 9 additions & 0 deletions src/SWBF2/Native/Terrain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

#include "Native/SWBF2.hpp"

#include "Terrain.hpp"
#include "Terrain.hpp"

namespace SWBF2::Native
{
}
Loading

0 comments on commit 66c710b

Please sign in to comment.