12struct std::less<glm::i32vec2> {
13 bool operator()(
const glm::i32vec2& lhs,
const glm::i32vec2& rhs)
const {
14 return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
19struct std::less<glm::vec<2, int32_t, glm::packed_lowp>> {
20 bool operator()(
const glm::vec<2, int32_t, glm::packed_lowp>& lhs,
const glm::vec<2, int32_t, glm::packed_lowp>& rhs)
const {
21 return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
26struct std::hash<glm::i32vec2> {
27 int32_t operator()(
const glm::i32vec2& vec)
const {
28 const int32_t p1 = 73856093;
29 const int32_t p2 = 19349663;
31 return vec.x * p1 ^ vec.y * p2;
36struct boost::hash<glm::vec<2, int32_t, glm::packed_lowp>> {
37 int32_t operator()(
const glm::vec<2, int32_t, glm::packed_lowp>& vec)
const {
38 const int32_t p1 = 73856093;
39 const int32_t p2 = 19349663;
41 return vec.x * p1 ^ vec.y * p2;
46struct boost::hash<glm::i32vec2> {
47 int32_t operator()(
const glm::i32vec2& vec)
const {
48 const int32_t p1 = 73856093;
49 const int32_t p2 = 19349663;
51 return vec.x * p1 ^ vec.y * p2;
56struct std::equal_to<glm::i32vec2> {
57 inline bool operator()(
const glm::i32vec2& _1,
const glm::i32vec2& _2)
const {
82 : sin(0.0f), cos(1.0f) {}
88 SinCos(Float psin, Float pcos)
89 : sin(psin), cos(pcos) {}
91 void setRot(Float rot) {
105 dif.sin = sin * other.cos - cos * other.sin;
106 dif.cos = cos * other.cos + sin * other.sin;
116 dif.sin = sin * other.cos + cos * other.sin;
117 dif.cos = cos * other.cos - sin * other.sin;
123 return { glm::abs(sin), glm::abs(cos) };
130inline vec2 rotate(
const vec2& v, Float sin, Float cos) {
133 result.x = v.x * cos - v.y * sin;
134 result.y = v.x * sin + v.y * cos;
138inline vec2 rotate(
const vec2& v,
const SinCos& sincos) {
139 return rotate(v, sincos.sin, sincos.cos);
144 : pos(0.0f, 0.0f), rot(0.0f) {}
147 : pos(pos), rot(rot) {}
153 vec2 getWorldPoint(
const vec2& localPoint)
const {
154 return rotate(localPoint, sincos) + pos;
157 vec2 getWorldPoint(
const vec2& localPoint,
const vec2& localOffset)
const {
158 return rotate(localPoint - localOffset, sincos) + localOffset + pos;
161 vec2 getLocalPoint(
const vec2& worldPoint,
const vec2& localOffset = { 0.0f, 0.0f })
const {
162 vec2 localPoint = worldPoint - pos - localOffset;
163 localPoint = rotate(localPoint, sincos.getNegate()) + localOffset;
178Float cross(
const vec2& a,
const vec2& b) {
180 return (a.x * b.y) - (a.y * b.x);
183inline bool overlap(Float min1, Float max1, Float min2, Float max2) {
184 return (min1 <= max2 && max1 >= min2);
187inline Float absdot(
const vec2& vec1,
const vec2& vec2) {
188 return glm::abs(glm::dot(vec1, vec2));
191inline vec2 reverse(
const vec2& vec) {
192 return { vec.y, vec.x };
198Float sideOf(
const vec2& p,
const vec2& a,
const vec2& b) {
199 return cross(a - b, p) + cross(b, a);
202template<
typename T = Float, glm::qualifier Prec = glm::packed_lowp>
206 using vec2 = glm::vec<2, T, Prec>;
209 : m_min(0, 0), m_max(0, 0) {}
211 AABB(vec2 min, vec2 max)
212 : m_min(min), m_max(max) {}
214 AABB(vec2 pos, T hW, T hH)
220 : m_min(-halfDim.x, -halfDim.y), m_max(halfDim.x, halfDim.y) {}
222 TAABB& operator+=(
const vec2& off) {
229 TAABB operator+(
const vec2& off)
const {
230 TAABB newAABB = *
this;
231 newAABB.m_min += off;
232 newAABB.m_max += off;
237 TAABB operator-(
const vec2& off)
const {
238 TAABB newAABB = *
this;
239 newAABB.m_min -= off;
240 newAABB.m_max -= off;
245 TAABB operator*(T off)
const {
246 TAABB newAABB = *
this;
247 newAABB.m_min *= off;
248 newAABB.m_max *= off;
253 vec2& min() {
return m_min; }
254 vec2& max() {
return m_max; }
255 const vec2& min()
const {
return m_min; }
256 const vec2& max()
const {
return m_max; }
258 void setMin(vec2 newMin) {
262 void setMax(vec2 newMax) {
271 return { m_max.x, m_min.y };
279 return { m_min.x, m_max.y };
282 void forEach(std::function<
void(vec2)> callback)
const {
289 vec2 midpoint()
const {
290 return (m_max + m_min) / (T)2;
294 return glm::abs(m_max.x - m_min.x);
298 return glm::abs(m_max.y - m_min.y);
301 bool intersects(
const AABB& other)
const {
303 d1 = vec2(other.m_min.x, other.m_min.y) - vec2(m_max.x, m_max.y);
304 d2 = vec2(m_min.x, m_min.y) - vec2(other.m_max.x, other.m_max.y);
306 if (d1.x > 0.0f || d1.y > 0.0f)
309 if (d2.x > 0.0f || d2.y > 0.0f)
315 AABB<T> intersectingArea(
const AABB& other)
const {
319 std::max(m_min.x, other.m_min.x),
320 std::max(m_min.y, other.m_min.y)
323 std::min(m_max.x, other.m_max.x),
324 std::min(m_max.y, other.m_max.y)
331 AABB<T> rotate(T sin, T cos)
const {
335 T hWidth = width() / (T)2;
336 T hHeight = height() / (T)2;
340 hHeight * sin + hWidth * cos,
341 hWidth * sin + hHeight * cos
346 return rotate(sincos.sin, sincos.cos);
350 return m_min.x < m_max.x && m_min.y < m_max.y;
364 c = p1.y * p2.x - p1.x * p2.y;
368 float denom = a * other.b - other.a * b;
370 intersectPoint = { 0.0f, 0.0f };
374 intersectPoint.x = (b * other.c - other.b * c) / denom;
375 intersectPoint.y = (c * other.a - other.c * a) / denom;
386T parallelAxisTheorem(T Icm, T mass, T sqDistance) {
387 return Icm + mass * sqDistance;
394 inline std::array<vec2, 4> getVertices()
const {
395 const vec2 wExt = rotate({ extent.x, extent.y }, transform.sincos);
396 const vec2 blExt = rotate({ extent.x, -extent.y }, transform.sincos);
397 const vec2 trExt = -blExt;
400 transform.pos - wExt,
401 {transform.pos.x + blExt.x, transform.pos.y + blExt.y},
402 transform.pos + wExt,
403 {transform.pos.x + trExt.x, transform.pos.y + trExt.y}
411 AABB<T> area = _1.intersectingArea(_2);
413 return AABB<T>(glm::vec<2, T>(NAN), glm::vec<2, T>(NAN));
418inline bool nearlyEqual(Float a, Float b, Float max = 0.0001f) {
419 return glm::abs(a - b) < max;
422inline bool nearlyEqual(vec2 a, vec2 b, Float max = 0.0001f) {
423 return glm::abs(a.x - b.x) < max && glm::abs(a.y - b.y) < max;
426inline Float sqaure(Float value) {
427 return value * value;
430inline Float pointSegmentDistance(vec2 p, vec2 v1, vec2 v2, vec2& cp) {
434 vec2 p_to_v1 = p - v1;
435 vec2 v1_to_v2 = v2 - v1;
436 Float proj = glm::dot(p_to_v1, v1_to_v2);
437 Float length = glm::length2(v1_to_v2);
439 Float d = proj / length;
444 else if (d >= 1.0f) {
448 cp = v1 + v1_to_v2 * d;
451 return glm::distance(p, cp);
454using MinMax = std::pair<Float, Float>;
456template<
class Container>
457MinMax projectBoxOnNormal(
const Container& vertices,
const vec2& normal) {
458 Float firstDot = glm::dot(vertices[0], normal);
459 MinMax minMax = { firstDot, firstDot };
461 for (
size_t i = 1; i < vertices.size(); i++) {
462 Float dot = glm::dot(vertices[i], normal);
464 if (dot < minMax.first) {
467 else if (dot > minMax.second) {
476template<
class Container,
class OutputContainer = std::vector<vec2>>
477OutputContainer sutherlandHodgmanClip(
const Container& subjectVertices,
const Container& clipVertices) {
478 OutputContainer outputVertices(subjectVertices.begin(), subjectVertices.end());
479 OutputContainer inputVertices;
481 vec2 prevClipVertex = clipVertices.back();
482 for (vec2 curClipVertex : clipVertices) {
485 inputVertices = outputVertices;
486 outputVertices.clear();
488 if (inputVertices.empty())
491 vec2 prevVertex = inputVertices.back();
492 for (vec2 curVertex : inputVertices) {
495 bool curVertexInside = sideOf(curVertex, prevClipVertex, curClipVertex) <= 0.0f;
496 bool prevVertexInside = sideOf(prevVertex, prevClipVertex, curClipVertex) <= 0.0f;
498 if (curVertexInside) {
499 if (!prevVertexInside) {
500 clipLine.intersects(subLine, outputVertices.emplace_back());
503 outputVertices.push_back(curVertex);
505 else if (prevVertexInside) {
506 clipLine.intersects(subLine, outputVertices.emplace_back());
510 prevVertex = curVertex;
513 prevClipVertex = curClipVertex;
516 return outputVertices;
519inline bool circleCollide(Float radi1,
const vec2& pos1, Float radi2,
const vec2& pos2) {
520 Float difOfX = (pos2.x - pos1.x);
521 Float difOfY = (pos2.y - pos1.y);
522 Float sumOfRadi = radi1 + radi2;
528inline Float convertToFloat(uint8_t num) {
529 constexpr Float inv255 = 1.0f / 255.0f;
530 return (Float)num * inv255;
533template<
typename T
int>
534Tint
constexpr getSqrtMagicNumber() {
535 static_assert(!(std::is_same_v<Tint, std::int64_t> || std::is_same_v<Tint, std::int32_t>));
540constexpr std::int32_t getSqrtMagicNumber() {
545constexpr std::int64_t getSqrtMagicNumber() {
546 return 0x5fe6eb50c7b537a9;
551inline T fastInverseSqrt(T x) {
552 static_assert(std::is_floating_point<T>::value,
"T must be floating point");
553 using Tint =
typename std::conditional<
sizeof(T) == 8, std::int64_t, std::int32_t>::type;
554 constexpr Tint magicNumber = getSqrtMagicNumber<Tint>();
559 i = magicNumber - (i >> 1);
561 y = y * (1.5 - (x2 * y * y));
562 y = y * (1.5 - (x2 * y * y));
575template<
typename Int,
typename Float>
576inline Int floor(Float x) {
A primary include file for all other files. Its purpose is to contain "#include"s that are not within...
T2D_NAMESPACE_BEGIN T constexpr square(T x)
Returns the sqaure of x.
Definition math.hpp:71
Used to simplify the use of precalculated values for sine and cosine.
Definition math.hpp:80