#ifndef VOXEL_TYPE_H #define VOXEL_TYPE_H #include "../../cube_tables.h" #include "../../util/fixed_array.h" #include #include class VoxelLibrary; // TODO Rename VoxelModel? // Definition of one type of voxel for use with `VoxelMesherBlocky`. // A voxel can be a simple coloured cube, or a more complex model. // Important: it is recommended that you create voxels from a library rather than using new(). class Voxel : public Resource { GDCLASS(Voxel, Resource) public: // Convention to mean "nothing". // Don't assign a non-empty model at this index. static const uint16_t AIR_ID = 0; // Plain data strictly used by the mesher. // It becomes distinct because it's going to be used in a multithread environment, // while the configuration that produced the data can be changed by the user at any time. struct BakedData { struct Model { std::vector positions; std::vector normals; std::vector uvs; std::vector indices; std::vector tangents; // Model sides: // They are separated because this way we can occlude them easily. // Due to these defining cube side triangles, normals are known already. FixedArray, Cube::SIDE_COUNT> side_positions; FixedArray, Cube::SIDE_COUNT> side_uvs; FixedArray, Cube::SIDE_COUNT> side_indices; FixedArray, Cube::SIDE_COUNT> side_tangents; FixedArray side_pattern_indices; void clear() { positions.clear(); normals.clear(); uvs.clear(); indices.clear(); tangents.clear(); for (int side = 0; side < Cube::SIDE_COUNT; ++side) { side_positions[side].clear(); side_uvs[side].clear(); side_indices[side].clear(); side_tangents[side].clear(); } } }; Model model; int material_id; Color color; uint8_t transparency_index; bool contributes_to_ao; bool empty; inline void clear() { model.clear(); empty = true; } }; Voxel(); enum Side { SIDE_NEGATIVE_X = Cube::SIDE_NEGATIVE_X, SIDE_POSITIVE_X = Cube::SIDE_POSITIVE_X, SIDE_NEGATIVE_Y = Cube::SIDE_NEGATIVE_Y, SIDE_POSITIVE_Y = Cube::SIDE_POSITIVE_Y, SIDE_NEGATIVE_Z = Cube::SIDE_NEGATIVE_Z, SIDE_POSITIVE_Z = Cube::SIDE_POSITIVE_Z, SIDE_COUNT = Cube::SIDE_COUNT }; // Properties void set_voxel_name(String name); _FORCE_INLINE_ StringName get_voxel_name() const { return _name; } void set_id(int id); _FORCE_INLINE_ int get_id() const { return _id; } void set_color(Color color); _FORCE_INLINE_ Color get_color() const { return _color; } void set_material_id(unsigned int id); _FORCE_INLINE_ unsigned int get_material_id() const { return _material_id; } // TODO Might become obsolete void set_transparent(bool t = true); _FORCE_INLINE_ bool is_transparent() const { return _transparency_index != 0; } void set_transparency_index(int i); int get_transparency_index() const { return _transparency_index; } void set_custom_mesh(Ref mesh); Ref get_custom_mesh() const { return _custom_mesh; } void set_random_tickable(bool rt); inline bool is_random_tickable() const { return _random_tickable; } void set_collision_mask(uint32_t mask); inline uint32_t get_collision_mask() const { return _collision_mask; } Vector2 get_cube_tile(int side) const { return _cube_tiles[side]; } //------------------------------------------- // Built-in geometry generators enum GeometryType { GEOMETRY_NONE = 0, GEOMETRY_CUBE, GEOMETRY_CUSTOM_MESH, GEOMETRY_MAX }; void set_geometry_type(GeometryType type); GeometryType get_geometry_type() const; inline bool is_empty() const { return _empty; } Ref duplicate(bool p_subresources) const override; //------------------------------------------ // Properties for internal usage only void bake(BakedData &baked_data, int p_atlas_size, bool bake_tangents); const std::vector &get_collision_aabbs() const { return _collision_aabbs; } private: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List *p_list) const; void set_cube_uv_side(int side, Vector2 tile_pos); static void _bind_methods(); void set_cube_geometry(); Array _b_get_collision_aabbs() const; void _b_set_collision_aabbs(Array array); private: // Identifiers int _id; StringName _name; // Properties int _material_id; // If two neighboring voxels are supposed to occlude their shared face, // this index decides wether or not it should happen. Equal indexes culls the face, different indexes doesn't. uint8_t _transparency_index = 0; Color _color; GeometryType _geometry_type; FixedArray _cube_tiles; Ref _custom_mesh; std::vector _collision_aabbs; bool _random_tickable = false; bool _empty = true; uint32_t _collision_mask = 1; }; VARIANT_ENUM_CAST(Voxel::GeometryType) VARIANT_ENUM_CAST(Voxel::Side) #endif // VOXEL_TYPE_H