Plasma Engine  2.0
Loading...
Searching...
No Matches
GameGrid_inl.h
1#pragma once
2
3template <class CellData>
5{
6 m_uiGridSizeX = 0;
7 m_uiGridSizeY = 0;
8
9 m_mRotateToWorldspace.SetIdentity();
10 m_mRotateToGridspace.SetIdentity();
11
12 m_vWorldSpaceOrigin.SetZero();
13 m_vLocalSpaceCellSize.Set(1.0f);
14 m_vInverseLocalSpaceCellSize.Set(1.0f);
15}
16
17template <class CellData>
18void plGameGrid<CellData>::CreateGrid(plUInt16 uiSizeX, plUInt16 uiSizeY)
19{
20 m_Cells.Clear();
21
22 m_uiGridSizeX = uiSizeX;
23 m_uiGridSizeY = uiSizeY;
24
25 m_Cells.SetCount(m_uiGridSizeX * m_uiGridSizeY);
26}
27
28template <class CellData>
29void plGameGrid<CellData>::SetWorldSpaceDimensions(const plVec3& vLowerLeftCorner, const plVec3& vCellSize, Orientation ori)
30{
31 plMat3 mRot;
32
33 switch (ori)
34 {
35 case InPlaneXY:
36 mRot.SetIdentity();
37 break;
38 case InPlaneXZ:
40 break;
41 case InPlaneXminusZ:
43 break;
44 }
45
46 SetWorldSpaceDimensions(vLowerLeftCorner, vCellSize, mRot);
47}
49template <class CellData>
50void plGameGrid<CellData>::SetWorldSpaceDimensions(const plVec3& vLowerLeftCorner, const plVec3& vCellSize, const plMat3& mRotation)
51{
52 m_vWorldSpaceOrigin = vLowerLeftCorner;
53 m_vLocalSpaceCellSize = vCellSize;
54 m_vInverseLocalSpaceCellSize = plVec3(1.0f).CompDiv(vCellSize);
55
56 m_mRotateToWorldspace = mRotation;
57 m_mRotateToGridspace = mRotation.GetInverse();
58}
59
60template <class CellData>
62{
63 const plVec3 vCell = (m_mRotateToGridspace * ((vWorldSpacePos - m_vWorldSpaceOrigin)).CompMul(m_vInverseLocalSpaceCellSize));
64
65 // Without the Floor, the border case when the position is outside (-1 / -1) is not immediately detected
66 return plVec2I32((plInt32)plMath::Floor(vCell.x), (plInt32)plMath::Floor(vCell.y));
67}
68
69template <class CellData>
71{
72 return m_vWorldSpaceOrigin + m_mRotateToWorldspace * GetCellLocalSpaceOrigin(vCoord);
73}
74
75template <class CellData>
77{
78 return m_vLocalSpaceCellSize.CompMul(plVec3((float)vCoord.x, (float)vCoord.y, 0.0f));
79}
80
81template <class CellData>
83{
84 return m_vWorldSpaceOrigin + m_mRotateToWorldspace * GetCellLocalSpaceCenter(vCoord);
86
87template <class CellData>
90 return m_vLocalSpaceCellSize.CompMul(plVec3((float)vCoord.x + 0.5f, (float)vCoord.y + 0.5f, 0.5f));
91}
92
93template <class CellData>
95{
96 return (vCoord.x >= 0 && vCoord.x < m_uiGridSizeX && vCoord.y >= 0 && vCoord.y < m_uiGridSizeY);
97}
98
99template <class CellData>
100bool plGameGrid<CellData>::PickCell(const plVec3& vRayStartPos, const plVec3& vRayDirNorm, plVec2I32* out_pCellCoord, plVec3* out_pIntersection) const
101{
102 plPlane p;
103 p = plPlane::MakeFromNormalAndPoint(m_mRotateToWorldspace * plVec3(0, 0, -1), m_vWorldSpaceOrigin);
104
105 plVec3 vPos;
107 if (!p.GetRayIntersection(vRayStartPos, vRayDirNorm, nullptr, &vPos))
108 return false;
109
110 if (out_pIntersection)
111 *out_pIntersection = vPos;
112
113 if (out_pCellCoord)
114 *out_pCellCoord = GetCellAtWorldPosition(vPos);
115
116 return true;
117}
118
119template <class CellData>
121{
122 plVec3 vGridBox(m_uiGridSizeX, m_uiGridSizeY, 1.0f);
123
124 vGridBox = m_mRotateToWorldspace * m_vLocalSpaceCellSize.CompMul(vGridBox);
125
126 return plBoundingBox(m_vWorldSpaceOrigin, m_vWorldSpaceOrigin + vGridBox);
127}
128
129template <class CellData>
130bool plGameGrid<CellData>::GetRayIntersection(const plVec3& vRayStartWorldSpace, const plVec3& vRayDirNormalizedWorldSpace, float fMaxLength,
131 float& out_fIntersection, plVec2I32& out_vCellCoord) const
132{
133 const plVec3 vRayStart = m_mRotateToGridspace * (vRayStartWorldSpace - m_vWorldSpaceOrigin);
134 const plVec3 vRayDir = m_mRotateToGridspace * vRayDirNormalizedWorldSpace;
135
136 plVec3 vGridBox(m_uiGridSizeX, m_uiGridSizeY, 1.0f);
137
138 const plBoundingBox localBox(plVec3(0.0f), m_vLocalSpaceCellSize.CompMul(vGridBox));
139
140 if (localBox.Contains(vRayStart))
141 {
142 // if the ray is already inside the box, we know that a cell is hit
143 out_fIntersection = 0.0f;
144 }
145 else
146 {
147 if (!localBox.GetRayIntersection(vRayStart, vRayDir, &out_fIntersection, nullptr))
148 return false;
149
150 if (out_fIntersection > fMaxLength)
151 return false;
152 }
153
154 const plVec3 vEnterPos = vRayStart + vRayDir * out_fIntersection;
155
156 const plVec3 vCell = vEnterPos.CompMul(m_vInverseLocalSpaceCellSize);
157
158 // Without the Floor, the border case when the position is outside (-1 / -1) is not immediately detected
159 out_vCellCoord = plVec2I32((plInt32)plMath::Floor(vCell.x), (plInt32)plMath::Floor(vCell.y));
160 out_vCellCoord.x = plMath::Clamp(out_vCellCoord.x, 0, m_uiGridSizeX - 1);
161 out_vCellCoord.y = plMath::Clamp(out_vCellCoord.y, 0, m_uiGridSizeY - 1);
162
163 return true;
164}
165
166template <class CellData>
167bool plGameGrid<CellData>::GetRayIntersectionExpandedBBox(const plVec3& vRayStartWorldSpace, const plVec3& vRayDirNormalizedWorldSpace,
168 float fMaxLength, float& out_fIntersection, const plVec3& vExpandBBoxByThis) const
169{
170 const plVec3 vRayStart = m_mRotateToGridspace * (vRayStartWorldSpace - m_vWorldSpaceOrigin);
171 const plVec3 vRayDir = m_mRotateToGridspace * vRayDirNormalizedWorldSpace;
172
173 plVec3 vGridBox(m_uiGridSizeX, m_uiGridSizeY, 1.0f);
174
175 plBoundingBox localBox(plVec3(0.0f), m_vLocalSpaceCellSize.CompMul(vGridBox));
176 localBox.Grow(vExpandBBoxByThis);
177
178 if (localBox.Contains(vRayStart))
179 {
180 // if the ray is already inside the box, we know that a cell is hit
181 out_fIntersection = 0.0f;
182 }
183 else
184 {
185 if (!localBox.GetRayIntersection(vRayStart, vRayDir, &out_fIntersection, nullptr))
186 return false;
187
188 if (out_fIntersection > fMaxLength)
189 return false;
190 }
191
192 return true;
193}
194
195template <class CellData>
197{
198 pCorners[0] = m_vWorldSpaceOrigin;
199 pCorners[1] = m_vWorldSpaceOrigin + m_mRotateToWorldspace * plVec3(m_uiGridSizeX * m_vLocalSpaceCellSize.x, 0, 0);
200 pCorners[2] = m_vWorldSpaceOrigin + m_mRotateToWorldspace * plVec3(0, m_uiGridSizeY * m_vLocalSpaceCellSize.y, 0);
201 pCorners[3] = m_vWorldSpaceOrigin + m_mRotateToWorldspace * plVec3(m_uiGridSizeX * m_vLocalSpaceCellSize.x, m_uiGridSizeY * m_vLocalSpaceCellSize.y, 0);
202}
203
204template <class CellData>
206{
207 stream.WriteVersion(1);
208
209 stream << m_uiGridSizeX;
210 stream << m_uiGridSizeY;
211 stream << m_mRotateToWorldspace;
212 stream << m_mRotateToGridspace;
213 stream << m_vWorldSpaceOrigin;
214 stream << m_vLocalSpaceCellSize;
215 stream << m_vInverseLocalSpaceCellSize;
216 PL_SUCCEED_OR_RETURN(stream.WriteArray(m_Cells));
217
218 return PL_SUCCESS;
219}
220
221template <class CellData>
223{
224 const plTypeVersion version = stream.ReadVersion(1);
225
226 stream >> m_uiGridSizeX;
227 stream >> m_uiGridSizeY;
228 stream >> m_mRotateToWorldspace;
229 stream >> m_mRotateToGridspace;
230 stream >> m_vWorldSpaceOrigin;
231 stream >> m_vLocalSpaceCellSize;
232 stream >> m_vInverseLocalSpaceCellSize;
233 PL_SUCCEED_OR_RETURN(stream.ReadArray(m_Cells));
234
235 return PL_SUCCESS;
236}
static constexpr plAngle MakeFromDegree(float fDegree)
Creates an instance of plAngle that was initialized from degree. (Performs a conversion)
Definition Angle_inl.h:33
bool Contains(const plVec3Template< Type > &vPoint) const
Checks whether the given point is inside the box.
Definition BoundingBox_inl.h:162
void Grow(const plVec3Template< Type > &vDiff)
Will increase the size of the box in all directions by the given amount (per axis).
Definition BoundingBox_inl.h:151
bool GetRayIntersection(const plVec3Template< Type > &vStartPos, const plVec3Template< Type > &vRayDir, Type *out_pIntersectionDistance=nullptr, plVec3Template< Type > *out_pIntersection=nullptr) const
Returns whether the given ray intersects the box. Optionally returns the intersection distance and po...
Definition BoundingBox_inl.h:392
plGameGrid is a general purpose 2D grid structure that has several convenience functions which are of...
Definition GameGrid.h:13
void SetWorldSpaceDimensions(const plVec3 &vLowerLeftCorner, const plVec3 &vCellSize, Orientation ori=InPlaneXZ)
Sets the lower left position of the grid in world space coordinates and the cell size.
Definition GameGrid_inl.h:29
plVec3 GetCellWorldSpaceOrigin(const plVec2I32 &vCoord) const
Returns the lower left world space position of the cell with the given coordinates.
Definition GameGrid_inl.h:70
bool IsValidCellCoordinate(const plVec2I32 &vCoord) const
Checks whether the given cell coordinate is inside valid ranges.
Definition GameGrid_inl.h:94
bool PickCell(const plVec3 &vRayStartPos, const plVec3 &vRayDirNorm, plVec2I32 *out_pCellCoord, plVec3 *out_pIntersection=nullptr) const
Casts a world space ray through the grid and determines which cell is hit (if any).
Definition GameGrid_inl.h:100
bool GetRayIntersection(const plVec3 &vRayStartWorldSpace, const plVec3 &vRayDirNormalizedWorldSpace, float fMaxLength, float &out_fIntersection, plVec2I32 &out_vCellCoord) const
Tests where and at which cell the given world space ray intersects the grids bounding box.
Definition GameGrid_inl.h:130
plBoundingBox GetWorldBoundingBox() const
Returns the world-space bounding box of the grid, as specified via SetWorldDimensions.
Definition GameGrid_inl.h:120
plVec3 GetCellWorldSpaceCenter(const plVec2I32 &vCoord) const
Returns the center world space position of the cell with the given coordinates.
Definition GameGrid_inl.h:82
plVec2I32 GetCellAtWorldPosition(const plVec3 &vWorldSpacePos) const
Returns the coordinate of the cell at the given world-space position. The world space dimension must ...
Definition GameGrid_inl.h:61
void CreateGrid(plUInt16 uiSizeX, plUInt16 uiSizeY)
Clears all data and reallocates the grid with the given dimensions.
Definition GameGrid_inl.h:18
Orientation
Definition GameGrid.h:16
bool GetRayIntersectionExpandedBBox(const plVec3 &vRayStartWorldSpace, const plVec3 &vRayDirNormalizedWorldSpace, float fMaxLength, float &out_fIntersection, const plVec3 &vExpandBBoxByThis) const
Tests whether a ray would hit the grid bounding box, if it were expanded by a constant.
Definition GameGrid_inl.h:167
static plMat3Template< float > MakeAxisRotation(const plVec3Template< float > &vAxis, plAngle angle)
Definition AllClasses_inl.h:189
const plMat3Template< Type > GetInverse(Type fEpsilon=plMath::SmallEpsilon< Type >()) const
Returns the inverse of this matrix.
Definition Mat3_inl.h:170
void SetIdentity()
Sets all elements to zero, except the diagonal, which is set to one.
Definition Mat3_inl.h:150
Interface for binary in (read) streams.
Definition Stream.h:22
plResult ReadArray(plArrayBase< ValueType, ArrayType > &inout_array)
Reads an array of elements from the stream.
Definition Stream_inl.h:349
Interface for binary out (write) streams.
Definition Stream.h:107
plResult WriteArray(const plArrayBase< ValueType, ArrayType > &array)
Writes an array of elements to the stream.
Definition Stream_inl.h:221
PL_ALWAYS_INLINE void WriteVersion(plTypeVersion version)
Writes a type version to the stream.
Definition Stream_inl.h:154
const plVec3Template< Type > CompDiv(const plVec3Template< Type > &rhs) const
Returns the component-wise division of *this and rhs.
Definition Vec3_inl.h:354
const plVec3Template< Type > CompMul(const plVec3Template< Type > &rhs) const
Returns the component-wise multiplication of *this and rhs.
Definition Vec3_inl.h:345
constexpr PL_ALWAYS_INLINE T Clamp(T value, T min_val, T max_val)
Clamps "value" to the range [min; max]. Returns "value", if it is inside the range already.
Definition Math_inl.h:51
static plPlaneTemplate< float > MakeFromNormalAndPoint(const plVec3Template< float > &vNormal, const plVec3Template< float > &vPointOnPlane)
Definition Plane_inl.h:26
bool GetRayIntersection(const plVec3Template< Type > &vRayStartPos, const plVec3Template< Type > &vRayDir, Type *out_pIntersectionDinstance=nullptr, plVec3Template< Type > *out_pIntersection=nullptr) const
Returns true, if the ray hit the plane. The intersection time describes at which multiple of the ray ...
Definition Plane_inl.h:368
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54