Skip to content

Commit

Permalink
Fix #258: Add per pixel setters for storage. Also fix inlining of fun…
Browse files Browse the repository at this point in the history
…ctions
  • Loading branch information
TokisanGames committed Nov 28, 2023
1 parent 0a608b0 commit 6ec4f7b
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 69 deletions.
4 changes: 0 additions & 4 deletions src/geoclipmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
// Private Functions
///////////////////////////

int GeoClipMap::_patch_2d(int x, int y, int res) {
return y * res + x;
}

RID GeoClipMap::_create_mesh(PackedVector3Array p_vertices, PackedInt32Array p_indices, AABB p_aabb) {
Array arrays;
arrays.resize(RenderingServer::ARRAY_MAX);
Expand Down
6 changes: 6 additions & 0 deletions src/geoclipmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ class GeoClipMap {
static Vector<RID> generate(int p_resolution, int p_clipmap_levels);
};

// Inline Functions

inline int GeoClipMap::_patch_2d(int x, int y, int res) {
return y * res + x;
}

#endif // GEOCLIPMAP_CLASS_H
2 changes: 1 addition & 1 deletion src/terrain_3d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di
// Get bit field from pixel
uint32_t base_id = Util::get_base(src.r);
uint32_t overlay_id = Util::get_overlay(src.r);
real_t blend = real_t(Util::get_blend(src.r)) / 255.0f; // 8 bits #22-15
real_t blend = real_t(Util::get_blend(src.r)) / 255.0f;
bool hole = Util::is_hole(src.r);
bool navigation = Util::is_nav(src.r);
bool autoshader = Util::is_auto(src.r);
Expand Down
4 changes: 2 additions & 2 deletions src/terrain_3d_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ class Terrain3DEditor : public Object {
Terrain3DEditor();
~Terrain3DEditor();

inline void set_terrain(Terrain3D *p_terrain) { _terrain = p_terrain; }
inline Terrain3D *get_terrain() const { return _terrain; }
void set_terrain(Terrain3D *p_terrain) { _terrain = p_terrain; }
Terrain3D *get_terrain() const { return _terrain; }

void set_brush_data(Dictionary data);
void set_tool(Tool p_tool);
Expand Down
112 changes: 64 additions & 48 deletions src/terrain_3d_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Terrain3DStorage::~Terrain3DStorage() {
// Lots of the upgrade process requires this to run first
// It only runs if the version is saved in the file, which only happens if it was
// different from the in the file is different from _version
inline void Terrain3DStorage::set_version(real_t p_version) {
void Terrain3DStorage::set_version(real_t p_version) {
LOG(INFO, vformat("%.3f", p_version));
_version = p_version;
if (_version >= 0.841f) {
Expand All @@ -51,12 +51,12 @@ inline void Terrain3DStorage::set_version(real_t p_version) {
}
}

inline void Terrain3DStorage::set_save_16_bit(bool p_enabled) {
void Terrain3DStorage::set_save_16_bit(bool p_enabled) {
LOG(INFO, p_enabled);
_save_16_bit = p_enabled;
}

inline void Terrain3DStorage::set_height_range(Vector2 p_range) {
void Terrain3DStorage::set_height_range(Vector2 p_range) {
LOG(INFO, vformat("%.2v", p_range));
_height_range = p_range;
}
Expand Down Expand Up @@ -450,6 +450,24 @@ void Terrain3DStorage::set_color_maps(const TypedArray<Image> &p_maps) {
force_update_maps(TYPE_COLOR);
}

void Terrain3DStorage::set_pixel(MapType p_map_type, Vector3 p_global_position, Color p_pixel) {
if (p_map_type < 0 || p_map_type >= TYPE_MAX) {
LOG(ERROR, "Specified map type out of range");
return;
}
int region = get_region_index(p_global_position);
if (region < 0 || region >= _region_offsets.size()) {
return;
}
Ref<Image> map = get_map_region(p_map_type, region);
Vector2i global_offset = Vector2i(get_region_offsets()[region]) * _region_size;
Vector2i img_pos = Vector2i(
Vector2(p_global_position.x - global_offset.x,
p_global_position.z - global_offset.y)
.floor());
map->set_pixelv(img_pos, p_pixel);
}

Color Terrain3DStorage::get_pixel(MapType p_map_type, Vector3 p_global_position) {
if (p_map_type < 0 || p_map_type >= TYPE_MAX) {
LOG(ERROR, "Specified map type out of range");
Expand All @@ -468,43 +486,6 @@ Color Terrain3DStorage::get_pixel(MapType p_map_type, Vector3 p_global_position)
return map->get_pixelv(img_pos);
}

Color Terrain3DStorage::get_color(Vector3 p_global_position) {
Color clr = get_pixel(TYPE_COLOR, p_global_position);
clr.a = 1.0;
return clr;
}

/**
* Returns the location of a terrain vertex at a certain LOD.
* p_lod (0-8): Determines how many heights around the given global position will be sampled.
* p_filter:
* HEIGHT_FILTER_NEAREST: Samples the height map at the exact coordinates given.
* HEIGHT_FILTER_MINIMUM: Samples (1 << p_lod) ** 2 heights around the given coordinates and returns the lowest.
* p_global_position: X and Z coordinates of the vertex. Heights will be sampled around these coordinates.
*/
Vector3 Terrain3DStorage::get_mesh_vertex(int32_t p_lod, HeightFilter p_filter, Vector3 p_global_position) {
LOG(INFO, "Calculating vertex location");
int32_t step = 1 << CLAMP(p_lod, 0, 8);
real_t height = 0.0;
switch (p_filter) {
case HEIGHT_FILTER_NEAREST: {
height = get_height(p_global_position);
} break;
case HEIGHT_FILTER_MINIMUM: {
height = get_height(p_global_position);
for (int32_t dx = -step / 2; dx < step / 2; dx += 1) {
for (int32_t dz = -step / 2; dz < step / 2; dz += 1) {
real_t h = get_height(p_global_position + Vector3(dx, 0.0, dz));
if (h < height) {
height = h;
}
}
}
} break;
}
return Vector3(p_global_position.x, height, p_global_position.z);
}

/**
* Returns:
* X = base index
Expand All @@ -516,13 +497,11 @@ Vector3 Terrain3DStorage::get_mesh_vertex(int32_t p_lod, HeightFilter p_filter,
* value of .3-.5, otherwise it's the base texture.
**/
Vector3 Terrain3DStorage::get_texture_id(Vector3 p_global_position) {
// Get bit field from pixel
uint32_t bits;
*(float *)&bits = get_pixel(TYPE_CONTROL, p_global_position).r; // Must be 32-bit float, not double/real
uint32_t base_index = bits >> 27u & 0x1Fu;
uint32_t overlay_index = bits >> 22u & 0x1Fu;
real_t blend = real_t(bits >> 14u & 0xFFu) / 255.0f;
return Vector3(real_t(base_index), real_t(overlay_index), blend);
float src = get_pixel(TYPE_CONTROL, p_global_position).r; // Must be 32-bit float, not double/real
uint32_t base_id = Util::get_base(src);
uint32_t overlay_id = Util::get_overlay(src);
real_t blend = real_t(Util::get_blend(src)) / 255.0f;
return Vector3(real_t(base_id), real_t(overlay_id), blend);
}

/**
Expand Down Expand Up @@ -976,6 +955,37 @@ Ref<Image> Terrain3DStorage::layered_to_image(MapType p_map_type) {
return img;
}

/**
* Returns the location of a terrain vertex at a certain LOD.
* p_lod (0-8): Determines how many heights around the given global position will be sampled.
* p_filter:
* HEIGHT_FILTER_NEAREST: Samples the height map at the exact coordinates given.
* HEIGHT_FILTER_MINIMUM: Samples (1 << p_lod) ** 2 heights around the given coordinates and returns the lowest.
* p_global_position: X and Z coordinates of the vertex. Heights will be sampled around these coordinates.
*/
Vector3 Terrain3DStorage::get_mesh_vertex(int32_t p_lod, HeightFilter p_filter, Vector3 p_global_position) {
LOG(INFO, "Calculating vertex location");
int32_t step = 1 << CLAMP(p_lod, 0, 8);
real_t height = 0.0;
switch (p_filter) {
case HEIGHT_FILTER_NEAREST: {
height = get_height(p_global_position);
} break;
case HEIGHT_FILTER_MINIMUM: {
height = get_height(p_global_position);
for (int32_t dx = -step / 2; dx < step / 2; dx += 1) {
for (int32_t dz = -step / 2; dz < step / 2; dz += 1) {
real_t h = get_height(p_global_position + Vector3(dx, 0.0, dz));
if (h < height) {
height = h;
}
}
}
} break;
}
return Vector3(p_global_position.x, height, p_global_position.z);
}

Vector3 Terrain3DStorage::get_normal(Vector3 p_global_position) {
real_t left = get_height(p_global_position + Vector3(-1.0f, 0.0f, 0.0f));
real_t right = get_height(p_global_position + Vector3(1.0f, 0.0f, 0.0f));
Expand Down Expand Up @@ -1088,12 +1098,16 @@ void Terrain3DStorage::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_control_maps"), &Terrain3DStorage::get_control_maps);
ClassDB::bind_method(D_METHOD("set_color_maps", "maps"), &Terrain3DStorage::set_color_maps);
ClassDB::bind_method(D_METHOD("get_color_maps"), &Terrain3DStorage::get_color_maps);
ClassDB::bind_method(D_METHOD("set_pixel", "map_type", "global_position", "pixel"), &Terrain3DStorage::set_pixel);
ClassDB::bind_method(D_METHOD("get_pixel", "map_type", "global_position"), &Terrain3DStorage::get_pixel);
ClassDB::bind_method(D_METHOD("set_height", "global_position", "height"), &Terrain3DStorage::set_height);
ClassDB::bind_method(D_METHOD("get_height", "global_position"), &Terrain3DStorage::get_height);
ClassDB::bind_method(D_METHOD("set_color", "global_position", "color"), &Terrain3DStorage::set_color);
ClassDB::bind_method(D_METHOD("get_color", "global_position"), &Terrain3DStorage::get_color);
ClassDB::bind_method(D_METHOD("set_control", "global_position", "control"), &Terrain3DStorage::set_control);
ClassDB::bind_method(D_METHOD("get_control", "global_position"), &Terrain3DStorage::get_control);
ClassDB::bind_method(D_METHOD("set_roughness", "global_position", "roughness"), &Terrain3DStorage::set_roughness);
ClassDB::bind_method(D_METHOD("get_roughness", "global_position"), &Terrain3DStorage::get_roughness);
ClassDB::bind_method(D_METHOD("get_mesh_vertex", "lod", "filter", "global_position"), &Terrain3DStorage::get_mesh_vertex);
ClassDB::bind_method(D_METHOD("get_texture_id", "global_position"), &Terrain3DStorage::get_texture_id);
ClassDB::bind_method(D_METHOD("force_update_maps", "map_type"), &Terrain3DStorage::force_update_maps, DEFVAL(TYPE_MAX));

Expand All @@ -1102,6 +1116,8 @@ void Terrain3DStorage::_bind_methods() {
ClassDB::bind_method(D_METHOD("import_images", "images", "global_position", "offset", "scale"), &Terrain3DStorage::import_images, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("export_image", "file_name", "map_type"), &Terrain3DStorage::export_image);
ClassDB::bind_method(D_METHOD("layered_to_image", "map_type"), &Terrain3DStorage::layered_to_image);

ClassDB::bind_method(D_METHOD("get_mesh_vertex", "lod", "filter", "global_position"), &Terrain3DStorage::get_mesh_vertex);
ClassDB::bind_method(D_METHOD("get_normal", "global_position"), &Terrain3DStorage::get_normal);

int ro_flags = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY;
Expand Down
74 changes: 60 additions & 14 deletions src/terrain_3d_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ class Terrain3DStorage : public Resource {
Terrain3DStorage();
~Terrain3DStorage();

inline void set_version(real_t p_version);
inline real_t get_version() const { return _version; }
inline void set_save_16_bit(bool p_enabled);
inline bool get_save_16_bit() const { return _save_16_bit; }
void set_version(real_t p_version);
real_t get_version() const { return _version; }
void set_save_16_bit(bool p_enabled);
bool get_save_16_bit() const { return _save_16_bit; }

inline void set_height_range(Vector2 p_range);
inline Vector2 get_height_range() const { return _height_range; }
void set_height_range(Vector2 p_range);
Vector2 get_height_range() const { return _height_range; }
void update_heights(real_t p_height);
void update_heights(Vector2 p_heights);
void update_height_range();
Expand All @@ -129,7 +129,7 @@ class Terrain3DStorage : public Resource {
int get_region_count() const { return _region_offsets.size(); }
Vector2i get_region_offset(Vector3 p_global_position);
int get_region_index(Vector3 p_global_position);
bool has_region(Vector3 p_global_position) { return get_region_index(p_global_position) != -1; }
bool has_region(Vector3 p_global_position);
Error add_region(Vector3 p_global_position, const TypedArray<Image> &p_images = TypedArray<Image>(), bool p_update = true);
void remove_region(Vector3 p_global_position, bool p_update = true);
void update_regions(bool force_emit = false);
Expand All @@ -146,12 +146,16 @@ class Terrain3DStorage : public Resource {
TypedArray<Image> get_control_maps() const { return _control_maps; }
void set_color_maps(const TypedArray<Image> &p_maps);
TypedArray<Image> get_color_maps() const { return _color_maps; }
void set_pixel(MapType p_map_type, Vector3 p_global_position, Color p_pixel);
Color get_pixel(MapType p_map_type, Vector3 p_global_position);
inline real_t get_height(Vector3 p_global_position) { return get_pixel(TYPE_HEIGHT, p_global_position).r; }
inline Color get_color(Vector3 p_global_position);
inline Color get_control(Vector3 p_global_position) { return get_pixel(TYPE_CONTROL, p_global_position); }
inline real_t get_roughness(Vector3 p_global_position) { return get_pixel(TYPE_COLOR, p_global_position).a; }
Vector3 get_mesh_vertex(int32_t p_lod, HeightFilter p_filter, Vector3 p_global_position);
void set_height(Vector3 p_global_position, real_t p_height);
real_t get_height(Vector3 p_global_position);
void set_color(Vector3 p_global_position, Color p_color);
Color get_color(Vector3 p_global_position);
void set_control(Vector3 p_global_position, uint32_t p_control);
uint32_t get_control(Vector3 p_global_position);
void set_roughness(Vector3 p_global_position, real_t p_roughness);
real_t get_roughness(Vector3 p_global_position);
Vector3 get_texture_id(Vector3 p_global_position);
TypedArray<Image> sanitize_maps(MapType p_map_type, const TypedArray<Image> &p_maps);
void force_update_maps(MapType p_map = TYPE_MAX);
Expand All @@ -168,9 +172,8 @@ class Terrain3DStorage : public Resource {
Ref<Image> layered_to_image(MapType p_map_type);

// Utility
Vector3 get_mesh_vertex(int32_t p_lod, HeightFilter p_filter, Vector3 p_global_position);
Vector3 get_normal(Vector3 global_position);

// Testing
void print_audit_data();

// DEPRECATED 0.8.3, remove 0.9
Expand All @@ -186,4 +189,47 @@ VARIANT_ENUM_CAST(Terrain3DStorage::MapType);
VARIANT_ENUM_CAST(Terrain3DStorage::RegionSize);
VARIANT_ENUM_CAST(Terrain3DStorage::HeightFilter);

// Inline Functions

inline bool Terrain3DStorage::has_region(Vector3 p_global_position) {
return get_region_index(p_global_position) != -1;
}

inline void Terrain3DStorage::set_height(Vector3 p_global_position, real_t p_height) {
set_pixel(TYPE_HEIGHT, p_global_position, Color(p_height, 0., 0., 1.));
}

inline real_t Terrain3DStorage::get_height(Vector3 p_global_position) {
return get_pixel(TYPE_HEIGHT, p_global_position).r;
}

inline void Terrain3DStorage::set_color(Vector3 p_global_position, Color p_color) {
p_color.a = get_roughness(p_global_position);
set_pixel(TYPE_COLOR, p_global_position, p_color);
}

inline Color Terrain3DStorage::get_color(Vector3 p_global_position) {
Color clr = get_pixel(TYPE_COLOR, p_global_position);
clr.a = 1.0f;
return clr;
}

inline void Terrain3DStorage::set_control(Vector3 p_global_position, uint32_t p_control) {
set_pixel(TYPE_CONTROL, p_global_position, Color(Util::as_float(p_control), 0.f, 0.f, 1.f));
}

inline uint32_t Terrain3DStorage::get_control(Vector3 p_global_position) {
return Util::as_uint(get_pixel(TYPE_CONTROL, p_global_position).r);
}

inline void Terrain3DStorage::set_roughness(Vector3 p_global_position, real_t p_roughness) {
Color clr = get_pixel(TYPE_COLOR, p_global_position);
clr.a = p_roughness;
set_pixel(TYPE_COLOR, p_global_position, clr);
}

inline real_t Terrain3DStorage::get_roughness(Vector3 p_global_position) {
return get_pixel(TYPE_COLOR, p_global_position).a;
}

#endif // TERRAIN3D_STORAGE_CLASS_H

0 comments on commit 6ec4f7b

Please sign in to comment.