Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ alp_add_git_repository(stb URL https://github.com/nothings/stb COMMITISH f4a71b1
add_library(stb INTERFACE)
target_include_directories(stb SYSTEM INTERFACE ${stb_SOURCE_DIR})

alp_add_git_repository(tl_expected URL https://github.com/TartanLlama/expected.git COMMITISH v1.1.0 DO_NOT_ADD_SUBPROJECT)
add_library(tl_expected INTERFACE)
target_include_directories(tl_expected SYSTEM INTERFACE ${tl_expected_SOURCE_DIR}/include)

set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "SPDLOG_FMT_EXTERNAL" FORCE)
alp_add_git_repository(spdlog URL https://github.com/gabime/spdlog.git COMMITISH v1.17.0)

Expand All @@ -54,7 +50,7 @@ set(LIBIGL_COPYLEFT_CORE ON)
set(LIBIGL_RESTRICTED_TRIANGLE ON)
alp_add_git_repository(libigl URL https://github.com/libigl/libigl.git COMMITISH v2.6.0)

alp_add_git_repository(radix URL https://github.com/AlpineMapsOrg/radix.git COMMITISH 2ce3484513b826bb11e5433f868b048eaffe3e5d NOT_SYSTEM DEEP_CLONE)
alp_add_git_repository(radix URL https://github.com/AlpineMapsOrg/radix.git COMMITISH 9720bce6399f4581e35edc88f87651f020348b34 NOT_SYSTEM DEEP_CLONE)

set(ALP_CLI_COMPONENT_OPTIONS
ALP_BUILD_SF_MERGER
Expand Down
6 changes: 3 additions & 3 deletions src/dag_builder/encoded.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <type_traits>
#include <vector>

#include <tl/expected.hpp>
#include <expected>
#include <zpp_bits.h>
#include <glm/glm.hpp>
#include <opencv2/core.hpp>
Expand Down Expand Up @@ -165,14 +165,14 @@ auto serialize(Archive &archive, Clustering &clustering) {
}
}

inline tl::expected<void, ::io::Error>
inline std::expected<void, ::io::Error>
save_clustering(const Clustering &clustering,
const std::filesystem::path &path,
const bool make_dirs = true) {
return ::io::write_to_path(clustering, path, make_dirs);
}

inline tl::expected<Clustering, ::io::Error>
inline std::expected<Clustering, ::io::Error>
load_clustering(const std::filesystem::path &path) {
return ::io::read_from_path<Clustering>(path);
}
6 changes: 3 additions & 3 deletions src/dag_builder/thread_safe_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <shared_mutex>
#include <type_traits>

#include <tl/expected.hpp>
#include <expected>

#include "octree/Id.h"

Expand Down Expand Up @@ -33,7 +33,7 @@ class ThreadSafeStorage {
return std::move(this->_storage);
}

tl::expected<value_type, load_error> load(const octree::Id &id) const {
std::expected<value_type, load_error> load(const octree::Id &id) const {
std::shared_lock lock(this->_mutex);
return this->_storage.load(id);
}
Expand All @@ -47,7 +47,7 @@ class ThreadSafeStorage {
return this->_storage.base_path();
}

tl::expected<void, save_error> save(const octree::Id &id, const value_type &value) const {
std::expected<void, save_error> save(const octree::Id &id, const value_type &value) const {
std::unique_lock lock(this->_mutex);
return this->_storage.save(id, value);
}
Expand Down
6 changes: 3 additions & 3 deletions src/mesh_convert/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <filesystem>

#include <glm/glm.hpp>
#include <tl/expected.hpp>
#include <expected>

#include "mesh/SimpleMesh.h"
#include "mesh/io.h"
Expand All @@ -11,7 +11,7 @@

void run(const cli::Args& args) {
LOG_INFO("Loading input mesh...");
const tl::expected<SimpleMesh, mesh::io::LoadMeshError> load_result = mesh::io::load_from_path(args.input_path);
const std::expected<SimpleMesh, mesh::io::LoadMeshError> load_result = mesh::io::load_from_path(args.input_path);
if (!load_result.has_value()) {
LOG_ERROR("Failed to load mesh: {}", load_result.error().description());
return;
Expand All @@ -30,7 +30,7 @@ void run(const cli::Args& args) {
}

LOG_INFO("Writing output mesh...");
const tl::expected<void, mesh::io::SaveMeshError> save_result = mesh::io::save_to_path(mesh, args.output_path);
const std::expected<void, mesh::io::SaveMeshError> save_result = mesh::io::save_to_path(mesh, args.output_path);
if (!save_result.has_value()) {
LOG_ERROR("Failed to save mesh: {}", save_result.error().description());
return;
Expand Down
2 changes: 1 addition & 1 deletion src/sf_builder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ add_library(sfbuilderlib
mesh_builder.cpp
)
target_include_directories(sfbuilderlib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(sfbuilderlib PUBLIC terrainlib spdlog tl_expected)
target_link_libraries(sfbuilderlib PUBLIC terrainlib spdlog)

add_executable(sf-builder main.cpp)
target_link_libraries(sf-builder PRIVATE sfbuilderlib CLI11::CLI11)
55 changes: 32 additions & 23 deletions src/sf_builder/mesh_builder.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <algorithm>
#include <numeric>
#include <ranges>
#include <utility>
#include <vector>

#include <gdal.h>
Expand All @@ -15,7 +16,7 @@
#include "mesh/SimpleMesh.h"
#include "mesh/cleanup.h"
#include "mesh_builder.h"
#include "raster.h"
#include <radix/raster.h>
#include "raw_dataset_reader.h"
#include "srs.h"
#include "mesh/clip.h"
Expand Down Expand Up @@ -50,17 +51,17 @@ glm::dvec2 apply_transform(std::array<double, 6> transform, const glm::tvec2<T>
return result;
}

glm::dvec3 convert_pixel_to_vertex(const float height, const raster::Coords pixel_coords, const RawDatasetReader& reader, const PixelBounds& pixel_bounds) {
glm::dvec3 convert_pixel_to_vertex(const float height, const glm::uvec2 pixel_coords, const RawDatasetReader& reader, const PixelBounds& pixel_bounds) {
const glm::dvec2 point_offset_in_raster(0.5); // Convert pixel coordinates into a point in the dataset's srs.
const glm::dvec2 coords_raster_relative = glm::dvec2(pixel_coords) + point_offset_in_raster;
const glm::dvec2 coords_raster_absolute = coords_raster_relative + glm::dvec2(pixel_bounds.min);
const glm::dvec3 coords_source(reader.transform_pixel_to_srs_point(coords_raster_absolute), height);
return coords_source;
}

SimpleMesh meshify(const raster::Raster<glm::dvec3>& source_points, const raster::Mask& mask) {
SimpleMesh meshify(const radix::Raster<glm::dvec3>& source_points, const radix::RasterMask& mask) {
// Compact the vertex grid into a list of valid ones.
const size_t valid_vertex_count = std::reduce(mask.begin(), mask.end(), 0);
const size_t valid_vertex_count = std::reduce(mask.begin(), mask.end(), size_t(0));
// Check if we even have any valid vertices. Can happen if all of the region is padding.
if (valid_vertex_count == 0) {
return SimpleMesh();
Expand All @@ -69,25 +70,29 @@ SimpleMesh meshify(const raster::Raster<glm::dvec3>& source_points, const raster
std::vector<glm::dvec3> positions;
positions.reserve(valid_vertex_count);

const raster::Raster<size_t> vertex_index_map = raster::transform(source_points, mask, [&](const glm::dvec3 &point) -> size_t {
auto vertex_index_map_result = radix::raster::transform(source_points, mask, [&](const glm::dvec3& point) -> size_t {
const size_t index = positions.size();
positions.push_back(point);
return index;
});
DEBUG_ASSERT(vertex_index_map_result.has_value());
if (!vertex_index_map_result.has_value())
return {};
const auto vertex_index_map = std::move(*vertex_index_map_result);
DEBUG_ASSERT(positions.size() == valid_vertex_count);

// Allocate triangle vector
const size_t max_triangle_count = (source_points.width() - 1) * (source_points.height() - 1) * 2;
std::vector<glm::uvec3> triangles;
triangles.reserve(max_triangle_count);

for (size_t y = 0; y < source_points.height() - 1; y++) {
for (size_t x = 0; x < source_points.width() - 1; x++) {
const std::array<raster::Coords, 4> quad {
raster::Coords{x, y},
raster::Coords{x + 1, y},
raster::Coords{x + 1, y + 1},
raster::Coords{x, y + 1}};
for (unsigned y = 0; y < source_points.height() - 1; y++) {
for (unsigned x = 0; x < source_points.width() - 1; x++) {
const std::array<glm::uvec2, 4> quad {
glm::uvec2{x, y},
glm::uvec2{x + 1, y},
glm::uvec2{x + 1, y + 1},
glm::uvec2{x, y + 1}};

for (uint32_t i = 0; i < 4; i++) {
const auto& v0 = quad[i];
Expand Down Expand Up @@ -142,15 +147,15 @@ radix::geometry::Aabb3d extend_bounds_to_3d(radix::geometry::Aabb2d bounds2d) {
}
}

tl::expected<SimpleMesh, BuildMeshError> build_reference_mesh_tile(
std::expected<SimpleMesh, BuildMeshError> build_reference_mesh_tile(
Dataset &dataset,
const OGRSpatialReference &mesh_srs,
const OGRSpatialReference &tile_srs, const radix::tile::SrsBounds &tile_bounds,
const OGRSpatialReference &texture_srs, radix::tile::SrsBounds &texture_bounds) {
return build_reference_mesh_patch(dataset, mesh_srs, tile_srs, extend_bounds_to_3d(tile_bounds), texture_srs, texture_bounds);
}

tl::expected<SimpleMesh, BuildMeshError> build_reference_mesh_patch(
std::expected<SimpleMesh, BuildMeshError> build_reference_mesh_patch(
Dataset &dataset,
const OGRSpatialReference &mesh_srs,
const OGRSpatialReference &clip_srs, const radix::geometry::Aabb3d &clip_bounds,
Expand All @@ -171,43 +176,47 @@ tl::expected<SimpleMesh, BuildMeshError> build_reference_mesh_patch(
radix::geometry::Aabb2i pixel_bounds = reader.transform_srs_bounds_to_pixel_bounds(target_bounds_in_source_srs);
add_border_to_aabb(pixel_bounds, Border(1));
LOG_TRACE("Reading pixels [({}, {})-({}, {})] from dataset", pixel_bounds.min.x, pixel_bounds.min.y, pixel_bounds.max.x, pixel_bounds.max.y);
const std::optional<raster::HeightMap> read_result = reader.read_data_in_pixel_bounds_clamped(pixel_bounds);
if (!read_result.has_value() || read_result->size() == 0) {
return tl::unexpected(BuildMeshError::OutOfBounds);
auto read_result = reader.read_data_in_pixel_bounds_clamped(pixel_bounds);
if (!read_result.has_value() || read_result->buffer().empty()) {
return std::unexpected(BuildMeshError::OutOfBounds);
}
const raster::HeightMap height_map = read_result.value();
const radix::Raster<float> height_map = std::move(*read_result);

LOG_TRACE("Finding valid pixels");
const float no_data_value = reader.get_no_data_value();
const raster::Mask valid_mask = raster::transform(height_map, [=](const float height) {
const radix::RasterMask valid_mask = radix::raster::transform(height_map, [=](const float height) {
return height != no_data_value;
});

LOG_TRACE("Transforming pixels to vertices");
const raster::Raster<glm::dvec3> source_points = raster::transform(height_map, valid_mask, [&](const float height, const raster::Coords& coords) {
auto source_points_result = radix::raster::transform(height_map, valid_mask, [&](const float height, const glm::uvec2& coords) {
return convert_pixel_to_vertex(height, coords, reader, pixel_bounds);
});
DEBUG_ASSERT(source_points_result.has_value());
if (!source_points_result.has_value())
return std::unexpected(BuildMeshError::EmptyRegion);
const auto source_points = std::move(*source_points_result);

LOG_TRACE("Generating triangles");
SimpleMesh mesh_in_source_srs = meshify(source_points, valid_mask);
// Check if we even have any valid vertices. Can happen if all of the region is padding.
if (mesh_in_source_srs.vertex_count() == 0 || mesh_in_source_srs.face_count() == 0) {
return tl::unexpected(BuildMeshError::EmptyRegion);
return std::unexpected(BuildMeshError::EmptyRegion);
}

// Fast check if all vertices will be clipped
const radix::geometry::Aabb3d actual_source_bounds = calculate_bounds(mesh_in_source_srs);
const radix::geometry::Aabb3d approx_clip_bounds = srs::encompassing_bounds_transfer(source_srs, clip_srs, actual_source_bounds);
if (!radix::geometry::intersect(approx_clip_bounds, clip_bounds)) {
return tl::unexpected(BuildMeshError::EmptyRegion);
return std::unexpected(BuildMeshError::EmptyRegion);
}

LOG_TRACE("Clipping mesh based on target bounds");
const SimpleMesh mesh_in_clip_srs = transform_mesh(std::move(mesh_in_source_srs), source_srs, clip_srs);
SimpleMesh clipped_mesh = mesh::clip_on_bounds(mesh_in_clip_srs, clip_bounds);
// Check if there are any vertices left
if (clipped_mesh.vertex_count() == 0 || clipped_mesh.face_count() == 0) {
return tl::unexpected(BuildMeshError::EmptyRegion);
return std::unexpected(BuildMeshError::EmptyRegion);
}

// TODO: move this to another function?
Expand Down
4 changes: 2 additions & 2 deletions src/sf_builder/mesh_builder.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <tl/expected.hpp>
#include <expected>

#include "Dataset.h"
#include "srs.h"
Expand All @@ -17,7 +17,7 @@ enum class BuildMeshError {
std::ostream &operator<<(std::ostream &os, BuildMeshError error);

/// Builds a mesh from the given height dataset.
tl::expected<SimpleMesh, BuildMeshError> build_reference_mesh_patch(
std::expected<SimpleMesh, BuildMeshError> build_reference_mesh_patch(
Dataset &dataset,
const OGRSpatialReference &mesh_srs,
const OGRSpatialReference &clip_srs, const radix::geometry::Aabb3d &clip_bounds,
Expand Down
Loading
Loading