1/**************************************************************************/
2/* csg_shape.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef CSG_SHAPE_H
32#define CSG_SHAPE_H
33
34#include "csg.h"
35
36#include "scene/3d/path_3d.h"
37#include "scene/3d/visual_instance_3d.h"
38#include "scene/resources/concave_polygon_shape_3d.h"
39
40#include "thirdparty/misc/mikktspace.h"
41
42class CSGShape3D : public GeometryInstance3D {
43 GDCLASS(CSGShape3D, GeometryInstance3D);
44
45public:
46 enum Operation {
47 OPERATION_UNION,
48 OPERATION_INTERSECTION,
49 OPERATION_SUBTRACTION,
50
51 };
52
53private:
54 Operation operation = OPERATION_UNION;
55 CSGShape3D *parent_shape = nullptr;
56
57 CSGBrush *brush = nullptr;
58
59 AABB node_aabb;
60
61 bool dirty = false;
62 bool last_visible = false;
63 float snap = 0.001;
64
65 bool use_collision = false;
66 uint32_t collision_layer = 1;
67 uint32_t collision_mask = 1;
68 real_t collision_priority = 1.0;
69 Ref<ConcavePolygonShape3D> root_collision_shape;
70 RID root_collision_instance;
71 RID root_collision_debug_instance;
72 Transform3D debug_shape_old_transform;
73
74 bool calculate_tangents = true;
75
76 Ref<ArrayMesh> root_mesh;
77
78 struct Vector3Hasher {
79 _ALWAYS_INLINE_ uint32_t hash(const Vector3 &p_vec3) const {
80 uint32_t h = hash_murmur3_one_float(p_vec3.x);
81 h = hash_murmur3_one_float(p_vec3.y, h);
82 h = hash_murmur3_one_float(p_vec3.z, h);
83 return h;
84 }
85 };
86
87 struct ShapeUpdateSurface {
88 Vector<Vector3> vertices;
89 Vector<Vector3> normals;
90 Vector<Vector2> uvs;
91 Vector<real_t> tans;
92 Ref<Material> material;
93 int last_added = 0;
94
95 Vector3 *verticesw = nullptr;
96 Vector3 *normalsw = nullptr;
97 Vector2 *uvsw = nullptr;
98 real_t *tansw = nullptr;
99 };
100
101 //mikktspace callbacks
102 static int mikktGetNumFaces(const SMikkTSpaceContext *pContext);
103 static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace);
104 static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert);
105 static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert);
106 static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert);
107 static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
108 const tbool bIsOrientationPreserving, const int iFace, const int iVert);
109
110 void _update_shape();
111 void _update_collision_faces();
112 bool _is_debug_collision_shape_visible();
113 void _update_debug_collision_shape();
114 void _clear_debug_collision_shape();
115 void _on_transform_changed();
116
117protected:
118 void _notification(int p_what);
119 virtual CSGBrush *_build_brush() = 0;
120 void _make_dirty(bool p_parent_removing = false);
121
122 static void _bind_methods();
123
124 friend class CSGCombiner3D;
125 CSGBrush *_get_brush();
126
127 void _validate_property(PropertyInfo &p_property) const;
128
129public:
130 Array get_meshes() const;
131
132 void set_operation(Operation p_operation);
133 Operation get_operation() const;
134
135 virtual Vector<Vector3> get_brush_faces();
136
137 virtual AABB get_aabb() const override;
138
139 void set_use_collision(bool p_enable);
140 bool is_using_collision() const;
141
142 void set_collision_layer(uint32_t p_layer);
143 uint32_t get_collision_layer() const;
144
145 void set_collision_mask(uint32_t p_mask);
146 uint32_t get_collision_mask() const;
147
148 void set_collision_layer_value(int p_layer_number, bool p_value);
149 bool get_collision_layer_value(int p_layer_number) const;
150
151 void set_collision_mask_value(int p_layer_number, bool p_value);
152 bool get_collision_mask_value(int p_layer_number) const;
153
154 void set_collision_priority(real_t p_priority);
155 real_t get_collision_priority() const;
156
157 void set_snap(float p_snap);
158 float get_snap() const;
159
160 void set_calculate_tangents(bool p_calculate_tangents);
161 bool is_calculating_tangents() const;
162
163 bool is_root_shape() const;
164 CSGShape3D();
165 ~CSGShape3D();
166};
167
168VARIANT_ENUM_CAST(CSGShape3D::Operation)
169
170class CSGCombiner3D : public CSGShape3D {
171 GDCLASS(CSGCombiner3D, CSGShape3D);
172
173private:
174 virtual CSGBrush *_build_brush() override;
175
176public:
177 CSGCombiner3D();
178};
179
180class CSGPrimitive3D : public CSGShape3D {
181 GDCLASS(CSGPrimitive3D, CSGShape3D);
182
183protected:
184 bool flip_faces;
185 CSGBrush *_create_brush_from_arrays(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uv, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials);
186 static void _bind_methods();
187
188public:
189 void set_flip_faces(bool p_invert);
190 bool get_flip_faces();
191
192 CSGPrimitive3D();
193};
194
195class CSGMesh3D : public CSGPrimitive3D {
196 GDCLASS(CSGMesh3D, CSGPrimitive3D);
197
198 virtual CSGBrush *_build_brush() override;
199
200 Ref<Mesh> mesh;
201 Ref<Material> material;
202
203 void _mesh_changed();
204
205protected:
206 static void _bind_methods();
207
208public:
209 void set_mesh(const Ref<Mesh> &p_mesh);
210 Ref<Mesh> get_mesh();
211
212 void set_material(const Ref<Material> &p_material);
213 Ref<Material> get_material() const;
214};
215
216class CSGSphere3D : public CSGPrimitive3D {
217 GDCLASS(CSGSphere3D, CSGPrimitive3D);
218 virtual CSGBrush *_build_brush() override;
219
220 Ref<Material> material;
221 bool smooth_faces;
222 float radius;
223 int radial_segments;
224 int rings;
225
226protected:
227 static void _bind_methods();
228
229public:
230 void set_radius(const float p_radius);
231 float get_radius() const;
232
233 void set_radial_segments(const int p_radial_segments);
234 int get_radial_segments() const;
235
236 void set_rings(const int p_rings);
237 int get_rings() const;
238
239 void set_material(const Ref<Material> &p_material);
240 Ref<Material> get_material() const;
241
242 void set_smooth_faces(bool p_smooth_faces);
243 bool get_smooth_faces() const;
244
245 CSGSphere3D();
246};
247
248class CSGBox3D : public CSGPrimitive3D {
249 GDCLASS(CSGBox3D, CSGPrimitive3D);
250 virtual CSGBrush *_build_brush() override;
251
252 Ref<Material> material;
253 Vector3 size = Vector3(1, 1, 1);
254
255protected:
256 static void _bind_methods();
257#ifndef DISABLE_DEPRECATED
258 // Kept for compatibility from 3.x to 4.0.
259 bool _set(const StringName &p_name, const Variant &p_value);
260#endif
261
262public:
263 void set_size(const Vector3 &p_size);
264 Vector3 get_size() const;
265
266 void set_material(const Ref<Material> &p_material);
267 Ref<Material> get_material() const;
268
269 CSGBox3D() {}
270};
271
272class CSGCylinder3D : public CSGPrimitive3D {
273 GDCLASS(CSGCylinder3D, CSGPrimitive3D);
274 virtual CSGBrush *_build_brush() override;
275
276 Ref<Material> material;
277 float radius;
278 float height;
279 int sides;
280 bool cone;
281 bool smooth_faces;
282
283protected:
284 static void _bind_methods();
285
286public:
287 void set_radius(const float p_radius);
288 float get_radius() const;
289
290 void set_height(const float p_height);
291 float get_height() const;
292
293 void set_sides(const int p_sides);
294 int get_sides() const;
295
296 void set_cone(const bool p_cone);
297 bool is_cone() const;
298
299 void set_smooth_faces(bool p_smooth_faces);
300 bool get_smooth_faces() const;
301
302 void set_material(const Ref<Material> &p_material);
303 Ref<Material> get_material() const;
304
305 CSGCylinder3D();
306};
307
308class CSGTorus3D : public CSGPrimitive3D {
309 GDCLASS(CSGTorus3D, CSGPrimitive3D);
310 virtual CSGBrush *_build_brush() override;
311
312 Ref<Material> material;
313 float inner_radius;
314 float outer_radius;
315 int sides;
316 int ring_sides;
317 bool smooth_faces;
318
319protected:
320 static void _bind_methods();
321
322public:
323 void set_inner_radius(const float p_inner_radius);
324 float get_inner_radius() const;
325
326 void set_outer_radius(const float p_outer_radius);
327 float get_outer_radius() const;
328
329 void set_sides(const int p_sides);
330 int get_sides() const;
331
332 void set_ring_sides(const int p_ring_sides);
333 int get_ring_sides() const;
334
335 void set_smooth_faces(bool p_smooth_faces);
336 bool get_smooth_faces() const;
337
338 void set_material(const Ref<Material> &p_material);
339 Ref<Material> get_material() const;
340
341 CSGTorus3D();
342};
343
344class CSGPolygon3D : public CSGPrimitive3D {
345 GDCLASS(CSGPolygon3D, CSGPrimitive3D);
346
347public:
348 enum Mode {
349 MODE_DEPTH,
350 MODE_SPIN,
351 MODE_PATH
352 };
353
354 enum PathIntervalType {
355 PATH_INTERVAL_DISTANCE,
356 PATH_INTERVAL_SUBDIVIDE
357 };
358
359 enum PathRotation {
360 PATH_ROTATION_POLYGON,
361 PATH_ROTATION_PATH,
362 PATH_ROTATION_PATH_FOLLOW,
363 };
364
365private:
366 virtual CSGBrush *_build_brush() override;
367
368 Vector<Vector2> polygon;
369 Ref<Material> material;
370
371 Mode mode;
372
373 float depth;
374
375 float spin_degrees;
376 int spin_sides;
377
378 NodePath path_node;
379 PathIntervalType path_interval_type;
380 float path_interval;
381 float path_simplify_angle;
382 PathRotation path_rotation;
383 bool path_local;
384
385 Path3D *path = nullptr;
386
387 bool smooth_faces;
388 bool path_continuous_u;
389 real_t path_u_distance;
390 bool path_joined;
391
392 bool _is_editable_3d_polygon() const;
393 bool _has_editable_3d_polygon_no_depth() const;
394
395 void _path_changed();
396 void _path_exited();
397
398protected:
399 static void _bind_methods();
400 void _validate_property(PropertyInfo &p_property) const;
401 void _notification(int p_what);
402
403public:
404 void set_polygon(const Vector<Vector2> &p_polygon);
405 Vector<Vector2> get_polygon() const;
406
407 void set_mode(Mode p_mode);
408 Mode get_mode() const;
409
410 void set_depth(float p_depth);
411 float get_depth() const;
412
413 void set_spin_degrees(float p_spin_degrees);
414 float get_spin_degrees() const;
415
416 void set_spin_sides(int p_spin_sides);
417 int get_spin_sides() const;
418
419 void set_path_node(const NodePath &p_path);
420 NodePath get_path_node() const;
421
422 void set_path_interval_type(PathIntervalType p_interval_type);
423 PathIntervalType get_path_interval_type() const;
424
425 void set_path_interval(float p_interval);
426 float get_path_interval() const;
427
428 void set_path_simplify_angle(float p_angle);
429 float get_path_simplify_angle() const;
430
431 void set_path_rotation(PathRotation p_rotation);
432 PathRotation get_path_rotation() const;
433
434 void set_path_local(bool p_enable);
435 bool is_path_local() const;
436
437 void set_path_continuous_u(bool p_enable);
438 bool is_path_continuous_u() const;
439
440 void set_path_u_distance(real_t p_path_u_distance);
441 real_t get_path_u_distance() const;
442
443 void set_path_joined(bool p_enable);
444 bool is_path_joined() const;
445
446 void set_smooth_faces(bool p_smooth_faces);
447 bool get_smooth_faces() const;
448
449 void set_material(const Ref<Material> &p_material);
450 Ref<Material> get_material() const;
451
452 CSGPolygon3D();
453};
454
455VARIANT_ENUM_CAST(CSGPolygon3D::Mode)
456VARIANT_ENUM_CAST(CSGPolygon3D::PathRotation)
457VARIANT_ENUM_CAST(CSGPolygon3D::PathIntervalType)
458
459#endif // CSG_SHAPE_H
460