Skip to content

Commit 7b5bc79

Browse files
committed
terrain loader and eterrain
1 parent 3bf9060 commit 7b5bc79

File tree

18 files changed

+428
-195
lines changed

18 files changed

+428
-195
lines changed

.clang-tidy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ FormatStyle: none
3232
CheckOptions:
3333
- key: readability-identifier-length.IgnoredVariableNames
3434
value: 'x|y|z'
35+
- key: readability-identifier-length.IgnoredLoopCounterNames
36+
value: '^[ijk_xyz]$'
3537
- key: readability-identifier-length.IgnoredParameterNames
3638
value: 'x|y|z'
3739

assets/scenes/test_scene.ess

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ quadratic=0.44
4343

4444
[Terrain]
4545
name=test_terrain
46+
resource_name=test_terrain
4647
[/Terrain]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Test terrain file
2+
version=1.0
3+
4+
heightmap=GreyScaleElevation
5+
scale_x=1
6+
scale_y=1
7+
scale_z=100
265 KB
Loading

engine/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ set(SOURCES
2929
loaders/shader_loader.cpp
3030
loaders/system_font_loader.cpp
3131
loaders/text_loader.cpp
32+
loaders/terrain_loader.cpp
3233
log/log.cpp
3334
platform/platform.cpp
3435
platform/filesystem.cpp

engine/loaders/mesh_loader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace egkr
1010

1111
resource::shared_ptr mesh_loader::load(const std::string& name, void* /*params*/)
1212
{
13-
egkr::vector<supported_file_type> file_types{{.extension=".esm", .file_type=mesh_file_type::esm, .is_binary=true}, {.extension=".obj", .file_type=mesh_file_type::obj, .is_binary=false}};
13+
egkr::vector<supported_file_type> file_types{{.extension = ".esm", .file_type = mesh_file_type::esm, .is_binary = true}, {.extension = ".obj", .file_type = mesh_file_type::obj, .is_binary = false}};
1414

1515
bool found{};
1616
supported_file_type found_type{};
@@ -362,11 +362,11 @@ namespace egkr
362362

363363
properties.vertices = malloc(size);
364364

365+
generate_tangents(vertices, properties.indices);
365366
std::copy(vertices.data(), vertices.data() + properties.vertex_count, (vertex_3d*)properties.vertices);
366367

367368
properties.center = (properties.extents.min + properties.extents.max) / 2.F;
368369

369-
generate_tangents(properties.vertices, properties.indices);
370370

371371
return properties;
372372
}

engine/loaders/scene_loader.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ namespace egkr
276276
case parse_mode::mesh:
277277
current_mesh.resource_name = value;
278278
break;
279+
case parse_mode::terrain:
280+
current_terrain.resource_name = value;
281+
break;
279282
default:
280283
break;
281284
}

