[RELEASE] u22-v03
This version is submitted to U22 breau.
This commit is contained in:
7
util/coly2d/CMakeLists.txt
Normal file
7
util/coly2d/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
add_library(coly2d
|
||||
hittest.c
|
||||
shape.c
|
||||
)
|
||||
target_link_libraries(coly2d
|
||||
math
|
||||
)
|
4
util/coly2d/README.md
Normal file
4
util/coly2d/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
coly
|
||||
====
|
||||
|
||||
simplest 2D collision calculation library for C
|
171
util/coly2d/hittest.c
Normal file
171
util/coly2d/hittest.c
Normal 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
53
util/coly2d/hittest.h
Normal 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
54
util/coly2d/shape.c
Normal 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
51
util/coly2d/shape.h
Normal 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
|
||||
);
|
Reference in New Issue
Block a user