polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit 6bb1b1f05bcf2d7900cef18fc6ba1134769418c8
parent 985bab86476cf435f7fe92d8d8a902b5cc2b1d1b
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 28 Jul 2019 14:06:26 -0700

terrain collision working!!

Diffstat:
Msrc/terrain.h | 1-
Msrc/terrain_collision.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/terrain_collision.h | 2+-
Msrc/update.c | 16+++++++++++-----
4 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/src/terrain.h b/src/terrain.h @@ -63,7 +63,6 @@ struct terrain { double old_noisy_boi(struct terrain *, double x, double y); -void collide_terrain(struct terrain *terrain, struct node *node, struct model *model, vec3 *move); void update_terrain(struct terrain *terrain, const double pdist); void gen_terrain_samples(struct terrain *terrain, float scale, const double pdist); void init_terrain(struct terrain *terrain, float size); diff --git a/src/terrain_collision.c b/src/terrain_collision.c @@ -12,6 +12,8 @@ struct tri_query { struct vert_tri *vtri; }; +/** Get the top 3 closest terrain vertices to a specific world position `pos` + */ static void get_closest_verts(struct terrain *terrain, vec3 *pos, struct grid_query closest[3], @@ -50,6 +52,8 @@ static void get_closest_verts(struct terrain *terrain, } } + + static inline float sign (float *p1, float *p2, float *p3) { return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]); @@ -70,11 +74,9 @@ bool point_in_tri(float *pt, float *v1, float *v2, float *v3) return !(has_neg && has_pos); } -static void get_closest_tris(struct terrain *terrain, struct vert_tris *vtris) -{ -} +#ifdef DEBUG static void terrain_tri_debug(float *verts, struct tri *tri) { @@ -107,8 +109,49 @@ static void terrain_tri_debug(float *verts, struct tri *tri) } } +#endif + + +/** Test all of the triangles around a specific terrain vertex, looking to see if + * we are inside any of them. Return the intersecting triangle. This is all + * done in a 2d way. + */ +static struct tri *point_in_vert_tris(float *verts, struct vert_tris *vtris, float *point) +{ + for (int i = 0; i < vtris->tri_count; i++) { + struct tri *tri = &vtris->tris[i]; + float *v1 = &verts[tri->vert_indices[0]]; + float *v2 = &verts[tri->vert_indices[1]]; + float *v3 = &verts[tri->vert_indices[2]]; + if (point_in_tri(point, v1, v2, v3)) + return tri; + } + + return NULL; +} + + + +static void get_terrain_penetration(float *verts, struct tri *tri, float *pos, float *move) +{ + float tmp[3], normal[3]; + + float *v1 = &verts[tri->vert_indices[0]]; + float *v2 = &verts[tri->vert_indices[1]]; + float *v3 = &verts[tri->vert_indices[2]]; + + vec3_subtract(v3, v2, tmp); + vec3_subtract(v2, v1, normal); + vec3_cross(tmp, normal, normal); + vec3_normalize(normal, normal); + vec3_subtract(v1, pos, tmp); + float d = vec3_dot(tmp, normal); + vec3_scale(normal, d, move); + /* vec3_add(pos, tmp, move); */ +} -void collide_terrain(struct terrain *terrain, struct node *node, struct model *model, vec3 *move) + +void collide_terrain(struct terrain *terrain, float *pos, struct model *model, vec3 *move) { struct terrain_cell *cells[9] = {0}; struct grid_query queries[3]; @@ -118,8 +161,6 @@ void collide_terrain(struct terrain *terrain, struct node *node, struct model *m queries[i].cell_vert_index = -1; } - float *pos = node_world(node); - query_terrain_grid(terrain, pos[0], pos[1], cells); get_closest_verts(terrain, pos, queries, cells); @@ -129,11 +170,12 @@ void collide_terrain(struct terrain *terrain, struct node *node, struct model *m for (int i = 0; i < vtris->tri_count; i++) {; /* terrain_cell_debug(terrain, queries[i].cell, queries[i].cell_vert_index, pos); */ - terrain_tri_debug(terrain->verts, &vtris->tris[i]); + + struct tri *tri; + if ((tri = point_in_vert_tris(terrain->verts, vtris, pos))) { + terrain_tri_debug(terrain->verts, tri); + get_terrain_penetration(terrain->verts, tri, pos, move); + return; + } } } - - - /* assert(closest_cells[0]); */ - /* assert(closest_cells[1]); */ - /* assert(closest_cells[2]); */ diff --git a/src/terrain_collision.h b/src/terrain_collision.h @@ -6,6 +6,6 @@ #include "node.h" #include "model.h" -void collide_terrain(struct terrain *terrain, struct node *node, struct model *model, float *move); +void collide_terrain(struct terrain *terrain, float *pos, struct model *model, float *move); #endif /* TERRAIN_COLLISION_H */ diff --git a/src/update.c b/src/update.c @@ -1,7 +1,7 @@ #include "gl.h" #include "update.h" -#include "terrain.h" +#include "terrain_collision.h" #include "util.h" #include "mat4.h" #include "vec3.h" @@ -338,10 +338,14 @@ static void player_update(struct game *game, struct entity *player) struct terrain *terrain = &game->terrain; - player_terrain_collision(terrain, node); + /* player_terrain_collision(terrain, node); */ + + float move[3]; + collide_terrain(terrain, node_world(node), NULL, move); + node_translate(node, move); + /* vec3_add(player->velocity, move, player->velocity); */ + - collide_terrain(terrain, node, NULL, NULL); - node_recalc(node); } @@ -362,7 +366,7 @@ void update (struct game *game) { float *time = &res->time; float *light = res->light_dir; - gravity(game); + /* gravity(game); */ if (needs_terrain_update) { /* update_terrain(terrain); */ @@ -419,6 +423,8 @@ void update (struct game *game) { toggle_fog = 0; } + /* for (int i = 0; i < ) */ + *time = SDL_GetTicks(); day_night_cycle(*time, res);