-
-
Notifications
You must be signed in to change notification settings - Fork 236
/
voxel_mesher.h
144 lines (119 loc) · 5.66 KB
/
voxel_mesher.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef VOXEL_MESHER_H
#define VOXEL_MESHER_H
#include "../constants/cube_tables.h"
#include "../util/containers/fixed_array.h"
#include "../util/containers/span.h"
#include "../util/containers/std_vector.h"
#include "../util/godot/classes/image.h"
#include "../util/godot/classes/mesh.h"
#include "../util/macros.h"
ZN_GODOT_FORWARD_DECLARE(class ShaderMaterial)
namespace zylann::voxel {
namespace godot {
class VoxelBuffer;
}
class VoxelBuffer;
class VoxelGenerator;
class VoxelData;
// Base class for algorithms that generate meshes from voxels.
class VoxelMesher : public Resource {
GDCLASS(VoxelMesher, Resource)
public:
struct Input {
// Voxels to be used as the primary source of data.
const VoxelBuffer &voxels;
// When using LOD, some meshers can use the generator and edited voxels to affine results.
// If not provided, the mesher will only use `voxels`.
VoxelGenerator *generator = nullptr;
const VoxelData *data = nullptr;
// Origin of the block is required when doing deep sampling.
Vector3i origin_in_voxels;
// LOD index. 0 means highest detail. 1 means half detail etc.
uint8_t lod_index = 0;
// If true, collision information is required.
// Sometimes it doesn't change anything as the rendering mesh can be used as collider,
// but in other setups it can be different and will be returned in `collision_surface`.
bool collision_hint = false;
// If true, the mesher is told that the mesh will be used in a context with variable level of detail.
// For example, transition meshes will or will not be generated based on this (overriding mesher settings).
bool lod_hint = false;
// If true, the mesher can collect some extra information which can be useful to speed up detail texture
// baking. Depends on the mesher.
bool detail_texture_hint = false;
};
struct Output {
struct Surface {
Array arrays;
uint16_t material_index = 0;
};
StdVector<Surface> surfaces;
FixedArray<StdVector<Surface>, Cube::SIDE_COUNT> transition_surfaces;
Mesh::PrimitiveType primitive_type = Mesh::PRIMITIVE_TRIANGLES;
// Flags for creating the Godot mesh resource
uint32_t mesh_flags = 0;
struct CollisionSurface {
StdVector<Vector3f> positions;
StdVector<int> indices;
// If >= 0, the collision surface may actually be picked from a sub-section of arrays of the first surface
// in the render mesh (It may start from index 0).
// Used when transition meshes are combined with the main mesh.
int32_t submesh_vertex_end = -1;
int32_t submesh_index_end = -1;
};
CollisionSurface collision_surface;
// May be used to store extra information needed in shader to render the mesh properly
// (currently used only by the cubes mesher when baking colors)
Ref<Image> atlas_image;
};
static bool is_mesh_empty(const StdVector<Output::Surface> &surfaces);
// This can be called from multiple threads at once. Make sure member vars are protected or thread-local.
virtual void build(Output &output, const Input &voxels);
// Builds a mesh from the given voxels. This function is simplified to be used by the script API.
Ref<Mesh> build_mesh(const VoxelBuffer &voxels, TypedArray<Material> materials, Dictionary additional_data);
// Gets how many neighbor voxels need to be accessed around the meshed area, toward negative axes.
// If this is not respected, the mesher might produce seams at the edges, or an error
unsigned int get_minimum_padding() const;
// Gets how many neighbor voxels need to be accessed around the meshed area, toward positive axes.
// If this is not respected, the mesher might produce seams at the edges, or an error
unsigned int get_maximum_padding() const;
// Gets which channels this mesher is able to use in its current configuration.
// This is returned as a bitmask where channel index corresponds to bit position.
virtual int get_used_channels_mask() const {
return 0;
}
// Returns true if this mesher supports generating voxel data at multiple levels of detail.
virtual bool supports_lod() const {
return true;
}
// Some meshers can provide materials themselves. The index may come from the built output. Returns null if the
// index does not have a material assigned. If not provided here, a default material may be used.
// An error can be produced if the index is out of bounds.
virtual Ref<Material> get_material_by_index(unsigned int i) const;
// Get the highest+1 material index
virtual unsigned int get_material_index_count() const;
#ifdef TOOLS_ENABLED
// If the mesher has problems, messages may be returned by this method so they can be shown to the user.
virtual void get_configuration_warnings(PackedStringArray &out_warnings) const {}
#endif
// Returns `true` if the mesher generates specific data for mesh collisions, which will be found in
// `CollisionSurface`.
// If `false`, the rendering mesh may be used as collider.
virtual bool is_generating_collision_surface() const {
return false;
}
// Gets a special default material to be used to render meshes produced with this mesher, when variable level of
// detail is used. If null, standard materials or default Godot shaders can be used. This is mostly to provide a
// default shader that looks ok. Users are still expected to tweak them if need be.
// Such material is not meant to be modified.
virtual Ref<ShaderMaterial> get_default_lod_material() const;
protected:
Ref<Mesh> _b_build_mesh(Ref<godot::VoxelBuffer> voxels, TypedArray<Material> materials, Dictionary additional_data);
static void _bind_methods();
void set_padding(int minimum, int maximum);
private:
// Set in constructor and never changed after.
unsigned int _minimum_padding = 0;
unsigned int _maximum_padding = 0;
};
} // namespace zylann::voxel
#endif // VOXEL_MESHER_H