25 #include <glm/mat4x4.hpp>
27 #include "eng3d/rivers.hpp"
28 #include "eng3d/texture.hpp"
29 #include "eng3d/state.hpp"
30 #include "eng3d/curve.hpp"
31 #include "eng3d/shader.hpp"
32 #include "eng3d/camera.hpp"
41 mipmap_options.
wrap_s = Eng3D::TextureOptions::Wrap::REPEAT;
42 mipmap_options.wrap_t = Eng3D::TextureOptions::Wrap::REPEAT;
43 mipmap_options.min_filter = Eng3D::TextureOptions::Filter::LINEAR_MIPMAP;
44 mipmap_options.mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
45 mipmap_options.internal_format = Eng3D::TextureOptions::Format::SRGB;
48 line_shader = std::make_unique<Eng3D::OpenGL::Program>();
50 auto vs_shader = *s.builtin_shaders[
"vs_3d"].get();
51 line_shader->attach_shader(vs_shader);
53 line_shader->attach_shader(fs_shader);
64 std::unique_ptr<std::vector<glm::vec3>>
river;
66 : river{ new
std::vector<glm::vec3> }
72 : river{
std::make_unique<
std::vector<glm::vec3>>(_river) }
80 void Eng3D::Rivers::get_river(std::vector<glm::vec3>& river,
int current_index,
int prev_index, uint32_t* pixels,
int width,
int height) {
81 int x = current_index % width;
82 int y = current_index / width;
83 river.push_back(glm::vec3(x, y, -0.05));
85 const auto check_neighbor = [
this, current_index, prev_index, pixels, width, height](std::vector<glm::vec3>& _river,
int new_x,
int new_y) {
86 if(new_x < 0 || new_y < 0 || new_x >= width || new_y >= height)
88 int new_index = new_x + new_y * width;
89 if(new_index == prev_index)
return;
91 uint32_t neighbor_color = pixels[new_index];
92 if(neighbor_color == 0xFFFF0000) {
93 this->get_river(_river, new_index, current_index, pixels, width, height);
97 check_neighbor(river, x - 1, y + 0);
98 check_neighbor(river, x + 1, y + 0);
99 check_neighbor(river, x + 0, y + 1);
100 check_neighbor(river, x + 0, y - 1);
104 void Eng3D::Rivers::build_rivers() {
107 auto river_tex = s.tex_man.load(s.package_man.get_unique(
"map/river.png"), no_drop_options);
109 std::vector<int> rivers_starts;
110 auto pixels = river_tex->buffer.get();
111 for(
size_t y = 0; y < river_tex->height; y++)
112 for(
size_t x = 0; x < river_tex->width; x++)
113 if(pixels[x + y * river_tex->width] == 0xff0000ff)
114 rivers_starts.push_back(x + y * river_tex->width);
117 for(
size_t i = 0; i < rivers_starts.size(); i++) {
118 std::vector<glm::vec3> river;
119 this->get_river(river, rivers_starts[i], -1, pixels, river_tex->width, river_tex->height);
121 const size_t length = river.size();
122 if(length < 2)
continue;
124 std::vector<glm::vec3> mid_points(length + 3);
125 mid_points[0] = river[0];
126 mid_points[1] = river[0];
127 for(
size_t j = 0; j < length - 1; j++)
128 mid_points[j + 2] = 0.5f * (river[j] + river[j + 1]);
129 mid_points[length + 1] = river[length - 1];
130 mid_points[length + 2] = river[length - 1];
132 std::vector<glm::vec3> curve_points;
136 glm::vec3 p0, p1, p2, p3;
137 for(
size_t j = 1; j < mid_points.size() - 2; j++) {
138 p0 = mid_points[j - 1];
140 p2 = mid_points[j + 1];
141 p3 = mid_points[j + 2];
143 float step = 1 / 10.;
144 for(
float t = 1.f; t > 0.f; t -= step) {
150 glm::vec3 pt(0, 0, 0);
151 pt += p0 * (+1.f / 6.f * glm::pow(t0, 3.f) + 2.f * t0 + 4.f / 3.f + glm::pow(t0, 2.f));
152 pt += p3 * (-1.f / 6.f * glm::pow(t3, 3.f) - 2.f * t3 + 4.f / 3.f + glm::pow(t3, 2.f));
153 pt += p1 * (-1.f / 2.f * glm::pow(t1, 3.f) - glm::pow(t1, 2.f) + 2.f / 3.f);
154 pt += p2 * (+1.f / 2.f * glm::pow(t2, 3.f) - glm::pow(t2, 2.f) + 2.f / 3.f);
155 curve_points.push_back(pt);
159 std::vector<glm::vec3> normals(curve_points.size() - 1, glm::vec3(0, 0, 1));
160 auto curve = std::make_unique<Eng3D::Curve>(curve_points, normals, 1.0f);
161 this->curves.push_back(std::move(curve));
168 glm::mat4 model(1.f);
169 line_shader->set_uniform(
"model", model);
171 line_shader->set_uniform(
"view", camera.
get_view());
172 line_shader->set_texture(0,
"water_texture", *water_tex);
173 for(
auto& curve : curves)
std::unique_ptr< std::vector< glm::vec3 > > river
ConnectedNode(const std::vector< glm::vec3 > &_river)
virtual glm::mat4 get_view() const =0
Get the view matrix.
virtual glm::mat4 get_projection() const
Get the projection matrix.
std::shared_ptr< Eng3D::IO::Asset::Base > get_unique(const Eng3D::IO::Path &path)
Obtaining an unique asset means the "first-found" policy applies.
Rivers(Eng3D::State &s, bool lazy_init=true)
Construct a new Eng3D::Rivers object.
void draw(const Eng3D::Camera &camera)
Eng3D::TextureManager tex_man
Eng3D::IO::PackageManager package_man
std::shared_ptr< Eng3D::Texture > load(const std::string &path, TextureOptions options=default_options)
Finds a texture in the list of a texture manager if the texture is already in the list we load the sa...
enum Eng3D::TextureOptions::Wrap wrap_s