1 /*************************************************************************/
2 /*  shape_sw.h                                                           */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
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 #ifndef SHAPE_SW_H
31 #define SHAPE_SW_H
32 
33 #include "bsp_tree.h"
34 #include "geometry.h"
35 #include "servers/physics_server.h"
36 /*
37 
38 SHAPE_LINE, ///< plane:"plane"
39 SHAPE_SEGMENT, ///< float:"length"
40 SHAPE_CIRCLE, ///< float:"radius"
41 SHAPE_RECTANGLE, ///< vec3:"extents"
42 SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
43 SHAPE_CONCAVE_POLYGON, ///< Vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array)
44 SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
45 
46 */
47 
48 class ShapeSW;
49 
50 class ShapeOwnerSW {
51 public:
52 	virtual void _shape_changed() = 0;
53 	virtual void remove_shape(ShapeSW *p_shape) = 0;
54 
~ShapeOwnerSW()55 	virtual ~ShapeOwnerSW() {}
56 };
57 
58 class ShapeSW {
59 
60 	RID self;
61 	AABB aabb;
62 	bool configured;
63 	real_t custom_bias;
64 
65 	Map<ShapeOwnerSW *, int> owners;
66 
67 protected:
68 	void configure(const AABB &p_aabb);
69 
70 public:
71 	enum {
72 		MAX_SUPPORTS = 8
73 	};
74 
set_self(const RID & p_self)75 	_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
get_self()76 	_FORCE_INLINE_ RID get_self() const { return self; }
77 
78 	virtual PhysicsServer::ShapeType get_type() const = 0;
79 
get_aabb()80 	_FORCE_INLINE_ AABB get_aabb() const { return aabb; }
is_configured()81 	_FORCE_INLINE_ bool is_configured() const { return configured; }
82 
is_concave()83 	virtual bool is_concave() const { return false; }
84 
85 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const = 0;
86 	virtual Vector3 get_support(const Vector3 &p_normal) const;
87 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const = 0;
88 
89 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0;
90 	virtual Vector3 get_moment_of_inertia(float p_mass) const = 0;
91 
92 	virtual void set_data(const Variant &p_data) = 0;
93 	virtual Variant get_data() const = 0;
94 
set_custom_bias(real_t p_bias)95 	_FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; }
get_custom_bias()96 	_FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; }
97 
98 	void add_owner(ShapeOwnerSW *p_owner);
99 	void remove_owner(ShapeOwnerSW *p_owner);
100 	bool is_owner(ShapeOwnerSW *p_owner) const;
101 	const Map<ShapeOwnerSW *, int> &get_owners() const;
102 
103 	ShapeSW();
104 	virtual ~ShapeSW();
105 };
106 
107 class ConcaveShapeSW : public ShapeSW {
108 
109 public:
is_concave()110 	virtual bool is_concave() const { return true; }
111 	typedef void (*Callback)(void *p_userdata, ShapeSW *p_convex);
get_supports(const Vector3 & p_normal,int p_max,Vector3 * r_supports,int & r_amount)112 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
113 
114 	virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const = 0;
115 
ConcaveShapeSW()116 	ConcaveShapeSW() {}
117 };
118 
119 class PlaneShapeSW : public ShapeSW {
120 
121 	Plane plane;
122 
123 	void _setup(const Plane &p_plane);
124 
125 public:
126 	Plane get_plane() const;
127 
get_type()128 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_PLANE; }
129 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
130 	virtual Vector3 get_support(const Vector3 &p_normal) const;
get_supports(const Vector3 & p_normal,int p_max,Vector3 * r_supports,int & r_amount)131 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
132 
133 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
134 
135 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
136 
137 	virtual void set_data(const Variant &p_data);
138 	virtual Variant get_data() const;
139 
140 	PlaneShapeSW();
141 };
142 
143 class RayShapeSW : public ShapeSW {
144 
145 	float length;
146 
147 	void _setup(float p_length);
148 
149 public:
150 	float get_length() const;
151 
get_type()152 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_RAY; }
153 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
154 	virtual Vector3 get_support(const Vector3 &p_normal) const;
155 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
156 
157 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
158 
159 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
160 
161 	virtual void set_data(const Variant &p_data);
162 	virtual Variant get_data() const;
163 
164 	RayShapeSW();
165 };
166 
167 class SphereShapeSW : public ShapeSW {
168 
169 	real_t radius;
170 
171 	void _setup(real_t p_radius);
172 
173 public:
174 	real_t get_radius() const;
175 
get_type()176 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_SPHERE; }
177 
178 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
179 	virtual Vector3 get_support(const Vector3 &p_normal) const;
180 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
181 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
182 
183 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
184 
185 	virtual void set_data(const Variant &p_data);
186 	virtual Variant get_data() const;
187 
188 	SphereShapeSW();
189 };
190 
191 class BoxShapeSW : public ShapeSW {
192 
193 	Vector3 half_extents;
194 	void _setup(const Vector3 &p_half_extents);
195 
196 public:
get_half_extents()197 	_FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; }
198 
get_type()199 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_BOX; }
200 
201 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
202 	virtual Vector3 get_support(const Vector3 &p_normal) const;
203 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
204 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
205 
206 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
207 
208 	virtual void set_data(const Variant &p_data);
209 	virtual Variant get_data() const;
210 
211 	BoxShapeSW();
212 };
213 
214 class CapsuleShapeSW : public ShapeSW {
215 
216 	real_t height;
217 	real_t radius;
218 
219 	void _setup(real_t p_height, real_t p_radius);
220 
221 public:
get_height()222 	_FORCE_INLINE_ real_t get_height() const { return height; }
get_radius()223 	_FORCE_INLINE_ real_t get_radius() const { return radius; }
224 
get_type()225 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CAPSULE; }
226 
227 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
228 	virtual Vector3 get_support(const Vector3 &p_normal) const;
229 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
230 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
231 
232 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
233 
234 	virtual void set_data(const Variant &p_data);
235 	virtual Variant get_data() const;
236 
237 	CapsuleShapeSW();
238 };
239 
240 struct ConvexPolygonShapeSW : public ShapeSW {
241 
242 	Geometry::MeshData mesh;
243 
244 	void _setup(const Vector<Vector3> &p_vertices);
245 
246 public:
get_meshConvexPolygonShapeSW247 	const Geometry::MeshData &get_mesh() const { return mesh; }
248 
get_typeConvexPolygonShapeSW249 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONVEX_POLYGON; }
250 
251 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
252 	virtual Vector3 get_support(const Vector3 &p_normal) const;
253 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
254 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
255 
256 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
257 
258 	virtual void set_data(const Variant &p_data);
259 	virtual Variant get_data() const;
260 
261 	ConvexPolygonShapeSW();
262 };
263 
264 struct _VolumeSW_BVH;
265 struct FaceShapeSW;
266 
267 struct ConcavePolygonShapeSW : public ConcaveShapeSW {
268 	// always a trimesh
269 
270 	struct Face {
271 
272 		Vector3 normal;
273 		int indices[3];
274 	};
275 
276 	DVector<Face> faces;
277 	DVector<Vector3> vertices;
278 
279 	struct BVH {
280 
281 		AABB aabb;
282 		int left;
283 		int right;
284 
285 		int face_index;
286 	};
287 
288 	DVector<BVH> bvh;
289 
290 	struct _CullParams {
291 
292 		AABB aabb;
293 		Callback callback;
294 		void *userdata;
295 		const Face *faces;
296 		const Vector3 *vertices;
297 		const BVH *bvh;
298 		FaceShapeSW *face;
299 	};
300 
301 	struct _SegmentCullParams {
302 
303 		Vector3 from;
304 		Vector3 to;
305 		const Face *faces;
306 		const Vector3 *vertices;
307 		const BVH *bvh;
308 		Vector3 dir;
309 
310 		Vector3 result;
311 		Vector3 normal;
312 		real_t min_d;
313 		int collisions;
314 	};
315 
316 	void _cull_segment(int p_idx, _SegmentCullParams *p_params) const;
317 	void _cull(int p_idx, _CullParams *p_params) const;
318 
319 	void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx);
320 
321 	void _setup(DVector<Vector3> p_faces);
322 
323 public:
324 	DVector<Vector3> get_faces() const;
325 
get_typeConcavePolygonShapeSW326 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONCAVE_POLYGON; }
327 
328 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
329 	virtual Vector3 get_support(const Vector3 &p_normal) const;
330 
331 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
332 
333 	virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const;
334 
335 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
336 
337 	virtual void set_data(const Variant &p_data);
338 	virtual Variant get_data() const;
339 
340 	ConcavePolygonShapeSW();
341 };
342 
343 struct HeightMapShapeSW : public ConcaveShapeSW {
344 
345 	DVector<real_t> heights;
346 	int width;
347 	int depth;
348 	float cell_size;
349 
350 	//	void _cull_segment(int p_idx,_SegmentCullParams *p_params) const;
351 	//	void _cull(int p_idx,_CullParams *p_params) const;
352 
353 	void _setup(DVector<float> p_heights, int p_width, int p_depth, float p_cell_size);
354 
355 public:
356 	DVector<real_t> get_heights() const;
357 	int get_width() const;
358 	int get_depth() const;
359 	float get_cell_size() const;
360 
get_typeHeightMapShapeSW361 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_HEIGHTMAP; }
362 
363 	virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
364 	virtual Vector3 get_support(const Vector3 &p_normal) const;
365 	virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
366 
367 	virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const;
368 
369 	virtual Vector3 get_moment_of_inertia(float p_mass) const;
370 
371 	virtual void set_data(const Variant &p_data);
372 	virtual Variant get_data() const;
373 
374 	HeightMapShapeSW();
375 };
376 
377 //used internally
378 struct FaceShapeSW : public ShapeSW {
379 
380 	Vector3 normal; //cache
381 	Vector3 vertex[3];
382 
get_typeFaceShapeSW383 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONCAVE_POLYGON; }
384 
get_vertexFaceShapeSW385 	const Vector3 &get_vertex(int p_idx) const { return vertex[p_idx]; }
386 
387 	void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
388 	Vector3 get_support(const Vector3 &p_normal) const;
389 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const;
390 	bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
391 
392 	Vector3 get_moment_of_inertia(float p_mass) const;
393 
set_dataFaceShapeSW394 	virtual void set_data(const Variant &p_data) {}
get_dataFaceShapeSW395 	virtual Variant get_data() const { return Variant(); }
396 
397 	FaceShapeSW();
398 };
399 
400 struct MotionShapeSW : public ShapeSW {
401 
402 	ShapeSW *shape;
403 	Vector3 motion;
404 
get_typeMotionShapeSW405 	virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONVEX_POLYGON; }
406 
project_rangeMotionShapeSW407 	void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
408 
409 		Vector3 cast = p_transform.basis.xform(motion);
410 		real_t mina, maxa;
411 		real_t minb, maxb;
412 		Transform ofsb = p_transform;
413 		ofsb.origin += cast;
414 		shape->project_range(p_normal, p_transform, mina, maxa);
415 		shape->project_range(p_normal, ofsb, minb, maxb);
416 		r_min = MIN(mina, minb);
417 		r_max = MAX(maxa, maxb);
418 	}
419 
get_supportMotionShapeSW420 	Vector3 get_support(const Vector3 &p_normal) const {
421 
422 		Vector3 support = shape->get_support(p_normal);
423 		if (p_normal.dot(motion) > 0) {
424 			support += motion;
425 		}
426 		return support;
427 	}
get_supportsMotionShapeSW428 	virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
intersect_segmentMotionShapeSW429 	bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return false; }
430 
get_moment_of_inertiaMotionShapeSW431 	Vector3 get_moment_of_inertia(float p_mass) const { return Vector3(); }
432 
set_dataMotionShapeSW433 	virtual void set_data(const Variant &p_data) {}
get_dataMotionShapeSW434 	virtual Variant get_data() const { return Variant(); }
435 
MotionShapeSWMotionShapeSW436 	MotionShapeSW() { configure(AABB()); }
437 };
438 
439 struct _ShapeTestConvexBSPSW {
440 
441 	const BSP_Tree *bsp;
442 	const ShapeSW *shape;
443 	Transform transform;
444 
project_range_ShapeTestConvexBSPSW445 	_FORCE_INLINE_ void project_range(const Vector3 &p_normal, real_t &r_min, real_t &r_max) const {
446 
447 		shape->project_range(p_normal, transform, r_min, r_max);
448 	}
449 };
450 
451 #endif // SHAPESW_H
452