Skip to content

Commit

Permalink
Punch holes in collision. Add control map utility functions
Browse files Browse the repository at this point in the history
  • Loading branch information
TokisanGames committed Nov 18, 2023
1 parent 2456e0d commit 59c6a1f
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 33 deletions.
27 changes: 16 additions & 11 deletions src/terrain_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,19 +299,24 @@ void Terrain3D::_update_collision() {
Vector2i global_offset = Vector2i(_storage->get_region_offsets()[i]) * region_size;
Vector3 global_pos = Vector3(global_offset.x, 0, global_offset.y);

Ref<Image> map, map_plusx, map_plusz, map_plusxz;
Ref<Image> map, map_x, map_z, map_xz;
Ref<Image> cmap, cmap_x, cmap_z, cmap_xz;
map = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, i);
cmap = _storage->get_map_region(Terrain3DStorage::TYPE_CONTROL, i);
int region = _storage->get_region_index(Vector3(global_pos.x + region_size, 0, global_pos.z));
if (region >= 0) {
map_plusx = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, region);
map_x = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, region);
cmap_x = _storage->get_map_region(Terrain3DStorage::TYPE_CONTROL, region);
}
region = _storage->get_region_index(Vector3(global_pos.x, 0, global_pos.z + region_size));
if (region >= 0) {
map_plusz = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, region);
map_z = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, region);
cmap_z = _storage->get_map_region(Terrain3DStorage::TYPE_CONTROL, region);
}
region = _storage->get_region_index(Vector3(global_pos.x + region_size, 0, global_pos.z + region_size));
if (region >= 0) {
map_plusxz = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, region);
map_xz = _storage->get_map_region(Terrain3DStorage::TYPE_HEIGHT, region);
cmap_xz = _storage->get_map_region(Terrain3DStorage::TYPE_CONTROL, region);
}

