Game of Ur 0.3.3
This is a computer adaptation of Game of Ur, written in C++ mainly using SDL and OpenGL.
Loading...
Searching...
No Matches
spatial_query_math.hpp
Go to the documentation of this file.
1
12
13#ifndef FOOLSENGINE_SPATIALQUERYMATH_H
14#define FOOLSENGINE_SPATIALQUERYMATH_H
15
16#include <glm/glm.hpp>
17#include <glm/gtc/quaternion.hpp>
18
20#include "core/ecs_world.hpp"
21
22namespace ToyMaker {
23 struct ObjectBounds;
25
35 std::array<AreaTriangle, 12> computeBoxFaceTriangles(const std::array<glm::vec3, 8>& boxCorners);
36
43 std::pair<bool, glm::vec3> computeIntersection(const Ray& ray, const Plane& plane);
44
51 std::pair<bool, glm::vec3> computeIntersection(const Ray& ray, const AreaTriangle& triangle);
52
62 std::pair<uint8_t, std::pair<glm::vec3, glm::vec3>> computeIntersections(const Ray& ray, const AxisAlignedBounds& axisAlignedBounds);
63
64
72 // std::pair<uint8_t, std::pair<glm::vec3, glm::vec3>> computeIntersections(const Ray& ray, const ObjectBounds& objectbounds);
73
78 // bool overlaps(const Ray& ray, const ObjectBounds& objectBounds);
79
85 bool overlaps(const glm::vec3& point, const AxisAlignedBounds& bounds);
86
92 bool overlaps(const Ray& ray, const AxisAlignedBounds& bounds);
93
99 bool overlaps(const AxisAlignedBounds& one, const AxisAlignedBounds& two);
100
106 bool contains(const glm::vec3& point, const AxisAlignedBounds& bounds);
107
113 bool contains(const Ray& ray, const AxisAlignedBounds& bounds);
119 bool contains(const AxisAlignedBounds& one, const AxisAlignedBounds& two);
120
136 inline static std::string getComponentTypeName() { return "ObjectBounds"; }
137
142 enum class TrueVolumeType: uint8_t {
143 BOX,
144 SPHERE,
145 CAPSULE,
146 };
147
153 VolumeBox mBox { .mDimensions{ glm::vec3{0.f} } };
154 VolumeCapsule mCapsule;
155 VolumeSphere mSphere;
156 };
157
169 static ObjectBounds create(const VolumeBox& box, const glm::vec3& positionOffset, const glm::vec3& orientationOffset);
170
182 static ObjectBounds create(const VolumeCapsule& capsule, const glm::vec3& positionOffset, const glm::vec3& orientationOffset);
183
195 static ObjectBounds create(const VolumeSphere& sphere, const glm::vec3& positionOffset, const glm::vec3& orientationOffset);
196
201 TrueVolumeType mType { TrueVolumeType::BOX };
202
208
213 glm::vec3 mPosition { 0.f };
214
219 glm::vec3 mPositionOffset { 0.f };
220
225 glm::quat mOrientation { glm::vec3{ 0.f } };
226
232 glm::quat mOrientationOffset { glm::vec3{ 0.f } };
233
239 void applyModelMatrix(const glm::mat4& modelMatrix);
240
246 inline glm::mat3 getLocalRotationTransform() const {
247 return glm::mat3_cast(glm::normalize(mOrientationOffset));
248 }
249
255 inline glm::mat3 getWorldRotationTransform() const {
256 return glm::mat3_cast(glm::normalize(mOrientation));
257 }
258
264 glm::vec3 getComputedWorldPosition() const;
265
271 glm::quat getComputedWorldOrientation() const;
272
278 std::array<glm::vec3, 8> getVolumeRelativeBoxCorners() const;
279
285 std::array<glm::vec3, 8> getLocalOrientedBoxCorners() const;
286
292 std::array<glm::vec3, 8> getWorldOrientedBoxCorners() const;
293
303 protected:
304 };
305
318 public:
324 inline static std::string getComponentTypeName() { return "AxisAlignedBounds"; }
325
330 using Extents = std::pair<glm::vec3, glm::vec3>;
331
337
343 AxisAlignedBounds(const ObjectBounds& objectBounds);
344
350 AxisAlignedBounds(const Extents& axisAlignedExtents);
351
358 AxisAlignedBounds(const glm::vec3& position, const glm::vec3& dimensions):
359 AxisAlignedBounds { Extents{{position + .5f*dimensions}, {position - .5f*dimensions}} }
360 {}
361
368 AxisAlignedBounds operator+(const AxisAlignedBounds& other) const;
369
375 std::array<glm::vec3, 8> getAxisAlignedBoxCorners() const;
376
382 inline std::array<AreaTriangle, 12> getAxisAlignedBoxFaceTriangles() const { return computeBoxFaceTriangles(getAxisAlignedBoxCorners()); }
383
389 Extents getAxisAlignedBoxExtents() const;
390
396 inline glm::vec3 getDimensions() const { return mExtents.first - mExtents.second; }
397
403 inline glm::vec3 getPosition() const { return mExtents.second + .5f * getDimensions(); };
404
411 inline bool isSensible() const {
412 return (
413 isFinite(mExtents.first) && isFinite(mExtents.second)
414 );
415 }
416
422 inline void setPosition(const glm::vec3& position) {
423 assert(isFinite(position) && "Invalid position specified. Position must be finite");
424 const glm::vec3 deltaPosition { position - getPosition() };
425 mExtents.first += deltaPosition;
426 mExtents.second += deltaPosition;
427 }
428
434 inline void setDimensions(const glm::vec3& dimensions) {
435 assert(isNonNegative(dimensions) && isFinite(dimensions) && "Invalid dimensions provided. Dimensions must be non negative and finite");
436 const glm::vec3 position { getPosition() };
437 const glm::vec3 deltaDimensions { dimensions - getDimensions() };
438 mExtents.first += .5f * deltaDimensions;
439 mExtents.second -= .5f * deltaDimensions;
440 }
441 private:
447 void setByExtents(const Extents& axisAlignedExtents);
448
453 Extents mExtents {glm::vec3{0.f}, glm::vec3{0.f}};
454 };
455
460 NLOHMANN_JSON_SERIALIZE_ENUM( ObjectBounds::TrueVolumeType, {
461 {ObjectBounds::TrueVolumeType::BOX, "box"},
462 {ObjectBounds::TrueVolumeType::SPHERE, "sphere"},
463 {ObjectBounds::TrueVolumeType::CAPSULE, "capsule"},
464 })
465
470 inline void to_json(nlohmann::json& json, const ObjectBounds& objectBounds) {
471 json = {
472 {"type", ObjectBounds::getComponentTypeName()},
473 {"volume_type", objectBounds.mType},
474 {"position_offset", { objectBounds.mPositionOffset.x, objectBounds.mPositionOffset.y, objectBounds.mPositionOffset.z}},
475 {"orientation_offset", { objectBounds.mOrientationOffset.w, objectBounds.mOrientationOffset.x, objectBounds.mOrientationOffset.y, objectBounds.mOrientationOffset.z }},
476 };
477 switch(objectBounds.mType) {
478 case ObjectBounds::TrueVolumeType::BOX:
479 json["volume_properties"] = {
480 {"width", objectBounds.mTrueVolume.mBox.mDimensions.x},
481 {"height", objectBounds.mTrueVolume.mBox.mDimensions.y},
482 {"depth", objectBounds.mTrueVolume.mBox.mDimensions.z},
483 };
484 break;
485 case ObjectBounds::TrueVolumeType::SPHERE:
486 json["volume_properties"] = {
487 {"radius", objectBounds.mTrueVolume.mSphere.mRadius},
488 };
489 break;
490 case ObjectBounds::TrueVolumeType::CAPSULE:
491 json["volume_properties"] = {
492 {"radius", objectBounds.mTrueVolume.mCapsule.mRadius},
493 {"height", objectBounds.mTrueVolume.mCapsule.mHeight},
494 };
495 break;
496 };
497 }
498
500 inline void from_json(const nlohmann::json& json, ObjectBounds& objectBounds) {
501 assert(json.at("type") == ObjectBounds::getComponentTypeName() && "Incorrect type property for an objectBounds component");
502 const glm::vec3 positionOffset {
503 json.at("position_offset")[0],
504 json.at("position_offset")[1],
505 json.at("position_offset")[2],
506 };
507 const glm::vec3 orientationOffset {
508 glm::eulerAngles(glm::normalize(glm::quat {
509 json.at("orientation_offset")[0],
510 json.at("orientation_offset")[1],
511 json.at("orientation_offset")[2],
512 json.at("orientation_offset")[3]
513 }))
514 };
515
516 switch (static_cast<ObjectBounds::TrueVolumeType>(json.at("volume_type"))) {
517 case ObjectBounds::TrueVolumeType::BOX:
518 objectBounds = ObjectBounds::create(
519 VolumeBox{ .mDimensions {
520 json.at("volume_properties").at("width").get<float>(),
521 json.at("volume_properties").at("height").get<float>(),
522 json.at("volume_properties").at("depth").get<float>(),
523 } },
524 positionOffset,
525 orientationOffset
526 );
527 break;
528
529 case ObjectBounds::TrueVolumeType::SPHERE:
530 objectBounds = ObjectBounds::create(
531 VolumeSphere { .mRadius { json.at("volume_properties").at("radius").get<float>() }},
532 positionOffset,
533 orientationOffset
534 );
535 break;
536
537 case ObjectBounds::TrueVolumeType::CAPSULE:
538 objectBounds = ObjectBounds::create(
539 VolumeCapsule {
540 .mHeight { json.at("volume_properties").at("height").get<float>() },
541 .mRadius { json.at("volume_properties").at("radius").get<float>() },
542 },
543 positionOffset,
544 orientationOffset
545 );
546 break;
547 }
548 }
549
551 inline void to_json(nlohmann::json& json, const AxisAlignedBounds& axisAlignedBounds) { /* never used, so pass */
552 (void)json; // prevent unused parameter warnings
553 (void)axisAlignedBounds; // prevent unused parameter warnings
554 }
555
557 inline void from_json(const nlohmann::json& json, AxisAlignedBounds& objectBounds) { /* never used, so pass */
558 (void)json; // prevent unused parameter warnings
559 (void)objectBounds; // prevent unused parameter warnings
560 }
561
562}
563
564#endif
An object containing a coarse simplified representation, AABB, of spatially queryable objects.
Definition spatial_query_math.hpp:317
std::array< AreaTriangle, 12 > getAxisAlignedBoxFaceTriangles() const
Gets an array of triangles in the world which make up the surface of this box.
Definition spatial_query_math.hpp:382
void setPosition(const glm::vec3 &position)
Sets the position of this box.
Definition spatial_query_math.hpp:422
void setDimensions(const glm::vec3 &dimensions)
Sets the dimensions of this box.
Definition spatial_query_math.hpp:434
AxisAlignedBounds(const glm::vec3 &position, const glm::vec3 &dimensions)
Constructs a new Axis Aligned Bounds object based on the position of the origin and the dimensions of...
Definition spatial_query_math.hpp:358
std::pair< glm::vec3, glm::vec3 > Extents
Pair where first: right top front corner; second: left back bottom corner of an AABB.
Definition spatial_query_math.hpp:330
glm::vec3 getDimensions() const
Gets the dimensions of this box.
Definition spatial_query_math.hpp:396
Extents mExtents
The pair of coordinates at the extreme corners of this box (i.e., the top-right-front and bottom-left...
Definition spatial_query_math.hpp:453
std::array< glm::vec3, 8 > getAxisAlignedBoxCorners() const
Gets an array of coordinates of the corners of this box.
Definition spatial_query_math.cpp:386
AxisAlignedBounds()
Constructs a new empty Axis Aligned Bounds object.
Definition spatial_query_math.cpp:366
bool isSensible() const
Tests whether this box is sensible (it has a finite position, and finite positive dimensions).
Definition spatial_query_math.hpp:411
static std::string getComponentTypeName()
Gets the component type string for this object.
Definition spatial_query_math.hpp:324
glm::vec3 getPosition() const
Gets the position of the origin of this box.
Definition spatial_query_math.hpp:403
ToyMaker Engine's implementation of an ECS system.
std::pair< bool, glm::vec3 > computeIntersection(const Ray &ray, const Plane &plane)
Returns a bool-vector pair, with bool indicating whether a point of intersection was found,...
Definition spatial_query_math.cpp:8
bool contains(const glm::vec3 &point, const AxisAlignedBounds &bounds)
Returns whether point is contained by bounds.
Definition spatial_query_math.cpp:175
std::pair< uint8_t, std::pair< glm::vec3, glm::vec3 > > computeIntersections(const Ray &ray, const AxisAlignedBounds &axisAlignedBounds)
Returns an unsigned int and vector-pair pair, with unsigned indicating whether any and how many point...
Definition spatial_query_math.cpp:91
bool overlaps(const glm::vec3 &point, const AxisAlignedBounds &bounds)
Returns an unsigned int and vector pair pair, with int indicating whether and how many points of inte...
Definition spatial_query_math.cpp:128
bool isNonNegative(float number)
Tests whether a number is non-negative.
Definition spatial_query_basic_types.hpp:94
std::array< AreaTriangle, 12 > computeBoxFaceTriangles(const std::array< glm::vec3, 8 > &boxCorners)
Generates a list of triangles making up the surface of a box situated somewhere in the world,...
Definition spatial_query_math.cpp:254
bool isFinite(float number)
Tests whether a given number is finite.
Definition spatial_query_basic_types.hpp:47
Namespace containing all class definitions and functions related to the ToyMaker engine.
Definition camera_system.hpp:20
Classes and structs representing data related to the engine's spatial query system (the precursor to ...
A set of 3 points located in the world forming a (hopefully sensible) triangle.
Definition spatial_query_basic_types.hpp:297
A component defining the true bounds of a spatially queryable object situated somewhere in the world.
Definition spatial_query_math.hpp:130
glm::quat getComputedWorldOrientation() const
The final orientation of the object bounds in the world.
Definition spatial_query_math.cpp:346
TrueVolume mTrueVolume
The data defining the volume itself, independent of its position.
Definition spatial_query_math.hpp:207
static std::string getComponentTypeName()
Fetches the component type string associated with this class.
Definition spatial_query_math.hpp:136
glm::vec3 getComputedWorldPosition() const
The final position of the origin of the object bounds in the world.
Definition spatial_query_math.cpp:343
std::array< glm::vec3, 8 > getLocalOrientedBoxCorners() const
Gets the corners of the box just encapsulating this object's true volume and sharing its position and...
Definition spatial_query_math.cpp:350
std::array< glm::vec3, 8 > getWorldOrientedBoxCorners() const
Gets the corners of the box just encapsulating this object's true volume relative to the origin of th...
Definition spatial_query_math.cpp:358
TrueVolumeType mType
Value indicating the type of the volume represented by this object.
Definition spatial_query_math.hpp:201
void applyModelMatrix(const glm::mat4 &modelMatrix)
Computes new mPosition and mOrientation offsets based on (presumably) the model transform of the unde...
Definition spatial_query_math.cpp:249
glm::quat mOrientation
The orientation in the real world of the scene node this bounds component is attached to.
Definition spatial_query_math.hpp:225
glm::vec3 mPosition
The position, in the real world, of the scene node this data is attached to.
Definition spatial_query_math.hpp:213
static ObjectBounds create(const VolumeBox &box, const glm::vec3 &positionOffset, const glm::vec3 &orientationOffset)
Creates bounds for an object in the shape of a box.
Definition spatial_query_math.cpp:222
std::array< AreaTriangle, 12 > getWorldOrientedBoxFaceTriangles() const
Gets an array of triangles that make up the faces of the bounds-aligned box corners in world space.
Definition spatial_query_math.hpp:302
glm::vec3 mPositionOffset
The position of the origin of the spatial query volume relative to the origin of the node it is attac...
Definition spatial_query_math.hpp:219
glm::mat3 getWorldRotationTransform() const
Gets the rotation matrix associated with the underlying scene object's orientation,...
Definition spatial_query_math.hpp:255
glm::mat3 getLocalRotationTransform() const
Gets the rotation matrix associated with this object's orientation offset.
Definition spatial_query_math.hpp:246
glm::quat mOrientationOffset
The transformation mapping forward as known by the underlying scene node, to forward as known by the ...
Definition spatial_query_math.hpp:232
std::array< glm::vec3, 8 > getVolumeRelativeBoxCorners() const
Gets the corners of the box just encapsulating this object's true volume, relative to the origin of t...
Definition spatial_query_math.cpp:329
TrueVolumeType
The types of volumes supported by the engine.
Definition spatial_query_math.hpp:142
A set of numbers describing a plane situated somewhere in the world.
Definition spatial_query_basic_types.hpp:417
A set of numbers describing a ray with its source at some finite point in the world,...
Definition spatial_query_basic_types.hpp:374
Holds the parameters describing the spatial query volume of a simple three-dimensionsal box.
Definition spatial_query_basic_types.hpp:189
Holds the parameters describing the spatial query volume of a simple three-dimensionsal capsule (or p...
Definition spatial_query_basic_types.hpp:221
Holds parameters describing a spherical spatial query volume.
Definition spatial_query_basic_types.hpp:265
A union of supported volume structs.
Definition spatial_query_math.hpp:152