1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef COLLISION_VOLUME_H
4 #define COLLISION_VOLUME_H
5 
6 #include "System/float3.h"
7 #include "System/creg/creg_cond.h"
8 #include "System/Util.h"
9 
10 // the positive x-axis points to the "left" in object-space and to the "right" in world-space
11 // converting between them means flipping the sign of x-components of positions and directions
12 const float3 WORLD_TO_OBJECT_SPACE = float3(-1.0f, 1.0f, 1.0f);
13 const float COLLISION_VOLUME_EPS = 0.0000000001f;
14 
15 struct LocalModelPiece;
16 class CMatrix44f;
17 class CSolidObject;
18 class CUnit;
19 class CFeature;
20 
21 struct CollisionVolume
22 {
23 	CR_DECLARE_STRUCT(CollisionVolume)
24 
25 public:
26 	enum {
27 		COLVOL_TYPE_ELLIPSOID =  0, // dummy, these become spheres or boxes
28 		COLVOL_TYPE_CYLINDER  =  1,
29 		COLVOL_TYPE_BOX       =  2,
30 		COLVOL_TYPE_SPHERE    =  3,
31 	};
32 	enum {
33 		COLVOL_AXIS_X = 0,
34 		COLVOL_AXIS_Y = 1,
35 		COLVOL_AXIS_Z = 2,
36 	};
37 	enum {
38 		COLVOL_HITTEST_DISC = 0,
39 		COLVOL_HITTEST_CONT = 1,
40 	};
41 
42 public:
43 	CollisionVolume();
CollisionVolumeCollisionVolume44 	CollisionVolume(const CollisionVolume* v) { *this = *v; }
45 	CollisionVolume(
46 		const std::string& cvTypeStr,
47 		const float3& cvScales,
48 		const float3& cvOffsets
49 	);
50 
51 	CollisionVolume& operator = (const CollisionVolume&);
52 
53 	/**
54 	 * Called if a unit or feature does not define a custom volume.
55 	 * @param radius the object's default radius
56 	 */
57 	void InitSphere(float radius);
58 	void InitBox(const float3& scales);
59 	void InitShape(
60 		const float3& scales,
61 		const float3& offsets,
62 		const int vType,
63 		const int tType,
64 		const int pAxis
65 	);
66 
67 	void RescaleAxes(const float3& scales);
68 	void SetAxisScales(const float3& scales);
69 	void FixTypeAndScale(float3& scales);
70 	void SetBoundingRadius();
71 
GetVolumeTypeCollisionVolume72 	int GetVolumeType() const { return volumeType; }
SetVolumeTypeCollisionVolume73 	void SetVolumeType(int type) { volumeType = type; }
74 
SetIgnoreHitsCollisionVolume75 	void SetIgnoreHits(bool b) { ignoreHits = b; }
SetUseContHitTestCollisionVolume76 	void SetUseContHitTest(bool b) { useContHitTest = b; }
SetDefaultToPieceTreeCollisionVolume77 	void SetDefaultToPieceTree(bool b) { defaultToPieceTree = b; }
SetDefaultToFootPrintCollisionVolume78 	void SetDefaultToFootPrint(bool b) { defaultToFootPrint = b; }
79 
GetPrimaryAxisCollisionVolume80 	int GetPrimaryAxis() const { return volumeAxes[0]; }
GetSecondaryAxisCollisionVolume81 	int GetSecondaryAxis(int axis) const { return volumeAxes[axis + 1]; }
82 
GetBoundingRadiusCollisionVolume83 	float GetBoundingRadius() const { return volumeBoundingRadius; }
GetBoundingRadiusSqCollisionVolume84 	float GetBoundingRadiusSq() const { return volumeBoundingRadiusSq; }
85 
GetOffsetCollisionVolume86 	float GetOffset(int axis) const { return axisOffsets[axis]; }
GetOffsetsCollisionVolume87 	const float3& GetOffsets() const { return axisOffsets; }
88 
GetScaleCollisionVolume89 	float GetScale(int axis) const { return fAxisScales[axis]; }
GetHScaleCollisionVolume90 	float GetHScale(int axis) const { return hAxisScales[axis]; }
GetHScaleSqCollisionVolume91 	float GetHScaleSq(int axis) const { return hsqAxisScales[axis]; }
GetScalesCollisionVolume92 	const float3& GetScales() const { return fAxisScales; }
GetHScalesCollisionVolume93 	const float3& GetHScales() const { return hAxisScales; }
GetHSqScalesCollisionVolume94 	const float3& GetHSqScales() const { return hsqAxisScales; }
GetHIScalesCollisionVolume95 	const float3& GetHIScales() const { return hiAxisScales; }
96 
IgnoreHitsCollisionVolume97 	bool IgnoreHits() const { return ignoreHits; }
UseContHitTestCollisionVolume98 	bool UseContHitTest() const { return useContHitTest; }
DefaultToSphereCollisionVolume99 	bool DefaultToSphere() const { return (fAxisScales.x == 1.0f && fAxisScales.y == 1.0f && fAxisScales.z == 1.0f); }
DefaultToFootPrintCollisionVolume100 	bool DefaultToFootPrint() const { return defaultToFootPrint; }
DefaultToPieceTreeCollisionVolume101 	bool DefaultToPieceTree() const { return defaultToPieceTree; }
102 
103 	float3 GetWorldSpacePos(const CSolidObject* o, const float3& extOffsets = ZeroVector) const;
104 
105 	float GetPointSurfaceDistance(const CUnit* u, const LocalModelPiece* lmp, const float3& p) const;
106 	float GetPointSurfaceDistance(const CFeature* u, const LocalModelPiece* lmp, const float3& p) const;
107 
108 private:
109 	float GetPointSurfaceDistance(const CMatrix44f& m, const float3& p) const;
110 
111 	float3 fAxisScales;                 ///< full-length axis scales
112 	float3 hAxisScales;                 ///< half-length axis scales
113 	float3 hsqAxisScales;               ///< half-length axis scales (squared)
114 	float3 hiAxisScales;                ///< half-length axis scales (inverted)
115 	float3 axisOffsets;                 ///< offsets wrt. the model's mid-position (world-space)
116 
117 	float volumeBoundingRadius;         ///< radius of minimally-bounding sphere around volume
118 	float volumeBoundingRadiusSq;       ///< squared radius of minimally-bounding sphere
119 
120 	int volumeType;                     ///< which COLVOL_TYPE_* shape we have
121 	int volumeAxes[3];                  ///< [0] is prim. axis, [1] and [2] are sec. axes (all COLVOL_AXIS_*)
122 
123 	bool ignoreHits;                    /// if true, CollisionHandler does not check for hits against us
124 	bool useContHitTest;                /// if true, CollisionHandler does continuous instead of discrete hit-testing
125 	bool defaultToFootPrint;            /// if true, volume becomes a box with dimensions equal to a SolidObject's {x,z}size
126 	bool defaultToPieceTree;            /// if true, volume is owned by a unit but defaults to piece-volume tree for hit-testing
127 };
128 
129 #endif
130 
131