for (int z = 0; z < shape_size; z++) {
Expand All @@ -325,22 +330,22 @@ void Terrain3D::_update_collision() {

// Set heights on local map, or adjacent maps if on the last row/col
if (x < region_size && z < region_size) {
map_data[index] = map->get_pixel(x, z).r;
map_data[index] = (Util::is_hole(cmap->get_pixel(x, z).r)) ? NAN : map->get_pixel(x, z).r;
} else if (x == region_size && z < region_size) {
if (map_plusx.is_valid()) {
map_data[index] = map_plusx->get_pixel(0, z).r;
if (map_x.is_valid()) {
map_data[index] = (Util::is_hole(cmap_x->get_pixel(0, z).r)) ? NAN : map_x->get_pixel(0, z).r;
} else {
map_data[index] = 0.0f;
}
} else if (z == region_size && x < region_size) {
if (map_plusz.is_valid()) {
map_data[index] = map_plusz->get_pixel(x, 0).r;
if (map_z.is_valid()) {
map_data[index] = (Util::is_hole(cmap_z->get_pixel(x, 0).r)) ? NAN : map_z->get_pixel(x, 0).r;
} else {
map_data[index] = 0.0f;
}
} else if (x == region_size && z == region_size) {
if (map_plusxz.is_valid()) {
map_data[index] = map_plusxz->get_pixel(0, 0).r;
if (map_xz.is_valid()) {
map_data[index] = (Util::is_hole(cmap_xz->get_pixel(0, 0).r)) ? NAN : map_xz->get_pixel(0, 0).r;
} else {
map_data[index] = 0.0f;
}
Expand Down
37 changes: 15 additions & 22 deletions src/terrain_3d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "logger.h"
#include "terrain_3d_editor.h"
#include "util.h"

///////////////////////////
// Subclass Functions
Expand Down Expand Up @@ -207,15 +208,12 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di

} else if (map_type == Terrain3DStorage::TYPE_CONTROL) {
// Get bit field from pixel
uint32_t bits;
*(float *)&bits = src.r; // Must be a 32-bit float, no double/real_t
uint32_t base_id = bits >> 27 & 0x1F; // 5 bits #32-28
uint32_t overlay_id = bits >> 22 & 0x1F; // 5 bits #27-23
real_t blend = real_t(bits >> 14 & 0xFF) / 255.0f; // 8 bits #22-15
// Reserved 11 bits #4-14
uint8_t holes = bits >> 2 & 0x1; // 1 bit #3
uint8_t navigation = bits >> 1 & 0x1; // 1 bit #2
uint8_t autoshader = bits & 0x1; // 1 bit #1
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
bool hole = Util::is_hole(src.r);
bool navigation = Util::is_nav(src.r);
bool autoshader = Util::is_auto(src.r);

real_t alpha_clip = (brush_alpha > 0.1f) ? 1.0f : 0.0f;
uint32_t dest_id = uint32_t(Math::lerp(base_id, texture_id, alpha_clip));
Expand Down Expand Up @@ -256,7 +254,7 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di
break;
case HOLES:
if (brush_alpha > 0.1f) {
holes = enable;
hole = enable;
}
break;
case NAVIGATION:
Expand All @@ -268,19 +266,14 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di
break;
}

// Convert back to bit field
base_id = (base_id & 0x1F) << 27;
overlay_id = (overlay_id & 0x1F) << 22;
// Convert back to bitfield
uint32_t blend_int = uint32_t(CLAMP(Math::round(blend * 255.0f), 0.0f, 255.0f));
blend_int = (blend_int & 0xFF) << 14;
holes = (holes & 0x1) << 2;
navigation = (navigation & 0x1) << 1;
autoshader = (autoshader & 0x1);
bits = base_id | overlay_id | blend_int | holes | navigation | autoshader;

// Write back to pixel in FORMAT_RF
float out_float = *(float *)&bits; // Must be a 32-bit float, no double/real_t
dest = Color(out_float, 0.f, 0.f, 1.0f);
uint32_t bits = Util::enc_base(base_id) | Util::enc_overlay(overlay_id) |
Util::enc_blend(blend_int) | Util::enc_hole(hole) |
Util::enc_nav(navigation) | Util::enc_auto(autoshader);

// Write back to pixel in FORMAT_RF. Must be a 32-bit float
dest = Color(*(float *)&bits, 0.f, 0.f, 1.0f);

} else if (map_type == Terrain3DStorage::TYPE_COLOR) {
switch (_tool) {
Expand Down
23 changes: 23 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@ class Util {
public:
static inline const char *__class__ = "Terrain3DUtil";

// Controlmap handling
// Getters read the 32-bit float as a 32-bit uint, then mask bits to retreive value
// Encoders return a full 32-bit uint with bits in the proper place for ORing
static inline uint32_t get_mask(float pixel, uint32_t mask) { return *(uint32_t *)&pixel & mask; }

static inline uint8_t get_base(float pixel) { return *(uint32_t *)&pixel >> 27 & 0x1F; }
static inline uint32_t enc_base(uint8_t base) { return (base & 0x1F) << 27; }

static inline uint8_t get_overlay(float pixel) { return *(uint32_t *)&pixel >> 22 & 0x1F; }
static inline uint32_t enc_overlay(uint8_t over) { return (over & 0x1F) << 22; }

static inline uint8_t get_blend(float pixel) { return *(uint32_t *)&pixel >> 14 & 0xFF; }
static inline uint32_t enc_blend(uint8_t blend) { return (blend & 0xFF) << 14; }

static inline bool is_hole(float pixel) { return (*(uint32_t *)&pixel >> 2 & 0x1) == 1; }
static inline uint32_t enc_hole(bool hole) { return (hole & 0x1) << 2; }

static inline bool is_nav(float pixel) { return (*(uint32_t *)&pixel >> 1 & 0x1) == 1; }
static inline uint32_t enc_nav(bool nav) { return (nav & 0x1) << 1; }

static inline bool is_auto(float pixel) { return (*(uint32_t *)&pixel & 0x1) == 1; }
static inline uint32_t enc_auto(bool autosh) { return autosh & 0x1; }

// Print info to the console
static void print_dict(String name, const Dictionary &p_dict, int p_level = 1); // Defaults to INFO
static void dump_gen(GeneratedTex p_gen, String name = "");
Expand Down

0 comments on commit 59c6a1f

Please sign in to comment.