[RELEASE] u22-v03

This version is submitted to U22 breau.
This commit is contained in:
2020-09-14 00:00:00 +00:00
parent 360595de37
commit 84c3a02b9a
357 changed files with 29223 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
add_library(coly2d
hittest.c
shape.c
)
target_link_libraries(coly2d
math
)

4
util/coly2d/README.md Normal file
View File

@@ -0,0 +1,4 @@
coly
====
simplest 2D collision calculation library for C

171
util/coly2d/hittest.c Normal file
View File

@@ -0,0 +1,171 @@
#include "./hittest.h"
#include <assert.h>
#include <stdbool.h>
#include "util/math/algorithm.h"
#include "util/math/vector.h"
bool coly2d_hittest_point_and_rect(
const vec2_t* pos1, const vec2_t* pos2, const vec2_t* size2) {
assert(vec2_valid(pos1));
assert(vec2_valid(pos2));
assert(vec2_valid(size2));
vec2_t rpos;
vec2_sub(&rpos, pos2, pos1);
return
MATH_ABS(rpos.x) < size2->x &&
MATH_ABS(rpos.y) < size2->y;
}
bool coly2d_hittest_point_and_triangle(
const vec2_t* pos1,
const vec2_t* pos2_a,
const vec2_t* pos2_b,
const vec2_t* pos2_c) {
assert(vec2_valid(pos1));
assert(vec2_valid(pos2_a));
assert(vec2_valid(pos2_b));
assert(vec2_valid(pos2_c));
vec2_t v1, v2;
vec2_sub(&v1, pos1, pos2_a);
vec2_sub(&v2, pos2_b, pos2_a);
float a = vec2_cross(&v1, &v2);
vec2_sub(&v1, pos1, pos2_b);
vec2_sub(&v2, pos2_c, pos2_b);
if (a * vec2_cross(&v1, &v2) <= 0) return false;
vec2_sub(&v1, pos1, pos2_c);
vec2_sub(&v2, pos2_a, pos2_c);
return a*vec2_cross(&v1, &v2) > 0;
}
bool coly2d_hittest_lineseg_and_lineseg(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2_st,
const vec2_t* pos2_ed) {
assert(vec2_valid(pos1_st));
assert(vec2_valid(pos1_ed));
assert(vec2_valid(pos2_st));
assert(vec2_valid(pos2_ed));
vec2_t x;
vec2_sub(&x, pos1_ed, pos1_st);
vec2_t a;
vec2_sub(&a, pos2_st, pos1_st);
vec2_t b;
vec2_sub(&b, pos2_ed, pos1_st);
vec2_t y;
vec2_sub(&y, pos2_ed, pos2_st);
vec2_t c;
vec2_sub(&c, pos1_st, pos2_st);
vec2_t d;
vec2_sub(&d, pos1_ed, pos2_st);
return
vec2_cross(&x, &a) * vec2_cross(&x, &b) < 0 &&
vec2_cross(&y, &c) * vec2_cross(&y, &d) < 0;
}
bool coly2d_hittest_lineseg_and_rect(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2,
const vec2_t* size2) {
assert(vec2_valid(pos1_st));
assert(vec2_valid(pos1_ed));
assert(vec2_valid(pos2));
assert(vec2_valid(size2));
if (coly2d_hittest_point_and_rect(pos1_st, pos2, size2) ||
coly2d_hittest_point_and_rect(pos1_ed, pos2, size2)) {
return true;
}
const float left = pos2->x - size2->x;
const float right = pos2->x + size2->x;
const float top = pos2->y + size2->y;
const float bottom = pos2->y - size2->y;
const vec2_t v1 = vec2(left, top);
const vec2_t v2 = vec2(left, bottom);
const vec2_t v3 = vec2(right, bottom);
const vec2_t v4 = vec2(right, top);
return
coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, &v1, &v2) ||
coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, &v2, &v3) ||
coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, &v3, &v4) ||
coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, &v4, &v1);
}
bool coly2d_hittest_lineseg_and_ellipse(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2,
const vec2_t* size2) {
assert(vec2_valid(pos1_st));
assert(vec2_valid(pos1_ed));
assert(vec2_valid(pos2));
assert(vec2_valid(size2));
vec2_t p2 = *pos2;
p2.x /= size2->x;
p2.y /= size2->y;
vec2_t p1st = *pos1_st;
p1st.x /= size2->x;
p1st.y /= size2->y;
vec2_t c1;
vec2_sub(&c1, &p2, &p1st);
if (vec2_pow_length(&c1) < 1) return true;
vec2_t p1ed = *pos1_ed;
p1ed.x /= size2->x;
p1ed.y /= size2->y;
vec2_t c2;
vec2_sub(&c2, &p2, &p1ed);
if (vec2_pow_length(&c2) < 1) return true;
vec2_t ed;
vec2_sub(&ed, &p1ed, &p1st);
const float cross = vec2_cross(&ed, &c1);
if (MATH_ABS(cross) >= vec2_length(&ed)) return false;
vec2_t st;
vec2_sub(&st, &p1st, &p1ed);
return vec2_dot(&c1, &ed)*vec2_dot(&c2, &st) >= 0;
}
bool coly2d_hittest_lineseg_and_triangle(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2_a,
const vec2_t* pos2_b,
const vec2_t* pos2_c) {
assert(vec2_valid(pos1_st));
assert(vec2_valid(pos1_ed));
assert(vec2_valid(pos2_a));
assert(vec2_valid(pos2_b));
assert(vec2_valid(pos2_c));
/* TODO(catfoot): Tomas Moller's algorithm may make this function faster. */
if (coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, pos2_a, pos2_b) ||
coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, pos2_b, pos2_c) ||
coly2d_hittest_lineseg_and_lineseg(pos1_st, pos1_ed, pos2_c, pos2_a)) {
return true;
}
return
coly2d_hittest_point_and_triangle(pos1_st, pos2_a, pos2_b, pos2_c) ||
coly2d_hittest_point_and_triangle(pos1_ed, pos2_a, pos2_b, pos2_c);
}