engine/loaders/terrain_loader.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#include "terrain_loader.h"
2+
3+
#include "log/log.h"
4+
#include "platform/filesystem.h"
5+
#include "resources/resource.h"
6+
#include "resources/terrain.h"
7+
#include "systems/resource_system.h"
8+
#include <map>
9+
10+
namespace egkr::loader
11+
{
12+
terrain::unique_ptr terrain::create(const loader_properties& properties) { return std::make_unique<terrain>(properties); }
13+
14+
terrain::terrain(const loader_properties& properties): resource_loader{resource::type::terrain, properties} { }
15+
16+
resource::shared_ptr terrain::load(const std::string& name, void* /* params */)
17+
{
18+
const auto base_path = get_base_path();
19+
const std::string filename = std::format("{}/{}{}", base_path, name, ".eterrain");
20+
21+
const auto properties = load_configuration_file(filename);
22+
23+
resource::properties resource_properties{.type = get_loader_type(), .name = name, .full_path = filename, .data = new egkr::terrain::properties()};
24+
25+
resource_properties.data = new egkr::terrain::configuration();
26+
*(egkr::terrain::configuration*)resource_properties.data = properties;
27+
28+
return resource::create(resource_properties);
29+
}
30+
31+
bool terrain::unload(const resource::shared_ptr& resource)
32+
{
33+
delete (egkr::terrain::configuration*)resource->data;
34+
resource->data = nullptr;
35+
return true;
36+
}
37+
38+
static const std::map<std::string, std::function<void(egkr::terrain::configuration&, const std::string&)>> terrain_configuration_members = {
39+
{"version", [](egkr::terrain::configuration& /* config */, const std::string& /* value */) noexcept {}},
40+
{"heightmap", [](egkr::terrain::configuration& config, const std::string& value) noexcept { config.heightmap = value; }},
41+
{"tiles_x", [](egkr::terrain::configuration& config, const std::string& value) noexcept { config.tiles_x = (uint32_t)std::stoi(value); }},
42+
{"tiles_y", [](egkr::terrain::configuration& config, const std::string& value) noexcept { config.tiles_y = (uint32_t)std::stoi(value); }},
43+
{"scale_x", [](egkr::terrain::configuration& config, const std::string& value) noexcept { config.scale_x = std::stof(value); }},
44+
{"scale_y", [](egkr::terrain::configuration& config, const std::string& value) noexcept { config.scale_y = std::stof(value); }},
45+
{"scale_z", [](egkr::terrain::configuration& config, const std::string& value) noexcept { config.scale_z = std::stof(value); }},
46+
};
47+
48+
egkr::terrain::configuration terrain::load_configuration_file(const std::string& path)
49+
{
50+
egkr::terrain::configuration properties{};
51+
52+
auto handle = filesystem::open(path, file_mode::read, false);
53+
if (!handle.is_valid)
54+
{
55+
LOG_ERROR("Failed to open terrain file {}", path);
56+
return {};
57+
}
58+
59+
auto line = filesystem::read_line(handle, 511);
60+
uint32_t line_number{};
61+
for (; !line.empty(); line = filesystem::read_line(handle, 511), ++line_number)
62+
{
63+
std::string line_string{line.begin(), line.end()};
64+
trim(line_string);
65+
66+
if (line[0] == '#' || line[0] == '\0')
67+
{
68+
continue;
69+
}
70+
71+
auto split_index = line_string.find_first_of('=');
72+
if (split_index == std::string::npos)
73+
{
74+
LOG_WARN("Potential formatting issue found in file {}, '=' token not found on line number {}.", path, line_number);
75+
continue;
76+
}
77+
78+
auto variable_name = line_string.substr(0, split_index);
79+
trim(variable_name);
80+
81+
auto value = line_string.substr(split_index + 1);
82+
trim(value);
83+
84+
if (!terrain_configuration_members.contains(variable_name))
85+
{
86+
LOG_WARN("Unrecognised terrain configuration arguement: {}", variable_name);
87+
continue;
88+
}
89+
terrain_configuration_members.at(variable_name)(properties, value);
90+
}
91+
92+
if (properties.heightmap != "")
93+
{
94+
image_resource_parameters params{.flip_y = false};
95+
auto heightmap_image = resource_system::load(properties.heightmap, resource::type::image, &params);
96+
if (!heightmap_image || !heightmap_image->data)
97+
{
98+
LOG_ERROR("Could not load heightmap image: {}", properties.heightmap);
99+
}
100+
else
101+
{
102+
auto* image_properties = (texture::properties*)heightmap_image->data;
103+
const auto* pixels = (uint8_t*)image_properties->data;
104+
properties.tiles_x = image_properties->width;
105+
properties.tiles_y = image_properties->height;
106+
107+
const uint32_t count = properties.tiles_x * properties.tiles_y;
108+
properties.height_data.reserve(count);
109+
for (uint32_t i{}; i < 4 * count; i += 4)
110+
{
111+
const auto r = pixels[i + 0];
112+
const auto g = pixels[i + 1];
113+
const auto b = pixels[i + 2];
114+
115+
const float sum = (r + g + b) / (3.f * 255);
116+
properties.height_data.push_back(sum);
117+
}
118+
119+
egkr::resource_system::unload(heightmap_image);
120+
}
121+
}
122+
123+
return properties;
124+
}
125+
}

engine/loaders/terrain_loader.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include "resource_loader.h"
4+
#include "resources/terrain.h"
5+
6+
namespace egkr::loader
7+
{
8+
class terrain : public resource_loader
9+
{
10+
public:
11+
using unique_ptr = std::unique_ptr<terrain>;
12+
static unique_ptr create(const loader_properties& properties);
13+
14+
explicit terrain(const loader_properties& properties);
15+
terrain(const terrain&) = delete;
16+
terrain operator=(const terrain&) = delete;
17+
terrain(terrain&&) = delete;
18+
terrain operator=(terrain&&) = delete;
19+
20+
~terrain() override = default;
21+
22+
resource::shared_ptr load(const std::string& name, void* params) override;
23+
bool unload(const resource::shared_ptr& resource) override;
24+
private:
25+
egkr::terrain::configuration load_configuration_file(const std::string& path);
26+
};
27+
}

engine/renderer/passes/scene_pass.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ namespace egkr::pass
123123

124124
for (const auto& terrain : data.terrain)
125125
{
126-
const auto& world = terrain.transform.lock()->get_world();
127-
shader_system::set_uniform(terrain_shader_locations.model, &world);
126+
if (const auto& world = terrain.transform.lock())
127+
{
128+
const auto& model = world->get_world();
129+
shader_system::set_uniform(terrain_shader_locations.model, &model);
130+
};
128131
}
129132

130133
if (data.terrain.front().is_winding_reversed)

0 commit comments

Comments
 (0)