TerraForge3D  2.3.1
3D Terrain And Landscape Generator
Heightmap.cpp
1#include "Heightmap.h"
2#include <string>
3#include <cmath>
4#include <iostream>
5
6#include <stb/stb_image.h>
7#include <glad/glad.h>
8
9Heightmap::Heightmap(const std::string path)
10{
11 m_Path = path;
12 int width, height, channels;
13 stbi_set_flip_vertically_on_load(0);
14 void* data = stbi_load_16(path.c_str(), &width, &height, &channels, 1);
15 if (!data)
16 {
17 std::cout << "Failed to load heightmap (" << path << "): " << stbi_failure_reason() << std::endl;
18 return;
19 }
20 m_Data = static_cast<uint16_t*>(data);
21 m_Width = width;
22 m_Height = height;
23
24 glGenTextures(1, &m_RendererID);
25 glBindTexture(GL_TEXTURE_2D, m_RendererID);
26 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
27
28 std::vector<uint8_t> texData;
29 for (int i = 0; i < width * height; ++i)
30 {
31 uint8_t value = static_cast<float>(m_Data[i]) / (2 << 15) * 255;
32 texData.push_back(value);
33 texData.push_back(value);
34 texData.push_back(value);
35 texData.push_back(255);
36 }
37
38 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.data());
39 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
40 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
41 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
42 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
43 glGenerateMipmap(GL_TEXTURE_2D);
44}
45
46Heightmap::~Heightmap()
47{
48 if (m_Data)
49 {
50 glDeleteTextures(1, &m_RendererID);
51 free(m_Data);
52 }
53}
54
55uint16_t Heightmap::Sample(float x, float y, bool interpolated) const
56{
57 auto lerp = [](float a, float b, double t) { return a + (b - a) * t; };
58 auto clamp = [](float x, float min, float max) {
59 return x > max ? max : (x < min) ? min : x;
60 };
61
62 clamp(x, 0, 1);
63 clamp(y, 0, 1);
64
65 if (!interpolated)
66 return Get(x * (m_Width - 1), y * (m_Height - 1));
67
68 float x1 = std::floor(x * (m_Width - 1));
69 float y1 = std::floor(y * (m_Height - 1));
70 float x2 = x1 + 1;
71 float y2 = y1 + 1;
72
73 float xp = x * m_Width - x1;
74 float yp = y * m_Height - y1;
75
76 float h11 = Get(x1, y1);
77 float h21 = Get(x2, y1);
78 float h12 = Get(x1, y2);
79 float h22 = Get(x2, y2);
80
81 auto v1 = lerp(h11, h21, xp);
82 auto v2 = lerp(h12, h22, xp);
83 auto h = lerp(v1, v2, yp);
84 if (h < 0)
85 h = 0;
86 return (uint16_t) h;
87
88}
89
90uint16_t Heightmap::Get(uint32_t x, uint32_t y) const
91{
92 return m_Data[x + m_Width * y];
93}
@ value
the parser finished reading a JSON value