System info & network
This commit is contained in:
319
code/lib/geometry.h
Normal file
319
code/lib/geometry.h
Normal file
@@ -0,0 +1,319 @@
|
||||
#ifndef _PIUMA_LIB_GEOMETRY_H_
|
||||
#define _PIUMA_LIB_GEOMETRY_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "math.h"
|
||||
|
||||
// Rect
|
||||
union Rect
|
||||
{
|
||||
struct
|
||||
{
|
||||
f32 x, y;
|
||||
f32 w, h;
|
||||
};
|
||||
struct
|
||||
{
|
||||
v2 position; // Usually, the top-left corner of the rectangle
|
||||
v2 size;
|
||||
};
|
||||
};
|
||||
|
||||
inline bool is_inside(Rect rect, v2 p)
|
||||
{
|
||||
bool in_range_x = rect.x <= p.x && p.x <= (rect.x + rect.w);
|
||||
bool in_range_y = rect.y <= p.y && p.y <= (rect.y + rect.h);
|
||||
return in_range_x && in_range_y;
|
||||
}
|
||||
|
||||
// @Feature: add Cube/Parallelepiped? Unlike Box, it has rotations
|
||||
// Box
|
||||
struct Box
|
||||
{
|
||||
v3 min;
|
||||
v3 max;
|
||||
};
|
||||
|
||||
inline bool is_inside(Box b, v3 p)
|
||||
{
|
||||
return
|
||||
(p.x < b.min.x || p.x > b.max.x) ||
|
||||
(p.y < b.min.y || p.y > b.max.y) ||
|
||||
(p.z < b.min.z || p.z > b.max.z);
|
||||
}
|
||||
|
||||
inline bool overlaps(Box a, Box b)
|
||||
{
|
||||
if(a.min.x > b.max.x) // no overlap
|
||||
return false;
|
||||
if(a.max.x < b.min.x) // no overlap
|
||||
return false;
|
||||
if(a.min.y > b.max.y) // no overlap
|
||||
return false;
|
||||
if(a.max.y < b.min.y) // no overlap
|
||||
return false;
|
||||
if(a.min.z > b.max.z) // no overlap
|
||||
return false;
|
||||
if(a.max.z < b.min.z) // no overlap
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline Box box_from_point_cloud(v3 *points, u32 count)
|
||||
{
|
||||
if(count == 0)
|
||||
return Box{.min = {0,0,0}, .max = {0,0,0}};
|
||||
|
||||
Box box;
|
||||
box.min = points[0];
|
||||
box.max = points[0];
|
||||
for(u32 i = 0; i < count; i++)
|
||||
{
|
||||
v3 p = points[i];
|
||||
box.min.x = minimum(box.min.x, p.x);
|
||||
box.min.y = minimum(box.min.y, p.y);
|
||||
box.min.z = minimum(box.min.z, p.z);
|
||||
box.max.x = maximum(box.max.x, p.x);
|
||||
box.max.y = maximum(box.max.y, p.y);
|
||||
box.max.z = maximum(box.max.z, p.z);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
inline v3 box_closest_point(Box b, v3 point);
|
||||
inline f32 box_SDF(Box b, v3 point, v3* res_closest = NULL)
|
||||
{
|
||||
v3 closest = box_closest_point(b, point);
|
||||
f32 sign = -1 * is_inside(b, point);
|
||||
|
||||
if(res_closest)
|
||||
*res_closest = closest;
|
||||
return sign * distance(closest, point);
|
||||
}
|
||||
|
||||
|
||||
// Ray
|
||||
struct Ray
|
||||
{
|
||||
v3 position;
|
||||
v3 direction;
|
||||
};
|
||||
|
||||
|
||||
// Circle
|
||||
// @Cleanup: Should Circle be merged with Sphere?
|
||||
struct Circle
|
||||
{
|
||||
v2 center;
|
||||
f32 radius;
|
||||
};
|
||||
|
||||
inline bool is_inside(Circle c, v2 p)
|
||||
{
|
||||
v2 v = p - c.center;
|
||||
return dot(v, v) <= square(c.radius);
|
||||
}
|
||||
|
||||
// Sphere
|
||||
struct Sphere
|
||||
{
|
||||
v3 center;
|
||||
f32 radius;
|
||||
};
|
||||
|
||||
inline bool is_inside(Sphere s, v3 p)
|
||||
{
|
||||
v3 v = p - s.center;
|
||||
return dot(v, v) <= square(s.radius); // distance² <= radius²
|
||||
}
|
||||
|
||||
inline f32 sphere_SDF(Sphere s, v3 point)
|
||||
{
|
||||
return distance(s.center, point) - s.radius;
|
||||
}
|
||||
|
||||
|
||||
// Segment
|
||||
struct Segment
|
||||
{
|
||||
v3 a;
|
||||
v3 b;
|
||||
};
|
||||
|
||||
|
||||
// Plane
|
||||
struct Plane
|
||||
{
|
||||
v3 normal;
|
||||
f32 offset;
|
||||
};
|
||||
|
||||
inline f32 plane_SDF(Plane plane, v3 point)
|
||||
{
|
||||
f32 projected = dot(point, plane.normal);
|
||||
return plane.offset - projected;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Projections
|
||||
inline f32 project_point_on_vector(v3 vector, v3 point)
|
||||
{
|
||||
return dot(vector, point);
|
||||
}
|
||||
|
||||
inline v3 project_point_on_plane(Plane plane, v3 point)
|
||||
{
|
||||
f32 distance = plane_SDF(plane, point);
|
||||
return point - plane.normal * distance;
|
||||
}
|
||||
|
||||
|
||||
// Closest point
|
||||
inline v3 segment_closest_point(Segment seg, v3 point)
|
||||
{
|
||||
v3 ab = seg.b - seg.a;
|
||||
v3 ap = point - seg.a;
|
||||
f32 u = dot(ab, ap);
|
||||
return seg.a + ab * clamp(0.0, 1.0, u);
|
||||
}
|
||||
|
||||
inline v3 box_closest_point(Box b, v3 point)
|
||||
{
|
||||
v3 closest;
|
||||
// Closest point on the box is the one with coords closer to the ones of the point,
|
||||
// so for each axis we can clamp to the nearest point of the border.
|
||||
|
||||
f32 dx1 = abs(b.min.x - point.x);
|
||||
f32 dx2 = abs(b.max.x - point.x);
|
||||
closest.x = (dx1 < dx2) ? b.min.x : b.max.x;
|
||||
f32 dy1 = abs(b.min.y - point.y);
|
||||
f32 dy2 = abs(b.max.y - point.y);
|
||||
closest.y = (dy1 < dy2) ? b.min.y : b.max.y;
|
||||
f32 dz1 = abs(b.min.z - point.z);
|
||||
f32 dz2 = abs(b.max.z - point.z);
|
||||
closest.z = (dz1 < dz2) ? b.min.z : b.max.z;
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Triangles functions
|
||||
inline v3 triangle_normal(v3 a, v3 b, v3 c)
|
||||
{
|
||||
v3 ba = b - a;
|
||||
v3 ca = c - a;
|
||||
v3 orthogonal = cross(ba, ca);
|
||||
return normalize(orthogonal);
|
||||
}
|
||||
|
||||
|
||||
// Transformations (all angles in radians)
|
||||
inline m4 rotation_x(f32 angle)
|
||||
{
|
||||
f32 c = cos(angle);
|
||||
f32 s = sin(angle);
|
||||
|
||||
m4 result = m4_identity;
|
||||
result.E[1][1] = c;
|
||||
result.E[1][2] = -s;
|
||||
result.E[2][1] = s;
|
||||
result.E[2][2] = c;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline m4 rotation_y(f32 angle)
|
||||
{
|
||||
f32 c = cos(angle);
|
||||
f32 s = sin(angle);
|
||||
|
||||
m4 result = m4_identity;
|
||||
result.E[0][0] = c;
|
||||
result.E[0][2] = s;
|
||||
result.E[2][0] = -s;
|
||||
result.E[2][2] = c;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline m4 rotation_z(f32 angle)
|
||||
{
|
||||
f32 c = cos(angle);
|
||||
f32 s = sin(angle);
|
||||
|
||||
m4 result = m4_identity;
|
||||
result.E[0][0] = c;
|
||||
result.E[0][1] = -s;
|
||||
result.E[1][0] = s;
|
||||
result.E[1][1] = c;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline m4 rotation(f32 x, f32 y, f32 z)
|
||||
{
|
||||
return rotation_z(z) * rotation_y(y) * rotation_x(x);
|
||||
}
|
||||
|
||||
inline m4 rotation_v3(v3 angle)
|
||||
{
|
||||
return rotation(angle.x, angle.y, angle.z);
|
||||
}
|
||||
|
||||
|
||||
inline m4 translation(f32 x, f32 y, f32 z)
|
||||
{
|
||||
m4 result = m4_identity;
|
||||
|
||||
result.E[0][3] = x;
|
||||
result.E[1][3] = y;
|
||||
result.E[2][3] = z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline m4 translation_v3(v3 t)
|
||||
{
|
||||
return translation(t.x, t.y, t.z);
|
||||
}
|
||||
|
||||
inline m4 scale(f32 x, f32 y, f32 z)
|
||||
{
|
||||
m4 result = m4_zero;
|
||||
|
||||
result.E[0][0] = x;
|
||||
result.E[1][1] = y;
|
||||
result.E[2][2] = z;
|
||||
result.E[3][3] = 1.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline m4 scale_v3(v3 factor)
|
||||
{
|
||||
return scale(factor.x, factor.y, factor.z);
|
||||
}
|
||||
|
||||
inline m4 scale(f32 factor)
|
||||
{
|
||||
return scale(factor, factor, factor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Primitives
|
||||
// Pass array of 8 elements to fill with coordinates
|
||||
inline void build_cube_vertices(v3 *vertices)
|
||||
{
|
||||
for(int x = 0; x < 2; x++)
|
||||
for(int y = 0; y < 2; y++)
|
||||
for(int z = 0; z < 2; z++)
|
||||
vertices[x*2*2 + y*2 + z] = v3{.x = x - 0.5f, .y = y - 0.5f, .z = z - 0.5f};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user