v4k-git-backup/demos/html5/demo_collide.c

618 lines
21 KiB
C
Raw Normal View History

2023-08-10 14:30:56 +00:00
// original code by @vurtun (public domain)
// - rlyeh, public domain.
//
// @todo: fix leaks: poly_free()
#include "v4k.h"
// -- demo
int paused;
camera_t cam;
void game_loop(void *userdata) {
// key handler
// if (input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen()^1 );
// if (input_down(KEY_ESC) ) window_loop_exit(); // @todo: break -> window_close()
window_resize();
2023-08-10 14:30:56 +00:00
// animation
static float dx = 0, dy = 0;
if (input_down(KEY_SPACE)) paused ^= 1;
float delta = (0.25f / 60.f) * !paused;
dx = dx + delta * 2.0f;
dy = dy + delta * 0.8f;
// fps camera
{
vec3 move = {0};
vec2 view = {0};
// show/hide cursor
bool dragging = input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
if( ui_active() || ui_hover() || gizmo_active() || input_touch_active() ) dragging = false;
window_cursor( !dragging );
// keyboard/mouse
if( dragging ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
vec3 wasdec = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), cam.speed);
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * dragging);
move = add3(move, wasdec);
view = add2(view, mouse);
// gamepad
vec2 filtered_lpad = input_filter_deadzone(input2(GAMEPAD_LPAD), 0.15f /*15% deadzone*/);
vec2 filtered_rpad = input_filter_deadzone(input2(GAMEPAD_RPAD), 0.15f /*15% deadzone*/);
vec3 gamepad_move = scale3(vec3(filtered_lpad.x, input(GAMEPAD_LT) - input(GAMEPAD_RT), filtered_lpad.y), 1.0f);
vec2 gamepad_view = scale2(filtered_rpad, 1.0f);
move = add3(move, gamepad_move);
view = add2(view, gamepad_view);
// multi-touch
vec2 touch_move = input_touch_delta_from_origin(0, 0.0125f /*sensitivityFwd*/); // button #0 (left border)
vec2 touch_view = input_touch_delta(1, 0.125f /*sensitivityRot*/); // button #1 (right border)
move = add3(move, vec3(touch_move.x, 0, -touch_move.y));
view = add2(view, vec2(touch_view.x, -touch_view.y));
// apply inputs
camera_move(&cam, move.x,move.y,move.z);
camera_fps(&cam, view.x,view.y);
}
// projview matrix
mat44 projview; multiply44x2(projview, cam.proj, cam.view);
// rendering
viewport_color3(vec3(0.15,0.15,0.15));
#if 0
viewport_clear(true, true);
viewport_clip(vec2(0,0), vec2(window_width(), window_height()));
#endif
// debug draw collisions
{
// 3D
glEnable(GL_DEPTH_TEST);
// grid
ddraw_grid(0);
{
// Triangle-Ray Intersection*/
vec3 ro, rd;
int suc;
triangle tri = { vec3(-9,1,28), vec3(-10,0,28), vec3(-11,1,28) };
// ray
ro = vec3(-10,-1,20);
rd = vec3(-10+0.4f*sinf(dx), 2.0f*cosf(dy), 29.81023f);
rd = sub3(rd, ro);
rd = norm3(rd);
ray r = ray(ro, rd);
hit *hit = ray_hit_triangle(r, tri);
if (hit) {
// point of intersection
ddraw_color(RED);
ddraw_box(hit->p, vec3(0.10f, 0.10f, 0.10f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
}
// line
ddraw_color(RED);
rd = scale3(rd,10);
rd = add3(ro,rd);
ddraw_line(ro, rd);
// triangle
if (hit) ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_triangle(tri.p0,tri.p1,tri.p2);
}
{
// Plane-Ray Intersection*/
vec3 ro, rd;
mat33 rot;
// ray
static float d = 0;
d += delta * 2.0f;
ro = vec3(0,-1,20);
rd = vec3(0.1f, 0.5f, 9.81023f);
rd = sub3(rd, ro);
rd = norm3(rd);
// rotation
rotation33(rot, deg(d), 0,1,0);
rd = mulv33(rot, rd);
// intersection
ray r = ray(ro, rd);
plane pl = plane(vec3(0,0,28), vec3(0,0,1));
hit *hit = ray_hit_plane(r, pl);
if (hit) {
// point of intersection
ddraw_color(RED);
ddraw_box(hit->p, vec3(0.10f, 0.10f, 0.10f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
ddraw_color(RED);
}
// line
ddraw_color(RED);
rd = scale3(rd,9);
rd = add3(ro,rd);
ddraw_line(ro, rd);
// plane
if (hit) ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_plane(vec3(0,0,28), vec3(0,0,1), 3.0f);
}
{
// Sphere-Ray Intersection*/
vec3 ro, rd;
sphere s;
// ray
ro = vec3(0,-1,0);
rd = vec3(0.4f*sinf(dx), 2.0f*cosf(dy), 9.81023f);
rd = sub3(rd, ro);
rd = norm3(rd);
ray r = ray(ro, rd);
s = sphere(vec3(0,0,8), 1);
hit *hit = ray_hit_sphere(r, s);
if(hit) {
// points of intersection
vec3 in = add3(ro,scale3(rd,hit->t0));
ddraw_color(GREEN);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
in = add3(ro,scale3(rd,hit->t1));
ddraw_color(YELLOW);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
ddraw_color(RED);
}
// line
ddraw_color(RED);
rd = scale3(rd,10);
rd = add3(ro,rd);
ddraw_line(ro, rd);
// sphere
if (hit) ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_sphere(vec3(0,0,8), 1);
}
{ // ray-aabb
aabb bounds = aabb(vec3(10-0.5f,-0.5f,7.5f), vec3(10.5f,0.5f,8.5f));
vec3 ro = vec3(10,-1,0);
vec3 rd = vec3(10+0.4f*sinf(dx), 2.0f*cosf(dy), 9.81023f);
rd = norm3(sub3(rd, ro));
ray r = ray(ro, rd);
hit *hit = ray_hit_aabb(r, bounds);
if(hit) {
// points of intersection
vec3 in;
in = scale3(rd,hit->t0);
in = add3(ro,in);
ddraw_color(RED);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
in = scale3(rd,hit->t1);
in = add3(ro,in);
ddraw_color(RED);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(10,0,8), vec3(1,1,1));
// line
ddraw_color(RED);
rd = scale3(rd,10);
rd = add3(ro,rd);
ddraw_line(ro, rd);
}
{
// Sphere-Sphere intersection*/
sphere a = sphere(vec3(-10,0,8), 1);
sphere b = sphere(vec3(-10+0.6f*sinf(dx), 3.0f*cosf(dy),8), 1);
hit *m = sphere_hit_sphere(a, b);
if (m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_sphere(a.c, 1);
ddraw_sphere(b.c, 1);
}
{
// AABB-AABB intersection*/
const float x = 10+0.6f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = 20.0f;
aabb a = aabb(vec3(10-0.5f,-0.5f,20-0.5f), vec3(10+0.5f,0.5f,20.5f));
aabb b = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
hit *m = aabb_hit_aabb(a, b);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(10,0,20), vec3(1,1,1));
ddraw_box(vec3(x,y,z), vec3(1,1,1));
}
{
// Capsule-Capsule intersection*/
const float x = 20+0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = 28.5f;
capsule a = capsule(vec3(20.0f,-1.0f,28.0f), vec3(20.0f,1.0f,28.0f), 0.2f);
capsule b = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
hit *m = capsule_hit_capsule(a, b);
if( m ) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
ddraw_capsule(vec3(20.0f,-1.0f,28.0f), vec3(20.0f,1.0f,28.0f), 0.2f);
}
{
// AABB-Sphere intersection*/
aabb a = aabb(vec3(20-0.5f,-0.5f,7.5f), vec3(20.5f,0.5f,8.5f));
sphere s = sphere(vec3(20+0.6f*sinf(dx), 3.0f*cosf(dy),8), 1);
hit *m = aabb_hit_sphere(a, s);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(20,0,8), vec3(1,1,1));
ddraw_sphere(s.c, 1);
}
{
// Sphere-AABB intersection*/
const float x = 10+0.6f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -8.0f;
sphere s = sphere(vec3(10,0,-8), 1);
aabb a = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
hit *m = sphere_hit_aabb(s, a);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(x,y,z), vec3(1,1,1));
ddraw_sphere(s.c, 1);
}
{
// Capsule-Sphere intersection*/
capsule c = capsule(vec3(-20.5f,-1.0f,7.5f), vec3(-20+0.5f,1.0f,8.5f), 0.2f);
sphere b = sphere(vec3(-20+0.6f*sinf(dx), 3.0f*cosf(dy),8), 1);
hit *m = capsule_hit_sphere(c, b);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_sphere(b.c, 1);
ddraw_capsule(vec3(-20.5f,-1.0f,7.5f), vec3(-20+0.5f,1.0f,8.5f), 0.2f);
}
{
// Sphere-Capsule intersection*/
const float x = 20+0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -8;
sphere s = sphere(vec3(20,0,-8), 1);
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
hit *m = sphere_hit_capsule(s, c);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
ddraw_sphere(s.c, 1);
}
{
// Capsule-AABB intersection*/
const float x = -20+0.6f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = 28.0f;
capsule c = capsule(vec3(-20.5f,-1.0f,27.5f), vec3(-20+0.5f,1.0f,28.5f), 0.2f);
aabb b = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
hit *m = capsule_hit_aabb(c, b);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(x,y,z), vec3(1,1,1));
ddraw_capsule(vec3(-20.5f,-1.0f,27.5f), vec3(-20+0.5f,1.0f,28.5f), 0.2f);
}
{
// AABB-Capsule intersection*/
const float x = 0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -8;
aabb a = aabb(vec3(-0.5f,-0.5f,-8.5f), vec3(0.5f,0.5f,-7.5f));
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
hit *m = aabb_hit_capsule(a, c);
if(m) {
ddraw_color(RED);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
ddraw_arrow(m->contact_point, add3(m->contact_point, m->normal));
} else ddraw_color(WHITE);
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
ddraw_box(vec3(0,0,-8.0f), vec3(1,1,1));
}
{
// poly(Pyramid)-Sphere (GJK) intersection*/
sphere s = sphere(vec3(-10+0.6f*sinf(dx), 3.0f*cosf(dy),-8), 1);
poly pyr = pyramid(vec3(-10.5f,-0.5f,-7.5f), vec3(-10.5f,1.0f,-7.5f), 1.0f);
gjk_result gjk;
if (poly_hit_sphere(&gjk, pyr, s))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_sphere(s.c, 1);
ddraw_pyramid(vec3(-10.5f,-0.5f,-7.5f), 0.5f/*vec3(-10.5f,1.0f,-7.5f)*/, 1.0f);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-Sphere (GJK) intersection*/
sphere s = sphere(vec3(-20+0.6f*sinf(dx), 3.0f*cosf(dy),-8), 1);
poly dmd = diamond(vec3(-20.5f,-0.5f,-7.5f), vec3(-20.5f,1.0f,-7.5f), 0.5f);
gjk_result gjk;
if (poly_hit_sphere(&gjk, dmd, s))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_sphere(s.c, 1);
ddraw_diamond(vec3(-20.5f,-0.5f,-7.5f), vec3(-20.5f,1.0f,-7.5f), 0.5f);
poly_free(&dmd);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Pyramid)-Capsule (GJK) intersection*/
const float x = 0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -15;
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z), 0.2f);
poly pyr = pyramid(vec3(-0.5f,-0.5f,-15.5f), vec3(-0.5f,1.0f,-15.5f), 1.0f);
gjk_result gjk;
if (poly_hit_capsule(&gjk, pyr, c))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_capsule(c.a, c.b, c.r);
ddraw_pyramid(vec3(-0.5f,-0.5f,-15.5f), 0.5f/*vec3(-0.5f,1.0f,-15.5f)*/, 1.0f);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-Capsule (GJK) intersection*/
const float x = -10 + 0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -15;
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z), 0.2f);
poly dmd = diamond(vec3(-10.5f,-0.5f,-15.5f), vec3(-10.5f,1.0f,-15.5f), 0.5f);
gjk_result gjk;
if (poly_hit_capsule(&gjk, dmd, c))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_capsule(c.a, c.b, c.r);
ddraw_diamond(vec3(-10.5f,-0.5f,-15.5f), vec3(-10.5f,1.0f,-15.5f), 0.5f);
poly_free(&dmd);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-poly(Pyramid) (GJK) intersection*/
const float x = -20 + 0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -15;
poly pyr = pyramid(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.8f);
poly dmd = diamond(vec3(-20.5f,-0.5f,-15.5f), vec3(-20.5f,1.0f,-15.5f), 0.5f);
gjk_result gjk;
if (poly_hit_poly(&gjk, dmd, pyr))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_pyramid(vec3(x,y-0.5f,z), 1/*vec3(x,y+1,z)*/, 1/*0.8f*/);
ddraw_diamond(vec3(-20.5f,-0.5f,-15.5f), vec3(-20.5f,1.0f,-15.5f), 0.5f);
poly_free(&dmd);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Pyramid)-poly(Diamond) (GJK) intersection*/
const float x = 10 + 0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -15;
poly dmd = diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
poly pyr = pyramid(vec3(10.5f,-0.5f,-15.5f), vec3(10.5f,1.0f,-15.5f), 1.0f);
gjk_result gjk;
if (poly_hit_poly(&gjk, dmd, pyr))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
ddraw_pyramid(vec3(10.5f,-0.5f,-15.5f), 0.5f/*vec3(10.5f,1.0f,-15.5f)*/, 1.0f);
poly_free(&dmd);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-AABB (GJK) intersection*/
const float x = 20 + 0.4f*sinf(dx);
const float y = 3.0f*cosf(dy);
const float z = -15;
poly dmd = diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
aabb a = aabb(vec3(19.5f,-0.5f,-14.5f), vec3(20.5f,0.5f,-15.5f));
gjk_result gjk;
if (poly_hit_aabb(&gjk, dmd, a))
ddraw_color(RED);
else ddraw_color(WHITE);
poly_free(&dmd);
ddraw_diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
ddraw_box(vec3(20,0,-15), vec3(1,1,1));
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
}
//fx_begin();
//ddraw_flush();
//fx_end();
if( ui_panel("Audio", 0) ) {
if( ui_button("test audio") ) {
// audio (both clips & streams)
static audio_t voice; voice = audio_clip("coin.wav"); // "pew.sfxr"
static audio_t stream; stream = audio_stream("wrath_of_the_djinn.xm"); // "larry.mid"
audio_play(voice, 0);
audio_play(stream, 0);
}
ui_panel_end();
}
if( ui_panel("FX", 0) ) {
for( int i = 0; i < 64; ++i ) {
char *name = fx_name(i); if( !name ) break;
bool b = fx_enabled(i);
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
}
ui_panel_end();
}
}
int main(void) {
// 75% sized, msaa x4 enabled
window_create(0.75f, WINDOW_MSAA4);
window_title( "V4K - SPACE pauses simulation" );
// for(const char **list = file_list("fx**.fs"); *list; list++) {
// //fx_load(*list);
// }
// camera that points to origin
cam = camera();
// main loop
window_loop(game_loop, NULL);
}