53
util/coly2d/hittest.h Normal file
View File

@@ -0,0 +1,53 @@
#pragma once
#include <stdbool.h>
#include "util/math/vector.h"
bool
coly2d_hittest_point_and_rect(
const vec2_t* pos1,
const vec2_t* pos2,
const vec2_t* size2
);
bool
coly2d_hittest_point_and_triangle(
const vec2_t* pos1,
const vec2_t* pos2_a,
const vec2_t* pos2_b,
const vec2_t* pos2_c
);
bool
coly2d_hittest_lineseg_and_lineseg(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2_st,
const vec2_t* pos2_ed
);
bool
coly2d_hittest_lineseg_and_rect(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2,
const vec2_t* size2
);
bool
coly2d_hittest_lineseg_and_ellipse(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2,
const vec2_t* size2
);
bool
coly2d_hittest_lineseg_and_triangle(
const vec2_t* pos1_st,
const vec2_t* pos1_ed,
const vec2_t* pos2_a,
const vec2_t* pos2_b,
const vec2_t* pos2_c
);

54
util/coly2d/shape.c Normal file
View File

@@ -0,0 +1,54 @@
#include "./shape.h"
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include "util/math/algorithm.h"
#include "util/math/vector.h"
#include "./hittest.h"
bool coly2d_shape_valid(const coly2d_shape_t* shape) {
return
shape != NULL &&
vec2_valid(&shape->size) &&
MATH_FLOAT_VALID(shape->angle);
}
bool coly2d_shape_hittest_lineseg(
const coly2d_shape_t* shape, const vec2_t* st, const vec2_t* ed) {
assert(coly2d_shape_valid(shape));
assert(vec2_valid(st));
assert(vec2_valid(ed));
static const vec2_t origin = vec2(0, 0);
const float s = -sin(shape->angle);
const float c = cos(shape->angle);
const vec2_t st_ = vec2(st->x*c-st->y*s, st->x*s+st->y*c);
const vec2_t ed_ = vec2(ed->x*c-ed->y*s, ed->x*s+ed->y*c);
switch (shape->type) {
case COLY2D_SHAPE_TYPE_LINE:
return coly2d_hittest_lineseg_and_lineseg(
&st_, &ed_, &origin, &shape->size);
case COLY2D_SHAPE_TYPE_RECT:
return coly2d_hittest_lineseg_and_rect(
&st_, &ed_, &origin, &shape->size);
case COLY2D_SHAPE_TYPE_TRIANGLE:
return coly2d_hittest_lineseg_and_triangle(
&st_, &ed_,
&vec2( shape->size.x, 0),
&vec2(-shape->size.x, shape->size.y),
&vec2(-shape->size.x, -shape->size.y));
case COLY2D_SHAPE_TYPE_ELLIPSE:
return coly2d_hittest_lineseg_and_ellipse(
&st_, &ed_, &origin, &shape->size);
}
assert(false);
return false;
}

51
util/coly2d/shape.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <stdbool.h>
#include "util/math/vector.h"
typedef enum {
COLY2D_SHAPE_TYPE_LINE,
COLY2D_SHAPE_TYPE_RECT,
COLY2D_SHAPE_TYPE_TRIANGLE,
COLY2D_SHAPE_TYPE_ELLIPSE,
} coly2d_shape_type_t;
typedef struct {
coly2d_shape_type_t type;
vec2_t size;
float angle;
} coly2d_shape_t;
#define coly2d_shape_line(ed, a) ((coly2d_shape_t) { \
.type = COLY2D_SHAPE_TYPE_LINE, \
.size = ed, \
.angle = a, \
})
#define coly2d_shape_rect(sz, a) ((coly2d_shape_t) { \
.type = COLY2D_SHAPE_TYPE_RECT, \
.size = sz, \
.angle = a, \
})
#define coly2d_shape_triangle(sz, a) ((coly2d_shape_t) { \
.type = COLY2D_SHAPE_TYPE_TRIANGLE, \
.size = sz, \
.angle = a, \
})
#define coly2d_shape_ellipse(sz, a) ((coly2d_shape_t) { \
.type = COLY2D_SHAPE_TYPE_ELLIPSE, \
.size = sz, \
.angle = a, \
})
bool
coly2d_shape_valid(
const coly2d_shape_t* shape
);
bool
coly2d_shape_hittest_lineseg(
const coly2d_shape_t* shape,
const vec2_t* st,
const vec2_t* ed
);