Cuberite
A lightweight, fast and extensible game server for Minecraft
PiecePool.cpp
Go to the documentation of this file.
1 // PiecePool.cpp
2 
3 // Implements the cPiecePool class representing a pool of cPieces - "parts" of a structure, used in piece-generators
4 // A cPiece is a single static part of a structure that can rotate around the Y axis, has connectors to other pieces and knows how to draw itself into the world.
5 // The pool manages the pieces and provides lists of its pieces matching criteria, and provides relative weights for the random distribution of pieces.
6 
7 #include "Globals.h"
8 #include "PiecePool.h"
9 #include "VerticalStrategy.h"
10 #include "VerticalLimit.h"
11 #include "PieceModifier.h"
12 
13 
14 
15 
16 
18 // cPiece:
19 
20 bool cPiece::SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings)
21 {
22  auto strategy = CreateVerticalStrategyFromString(a_StrategyDesc, a_LogWarnings);
23  if (strategy == nullptr)
24  {
25  return false;
26  }
27  m_VerticalStrategy = strategy;
28  return true;
29 }
30 
31 
32 
33 
34 
35 bool cPiece::SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings)
36 {
37  auto limit = CreateVerticalLimitFromString(a_LimitDesc, a_LogWarnings);
38  if (limit == nullptr)
39  {
40  return false;
41  }
42  m_VerticalLimit = limit;
43  return true;
44 }
45 
46 
47 
48 
49 
50 bool cPiece::SetPieceModifiersFromString(const AString & a_Definition, bool a_LogWarnings)
51 {
52  auto modifiers = std::make_shared<cPieceModifiers>();
53  if (!CreatePieceModifierFromString(a_Definition, modifiers, a_LogWarnings))
54  {
55  return false;
56  }
57 
58  cPieceModifiers Modifiers;
59  for (size_t i = 0; i < modifiers->size(); i++)
60  {
61  Modifiers.push_back(std::move(modifiers->at(i)));
62  }
63 
64  m_Modifiers = Modifiers;
65 
66  return true;
67 }
68 
69 
70 
71 
72 
73 Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
74 {
75  Vector3i Size = GetSize();
76  switch (a_NumCCWRotations)
77  {
78  case 0:
79  {
80  // No rotation needed
81  return a_Pos;
82  }
83  case 1:
84  {
85  // 1 CCW rotation:
86  return Vector3i(a_Pos.z, a_Pos.y, Size.x - a_Pos.x - 1);
87  }
88  case 2:
89  {
90  // 2 rotations ( = axis flip):
91  return Vector3i(Size.x - a_Pos.x - 1, a_Pos.y, Size.z - a_Pos.z - 1);
92  }
93  case 3:
94  {
95  // 1 CW rotation:
96  return Vector3i(Size.z - a_Pos.z - 1, a_Pos.y, a_Pos.x);
97  }
98  }
99  ASSERT(!"Unhandled rotation");
100  return a_Pos;
101 }
102 
103 
104 
105 
106 
107 cPiece::cConnector cPiece::RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
108 {
109  cPiece::cConnector res(a_Connector);
110 
111  // Rotate the res connector:
112  switch (a_NumCCWRotations)
113  {
114  case 0:
115  {
116  // No rotation needed
117  break;
118  }
119  case 1:
120  {
121  // 1 CCW rotation:
123  break;
124  }
125  case 2:
126  {
127  // 2 rotations ( = axis flip):
129  break;
130  }
131  case 3:
132  {
133  // 1 CW rotation:
135  break;
136  }
137  }
138  res.m_Pos = RotatePos(a_Connector.m_Pos, a_NumCCWRotations);
139 
140  // Move the res connector:
141  res.m_Pos.x += a_MoveX;
142  res.m_Pos.y += a_MoveY;
143  res.m_Pos.z += a_MoveZ;
144 
145  return res;
146 }
147 
148 
149 
150 
151 
153  const cPiece::cConnector & a_MyConnector,
154  const Vector3i & a_ToConnectorPos,
155  int a_NumCCWRotations
156 ) const
157 {
158  ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4));
159  Vector3i ConnPos = RotatePos(a_MyConnector.m_Pos, a_NumCCWRotations);
160  ConnPos = a_ToConnectorPos - ConnPos;
161  return RotateMoveHitBox(a_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z);
162 }
163 
164 
165 
166 
167 
168 cCuboid cPiece::RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
169 {
170  ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4));
171  cCuboid res = GetHitBox();
172  res.p1 = RotatePos(res.p1, a_NumCCWRotations);
173  res.p2 = RotatePos(res.p2, a_NumCCWRotations);
174  res.p1.Move(a_MoveX, a_MoveY, a_MoveZ);
175  res.p2.Move(a_MoveX, a_MoveY, a_MoveZ);
176  return res;
177 }
178 
179 
180 
181 
182 
184 // cPiece::cConnector:
185 
186 cPiece::cConnector::cConnector(int a_X, int a_Y, int a_Z, int a_Type, eDirection a_Direction) :
187  m_Pos(a_X, a_Y, a_Z),
188  m_Type(a_Type),
189  m_Direction(a_Direction)
190 {
191 }
192 
193 
194 
195 
196 
197 cPiece::cConnector::cConnector(const Vector3i & a_Pos, int a_Type, eDirection a_Direction) :
198  m_Pos(a_Pos),
199  m_Type(a_Type),
200  m_Direction(a_Direction)
201 {
202 }
203 
204 
205 
206 
207 
209 {
210  switch (a_Direction)
211  {
212  case dirXM: return Vector3i(a_Pos.x - 1, a_Pos.y, a_Pos.z);
213  case dirXP: return Vector3i(a_Pos.x + 1, a_Pos.y, a_Pos.z);
214  case dirYM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
215  case dirYP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
216  case dirZM: return Vector3i(a_Pos.x, a_Pos.y, a_Pos.z - 1);
217  case dirZP: return Vector3i(a_Pos.x, a_Pos.y, a_Pos.z + 1);
218  case dirYM_XM_ZM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
219  case dirYM_XM_ZP: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
220  case dirYM_XP_ZM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
221  case dirYM_XP_ZP: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z);
222  case dirYP_XM_ZM: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
223  case dirYP_XM_ZP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
224  case dirYP_XP_ZM: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
225  case dirYP_XP_ZP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z);
226  }
227  UNREACHABLE("Unsupported connector direction");
228 }
229 
230 
231 
232 
233 
235 {
236  switch (a_Direction)
237  {
238  case dirXM: return "x-";
239  case dirXP: return "x+";
240  case dirYM: return "y-";
241  case dirYP: return "y+";
242  case dirZM: return "z-";
243  case dirZP: return "z+";
244  case dirYM_XM_ZM: return "y-x-z-";
245  case dirYM_XM_ZP: return "y-x-z+";
246  case dirYM_XP_ZM: return "y-x+z-";
247  case dirYM_XP_ZP: return "y-x+z+";
248  case dirYP_XM_ZM: return "y+x-z-";
249  case dirYP_XM_ZP: return "y+x-z+";
250  case dirYP_XP_ZM: return "y+x+z-";
251  case dirYP_XP_ZP: return "y+x+z+";
252  }
253  UNREACHABLE("Unsupported connector direction");
254 }
255 
256 
257 
258 
259 
261 {
262  switch (a_Direction)
263  {
264  case dirXM:
265  case dirXP:
266  case dirYM:
267  case dirYP:
268  case dirZM:
269  case dirZP:
270  case dirYM_XM_ZM:
271  case dirYM_XM_ZP:
272  case dirYM_XP_ZM:
273  case dirYM_XP_ZP:
274  case dirYP_XM_ZM:
275  case dirYP_XM_ZP:
276  case dirYP_XP_ZM:
277  case dirYP_XP_ZP:
278  {
279  return true;
280  }
281  }
282  return false;
283 }
284 
285 
286 
287 
288 
290 {
291  // 180-degree rotation:
292  switch (a_Direction)
293  {
294  case dirXM: return dirXP;
295  case dirXP: return dirXM;
296  case dirYM: return dirYM;
297  case dirYP: return dirYP;
298  case dirZM: return dirZM;
299  case dirZP: return dirZP;
300  case dirYM_XM_ZM: return dirYM_XP_ZP;
301  case dirYM_XM_ZP: return dirYM_XP_ZM;
302  case dirYM_XP_ZM: return dirYM_XM_ZP;
303  case dirYM_XP_ZP: return dirYM_XM_ZM;
304  case dirYP_XM_ZM: return dirYP_XP_ZP;
305  case dirYP_XM_ZP: return dirYP_XP_ZM;
306  case dirYP_XP_ZM: return dirYP_XM_ZP;
307  case dirYP_XP_ZP: return dirYP_XM_ZM;
308  }
309  UNREACHABLE("Unsupported connector direction");
310 }
311 
312 
313 
314 
315 
317 {
318  // 90 degrees CCW rotation:
319  switch (a_Direction)
320  {
321  case dirXM: return dirZP;
322  case dirXP: return dirZM;
323  case dirYM: return dirYM;
324  case dirYP: return dirYP;
325  case dirZM: return dirXM;
326  case dirZP: return dirXP;
327  case dirYM_XM_ZM: return dirYM_XM_ZP;
328  case dirYM_XM_ZP: return dirYM_XP_ZP;
329  case dirYM_XP_ZM: return dirYM_XM_ZM;
330  case dirYM_XP_ZP: return dirYM_XP_ZM;
331  case dirYP_XM_ZM: return dirYP_XM_ZP;
332  case dirYP_XM_ZP: return dirYP_XP_ZP;
333  case dirYP_XP_ZM: return dirYP_XM_ZM;
334  case dirYP_XP_ZP: return dirYP_XP_ZM;
335  }
336  UNREACHABLE("Unsupported connector direction");
337 }
338 
339 
340 
341 
342 
344 {
345  // 90 degrees CW rotation:
346  switch (a_Direction)
347  {
348  case dirXM: return dirZM;
349  case dirXP: return dirZP;
350  case dirYM: return dirYM;
351  case dirYP: return dirYP;
352  case dirZM: return dirXP;
353  case dirZP: return dirXM;
354  case dirYM_XM_ZM: return dirYM_XP_ZM;
355  case dirYM_XM_ZP: return dirYM_XM_ZM;
356  case dirYM_XP_ZM: return dirYM_XP_ZP;
357  case dirYM_XP_ZP: return dirYM_XM_ZP;
358  case dirYP_XM_ZM: return dirYP_XP_ZM;
359  case dirYP_XM_ZP: return dirYP_XM_ZM;
360  case dirYP_XP_ZM: return dirYP_XP_ZP;
361  case dirYP_XP_ZP: return dirYP_XM_ZP;
362  }
363  UNREACHABLE("Unsupported connector direction");
364 }
365 
366 
367 
368 
369 
371 {
372  // Translation of direction - direction -> number of CCW rotations needed:
373  // You need DirectionRotationTable[fixed][rot] CCW turns to connect rot to fixed (they are opposite)
374  // -1 if not possible
375  static const int DirectionRotationTable[14][14] =
376  {
377  /* YM, YP, ZM, ZP, XM, XP, YM-XM-ZM, YM-XM-ZP, YM-XP-ZM, YM-XP-ZP, YP-XM-ZM, YP-XM-ZP, YP-XP-ZM, YP-XP-ZP */
378  /* YM */ { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
379  /* YP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
380  /* ZM */ {-1, -1, 2, 0, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1},
381  /* ZP */ {-1, -1, 0, 2, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1},
382  /* XM */ {-1, -1, 3, 1, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1},
383  /* XP */ {-1, -1, 1, 3, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1},
384  /* YM-XM-ZM */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 1, 2},
385  /* YM-XM-ZP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, 2, 3},
386  /* YM-XP-ZM */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 2, 0, 1},
387  /* YM-XP-ZP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 1, 3, 0},
388  /* YP-XM-ZM */ {-1, -1, -1, -1, -1, -1, 0, 3, 1, 2, -1, -1, -1, -1},
389  /* YP-XM-ZP */ {-1, -1, -1, -1, -1, -1, 1, 0, 2, 3, -1, -1, -1, -1},
390  /* YP-XP-ZM */ {-1, -1, -1, -1, -1, -1, 3, 2, 0, 1, -1, -1, -1, -1},
391  /* YP-XP-ZP */ {-1, -1, -1, -1, -1, -1, 2, 1, 3, 0, -1, -1, -1, -1},
392  };
393 
394  return DirectionRotationTable[a_FixedDir][a_RotatingDir];
395 }
396 
397 
398 
399 
400 
402 {
403  // First try converting as a number:
404  int dirInt;
405  if (StringToInteger(a_Value, dirInt))
406  {
407  if (!IsValidDirection(dirInt))
408  {
409  return false;
410  }
411  a_Out = static_cast<eDirection>(dirInt);
412  return true;
413  }
414 
415  // Compare to string representation:
416  static const struct
417  {
418  const char * m_String;
419  eDirection m_Value;
420  } StringDirections[] =
421  {
422  {"x-", dirXM},
423  {"x+", dirXP},
424  {"y-", dirYM},
425  {"y+", dirYP},
426  {"z-", dirZM},
427  {"z+", dirZP},
428  {"y-x-z-", dirYM_XM_ZM},
429  {"y-x-z+", dirYM_XM_ZP},
430  {"y-x+z-", dirYM_XP_ZM},
431  {"y-x+z+", dirYM_XP_ZP},
432  {"y+x-z-", dirYP_XM_ZM},
433  {"y+x-z+", dirYP_XM_ZP},
434  {"y+x+z-", dirYP_XP_ZM},
435  {"y+x+z+", dirYP_XP_ZP},
436 
437  // Alternate names, with slashes:
438  {"y-/x-/z-", dirYM_XM_ZM},
439  {"y-/x-/z+", dirYM_XM_ZP},
440  {"y-/x+/z-", dirYM_XP_ZM},
441  {"y-/x+/z+", dirYM_XP_ZP},
442  {"y+/x-/z-", dirYP_XM_ZM},
443  {"y+/x-/z+", dirYP_XM_ZP},
444  {"y+/x+/z-", dirYP_XP_ZM},
445  {"y+/x+/z+", dirYP_XP_ZP},
446  };
447  auto lcValue = StrToLower(a_Value);
448  for (size_t i = 0; i < ARRAYCOUNT(StringDirections); i++)
449  {
450  if (strcmp(lcValue.c_str(), StringDirections[i].m_String) == 0)
451  {
452  a_Out = StringDirections[i].m_Value;
453  return true;
454  }
455  }
456 
457  // Not understood, failure:
458  return false;
459 }
460 
461 
462 
463 
464 
466 // cPlacedPiece:
467 
468 cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations) :
469  m_Parent(a_Parent),
470  m_Piece(&a_Piece),
471  m_Coords(a_Coords),
472  m_NumCCWRotations(a_NumCCWRotations),
473  m_HasBeenMovedToGround(false)
474 {
475  m_Depth = (m_Parent == nullptr) ? 0 : (m_Parent->GetDepth() + 1);
476  m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z);
477  m_HitBox.Sort();
478 }
479 
480 
481 
482 
483 
485 {
486  cPiece::cConnectors Connectors = m_Piece->GetConnectors();
487  ASSERT(Connectors.size() >= a_Index);
488  return m_Piece->RotateMoveConnector(Connectors[a_Index], m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z);
489 }
490 
491 
492 
493 
494 
496 {
498 }
499 
500 
501 
502 
503 
504 void cPlacedPiece::MoveToGroundBy(int a_OffsetY)
505 {
506  m_Coords.y += a_OffsetY;
507  m_HasBeenMovedToGround = true;
508 }
509 
510 
511 
512 
const char * m_String
Definition: BiomeDef.cpp:17
bool CreatePieceModifierFromString(const AString &a_Definition, std::shared_ptr< cPiece::cPieceModifiers > &a_Modifiers, bool a_LogWarnings)
cPiece::cVerticalLimitPtr CreateVerticalLimitFromString(const AString &a_LimitDesc, bool a_LogWarnings)
Returns a new cPiece::cVerticalLimit descendant based on the specified description.
cPiece::cVerticalStrategyPtr CreateVerticalStrategyFromString(const AString &a_StrategyDesc, bool a_LogWarnings)
Returns a new cPiece::cVerticalStrategy descendant based on the specified description.
#define UNREACHABLE(x)
Definition: Globals.h:288
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:231
#define ASSERT(x)
Definition: Globals.h:276
eMonsterType m_Type
Definition: Monster.cpp:35
AString StrToLower(const AString &s)
Returns a lower-cased copy of the string.
std::string AString
Definition: StringUtils.h:11
bool StringToInteger(const AString &a_str, T &a_Num)
Parses any integer type.
Definition: StringUtils.h:143
Vector3< int > Vector3i
Definition: Vector3.h:487
Definition: Cuboid.h:10
Vector3i p2
Definition: Cuboid.h:13
void Sort(void)
Definition: Cuboid.cpp:23
Vector3i p1
Definition: Cuboid.h:13
Represents a single piece.
Definition: PiecePool.h:21
virtual cCuboid GetHitBox(void) const =0
Returns the "hitbox" of this piece.
virtual cConnectors GetConnectors(void) const =0
Returns all of the available connectors that the piece has.
cCuboid RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
Returns the hitbox after the specified number of CCW rotations and moved by the specified amounts.
Definition: PiecePool.cpp:168
cVerticalStrategyPtr m_VerticalStrategy
The strategy used for vertical placement of this piece when it is used as a starting piece.
Definition: PiecePool.h:179
cCuboid RotateHitBoxToConnector(const cConnector &a_MyConnector, const Vector3i &a_ToConnectorPos, int a_NumCCWRotations) const
Returns the hitbox after the specified number of rotations and moved so that a_MyConnector is placed ...
Definition: PiecePool.cpp:152
bool SetVerticalStrategyFromString(const AString &a_StrategyDesc, bool a_LogWarnings)
Sets the vertical strategy based on the description in the string.
Definition: PiecePool.cpp:20
cPieceModifiers m_Modifiers
The modifiers which are modifying piece's blocks.
Definition: PiecePool.h:185
virtual Vector3i GetSize(void) const =0
Returns the dimensions of this piece.
cVerticalLimitPtr m_VerticalLimit
The checker that verifies each placement's vertical position.
Definition: PiecePool.h:182
bool SetVerticalLimitFromString(const AString &a_LimitDesc, bool a_LogWarnings)
Sets the vertical limit based on the description string.
Definition: PiecePool.cpp:35
Vector3i RotatePos(const Vector3i &a_Pos, int a_NumCCWRotations) const
Returns a copy of the a_Pos after rotating the piece the specified number of CCW rotations.
Definition: PiecePool.cpp:73
bool SetPieceModifiersFromString(const AString &a_Definition, bool a_LogWarnings)
Sets the modifiers with their params in the string.
Definition: PiecePool.cpp:50
cConnector RotateMoveConnector(const cConnector &a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
Returns a copy of the connector that is rotated and then moved by the specified amounts.
Definition: PiecePool.cpp:107
std::vector< cConnector > cConnectors
Definition: PiecePool.h:95
std::vector< cPieceModifierPtr > cPieceModifiers
Definition: PiecePool.h:176
cConnector(int a_X, int a_Y, int a_Z, int a_Type, eDirection a_Direction)
Definition: PiecePool.cpp:186
static int GetNumCCWRotationsToFit(eDirection a_FixedDir, eDirection a_RotatingDir)
Returns the number of CCW rotations that a_RotatingDir requires in order to be the counter-direction ...
Definition: PiecePool.cpp:370
static eDirection RotateDirectionCCW(eDirection a_Direction)
Returns the direction corresponding to the given direction rotated 90 degrees CCW around the Y axis.
Definition: PiecePool.cpp:316
static eDirection RotateDirection(eDirection a_Direction)
Returns the direction corresponding to the given direction rotated 180 degrees around the Y axis.
Definition: PiecePool.cpp:289
Vector3i m_Pos
Position relative to the piece.
Definition: PiecePool.h:50
static bool StringToDirection(const AString &a_Value, eDirection &a_Out)
Converts the string representation of a direction into the eDirection enum value.
Definition: PiecePool.cpp:401
eDirection m_Direction
Direction in which the connector is facing.
Definition: PiecePool.h:58
static const char * DirectionToString(eDirection a_Direction)
Returns the string representation of the direction.
Definition: PiecePool.cpp:234
static Vector3i AddDirection(const Vector3i &a_Pos, eDirection a_Direction)
Returns the position of the block that has the specified direction from the specified position.
Definition: PiecePool.cpp:208
static bool IsValidDirection(int a_Direction)
Returns true if the specified number corresponds to a valid eDirection.
Definition: PiecePool.cpp:260
static eDirection RotateDirectionCW(eDirection a_Direction)
Returns the direction corresponding to the given direction rotated 90 degrees CW around the Y axis.
Definition: PiecePool.cpp:343
Represents a single piece that has been placed to specific coords in the world.
Definition: PiecePool.h:328
void MoveToGroundBy(int a_OffsetY)
Moves the placed piece Y-wise by the specified offset.
Definition: PiecePool.cpp:504
cPlacedPiece(const cPlacedPiece *a_Parent, const cPiece &a_Piece, const Vector3i &a_Coords, int a_NumCCWRotations)
Definition: PiecePool.cpp:468
cPiece::cConnector GetRotatedConnector(size_t a_Index) const
Returns the connector at the specified index, rotated in the actual placement.
Definition: PiecePool.cpp:484
const cPiece * m_Piece
Definition: PiecePool.h:358
int GetDepth(void) const
Definition: PiecePool.h:337
const cPlacedPiece * m_Parent
Definition: PiecePool.h:357
int m_NumCCWRotations
Definition: PiecePool.h:360
bool m_HasBeenMovedToGround
Set to true once the piece has been moved Y-wise.
Definition: PiecePool.h:366
Vector3i m_Coords
Definition: PiecePool.h:359
cCuboid m_HitBox
Definition: PiecePool.h:361
T x
Definition: Vector3.h:17
void Move(T a_X, T a_Y, T a_Z)
Definition: Vector3.h:162
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17