summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan.goodliffe@octal.co.uk>2026-03-09 12:17:41 +0000
committerDan Goodliffe <dan.goodliffe@octal.co.uk>2026-03-09 12:18:59 +0000
commit57b27dada7e6968a6081207d9b466bf7e842039b (patch)
tree0acfb043f44c789fc5ee9696ac34ea9ed7fed767
parentRemove identifier naming lint comments, gl* is fine (diff)
downloadilt-57b27dada7e6968a6081207d9b466bf7e842039b.tar.bz2
ilt-57b27dada7e6968a6081207d9b466bf7e842039b.tar.xz
ilt-57b27dada7e6968a6081207d9b466bf7e842039b.zip
Specialise glTexture::savePosition
Normalises the range of position information into the range 0-255 so the resulting image is remotely useful.
-rw-r--r--gfx/gl/glTexture.cpp71
-rw-r--r--gfx/models/tga.h9
-rw-r--r--test/test-render.cpp2
3 files changed, 59 insertions, 23 deletions
diff --git a/gfx/gl/glTexture.cpp b/gfx/gl/glTexture.cpp
index e334d5e..0bc3d62 100644
--- a/gfx/gl/glTexture.cpp
+++ b/gfx/gl/glTexture.cpp
@@ -1,6 +1,8 @@
#include "glTexture.h"
+#include "config/types.h"
#include "filesystem.h"
#include "gfx/models/tga.h"
+#include "maths.h"
#include <fcntl.h>
#include <ranges>
#include <sys/mman.h>
@@ -95,31 +97,37 @@ Impl::glTextureDims<Dims>::image(const GLenum format, const GLenum type, const v
namespace {
template<glm::length_t Dims>
requires(Dims >= 1 && Dims <= 3)
+ size_t
+ areaOf(glm::vec<Dims, GLsizei> size)
+ {
+ size_t area = 1;
+ for (auto dim = 0; dim < Dims; ++dim) {
+ area *= static_cast<size_t>(size[dim]);
+ }
+ return area;
+ }
+
+ template<glm::length_t Dims, glm::length_t channels>
+ requires(Dims >= 1 && Dims <= 3)
void
- save(const Impl::glTextureDims<Dims> & texture, const GLenum format, const GLenum type, uint8_t channels,
- const char * path, uint8_t tgaFormat)
+ save(const Impl::glTextureDims<Dims> & texture, const GLenum format, const GLenum type, const char * path,
+ uint8_t tgaFormat)
{
const auto size = texture.getSize();
- const auto area = [size]() {
- size_t area = 1;
- for (auto dim = 0; dim < Dims; ++dim) {
- area *= static_cast<size_t>(size[dim]);
- }
- return area;
- }();
+ const auto area = areaOf(size);
size_t dataSize = area * channels;
- const size_t fileSize = dataSize + sizeof(TGAHead);
+ const size_t fileSize = dataSize + sizeof(TGAHead<channels>);
filesystem::fh out {path, O_RDWR | O_CREAT, 0660};
out.truncate(fileSize);
auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED);
- *tga.get<TGAHead>() = {
+ auto outTga = tga.get<TGAHead<channels>>();
+ *outTga = {
.format = tgaFormat,
- .size = {size.x, 1 * (area / static_cast<size_t>(size.x))},
- .pixelDepth = static_cast<uint8_t>(8 * channels),
+ .size = {size.x, (area / static_cast<size_t>(size.x))},
};
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glGetTextureImage(texture, 0, format, type, static_cast<GLsizei>(dataSize), tga.get<TGAHead>() + 1);
+ glGetTextureImage(texture, 0, format, type, static_cast<GLsizei>(dataSize), outTga->data);
tga.msync(MS_ASYNC);
}
}
@@ -129,7 +137,7 @@ template<glm::length_t Dims>
void
Impl::glTextureDims<Dims>::saveColour(const char * path) const
{
- save(*this, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2);
+ save<Dims, 3>(*this, GL_BGR, GL_UNSIGNED_BYTE, path, 2);
}
template<glm::length_t Dims>
@@ -137,7 +145,34 @@ template<glm::length_t Dims>
void
Impl::glTextureDims<Dims>::savePosition(const char * path) const
{
- save(*this, GL_BGR_INTEGER, GL_UNSIGNED_BYTE, 3, path, 2);
+ const auto size = getSize();
+ const auto area = areaOf(size);
+ size_t dataSize = area * sizeof(TGAHead<3>::PixelType);
+ const size_t fileSize = dataSize + sizeof(TGAHead<3>);
+
+ filesystem::fh out {path, O_RDWR | O_CREAT, 0660};
+ out.truncate(fileSize);
+ auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED);
+ auto outTga = tga.get<TGAHead<3>>();
+ *outTga = {
+ .format = 2,
+ .size = {size.x, (area / static_cast<size_t>(size.x))},
+ };
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ std::vector<GlobalPosition3D> raw {area};
+ glGetTextureImage(
+ name, 0, GL_BGR_INTEGER, GL_INT, static_cast<GLsizei>(sizeof(GlobalPosition3D) * area), raw.data());
+ using Comp = GlobalPosition3D (*)(const GlobalPosition3D &, const GlobalPosition3D &);
+ auto notZero = std::views::filter([](const GlobalPosition3D & pos) {
+ return pos != GlobalPosition3D {};
+ });
+ const auto minPos = *std::ranges::fold_left_first(raw | notZero, static_cast<Comp>(&glm::min));
+ const auto maxPos = *std::ranges::fold_left_first(raw | notZero, static_cast<Comp>(&glm::max));
+ const auto rangePos = difference(maxPos, minPos);
+ std::ranges::transform(raw, outTga->data, [minPos, rangePos](const GlobalPosition3D & pos) {
+ return GlobalPosition3D(255.F * (difference(pos, minPos) / rangePos));
+ });
+ tga.msync(MS_ASYNC);
}
template<glm::length_t Dims>
@@ -145,7 +180,7 @@ template<glm::length_t Dims>
void
Impl::glTextureDims<Dims>::saveDepth(const char * path) const
{
- save(*this, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 1, path, 3);
+ save<Dims, 1>(*this, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, path, 3);
}
template<glm::length_t Dims>
@@ -153,7 +188,7 @@ template<glm::length_t Dims>
void
Impl::glTextureDims<Dims>::saveNormal(const char * path) const
{
- save(*this, GL_BGR, GL_BYTE, 3, path, 2);
+ save<Dims, 3>(*this, GL_BGR, GL_BYTE, path, 2);
}
template struct Impl::glTextureDims<1>;
diff --git a/gfx/models/tga.h b/gfx/models/tga.h
index 3d072fb..955e5e1 100644
--- a/gfx/models/tga.h
+++ b/gfx/models/tga.h
@@ -3,14 +3,15 @@
#include <cstdint>
#include <glm/vec2.hpp>
-struct TGAHead {
+template<glm::length_t Channels> struct TGAHead {
using XY = glm::vec<2, uint16_t>;
+ using PixelType = glm::vec<Channels, uint8_t>;
+
uint8_t idLength {}, colorMapType {}, format {};
uint16_t __attribute__((packed)) colorMapFirst {}, colorMapLength {};
uint8_t colorMapEntrySize {};
XY origin {}, size {};
- uint8_t pixelDepth {};
+ uint8_t pixelDepth {8 * Channels};
uint8_t descriptor {};
+ PixelType data[1] {};
};
-
-static_assert(sizeof(TGAHead) == 18);
diff --git a/test/test-render.cpp b/test/test-render.cpp
index 0b47ce8..35d71f3 100644
--- a/test/test-render.cpp
+++ b/test/test-render.cpp
@@ -40,7 +40,7 @@ namespace {
public:
TestScene()
{
- terrain->point(GeoData::VertexHandle {517}).z = 100'000;
+ terrain->point(GeoData::VertexHandle {517}).z = 40'000;
terrain->generateMeshes();
gameState->assets = AssetFactory::loadAll(RESDIR);
brush47rvc = gameState->assets.at("brush-47").dynamicCast<RailVehicleClass>();