Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <math.h>
- #include "types.h"
- #include "vectormath.h"
- #include "matrixmath.h"
- extern struct Game game;
- inline int8_t sgn(const float input) {
- // Remove sign and check for ~= 0
- if ((float)((uint32_t)input & ~(1<<31)) < 0.00001f) return 0;
- int8_t values[] = { 1, -1 };
- return values[((uint32_t)input>>31)];
- }
- inline bool object_fits_within(struct object_bb *o, const int64_t x0, const int64_t x1, const int64_t z0, const int64_t z1) {
- return (!(o->offset.f[0] + o->difference.f[0] > x1 || o->offset.f[0] - o->difference.f[0] < x0 ||
- o->offset.f[2] + o->difference.f[2] > z1 || o->offset.f[2] - o->difference.f[2] < z0));
- }
- inline void gen_new_coords(const uint8_t quadrant, const int64_t x0, const int64_t x1, const int64_t z0, const int64_t z1, int64_t *new_x0, int64_t *new_x1, int64_t *new_z0, int64_t *new_z1) {
- assert(quadrant<=3);
- const uint64_t len_x = (uint64_t)((x1 - x0)/2),
- len_z = (uint64_t)((z1 - z0)/2);
- if (quadrant == 0 || quadrant == 3) {
- *new_x0 = x0 + len_x;
- *new_x1 = x1;
- } else {
- *new_x0 = x0;
- *new_x1 = x0 + len_x;
- }
- // 0 or 1 else 2 or 3
- if (quadrant < 2) {
- *new_z0 = z0 + len_z;
- *new_z1 = z1;
- } else {
- *new_z0 = z0;
- *new_z1 = z0 + len_z;
- }
- }
- // initial init, called each time a new node is created.
- void init_node(struct collision_node *node) {
- uint8_t x;
- const uint16_t default_entries = game.settings.bucket_size;
- for (x = 0; x < 4; ++x) {
- node->child[x] = NULL;
- }
- node->triangle = malloc(sizeof(union triangle) * default_entries);
- if (node->triangle == NULL) {
- // malloc error, tough break man
- }
- node->object_count = 0;
- node->max_objects = default_entries;
- }
- inline float comparef_lower(const float f1, const float f2) {
- return (f1 < f2) ? f1 : f2;
- //else return f2;
- }
- inline float comparef_higher(const float f1, const float f2) {
- return (f1 > f2) ? f1 : f2;
- }
- /*
- inline void gen_bb(struct object_bb *o, const union triangle tri) {
- uint8_t x;
- float min,max,difference[3],offset[3];
- o->tri = tri;
- for (x = 0; x < 3; ++x) {
- min = comparef_lower(o->tri.f[x],o->tri.f[x+4]);
- min = comparef_lower(min,o->tri.f[x+8]);
- max = comparef_higher(o->tri.f[x],o->tri.f[x+4]);
- max = comparef_higher(max,o->tri.f[x+8]);
- difference[x] = ((max - min) * 0.5f);
- offset[x] = min + difference[x];
- }
- memcpy(&o->difference,difference,sizeof(float)*3);
- memcpy(&o->offset,offset,sizeof(float)*3);
- }*/
- void gen_bb(struct object_bb *o, const union triangle tri) {
- o->tri = tri;
- union opt_vecf min, max;
- min.v = _mm_min_ps(tri.p[0].v, tri.p[1].v);
- min.v = _mm_min_ps(min.v, tri.p[2].v);
- max.v = _mm_max_ps(tri.p[0].v, tri.p[1].v);
- max.v = _mm_max_ps(max.v, tri.p[2].v);
- o->difference = vec3dividef(vec3sub(max, min), 2.f);
- o->offset = vec3add(min, o->difference);
- }
- // recursive insert
- void qtins_auto(struct collision_node *node, struct object_bb *o, int64_t x0, int64_t x1, int64_t z0, int64_t z1) {
- if (node->object_count < node->max_objects) {
- node->triangle[node->object_count] = o->tri;
- node->object_count++;
- } else {
- int x,y,z;
- int64_t new_x0, new_x1, new_z0, new_z1;
- bool bottom_level = (x1-x0 == 1);
- if (!bottom_level) {
- for (x = 0; x < 4; ++x) {
- gen_new_coords(x, x0, x1, z0, z1, &new_x0, &new_x1, &new_z0, &new_z1);
- if (object_fits_within(o, new_x0, new_x1, new_z0, new_z1)) {
- if (!node->child[x]) {
- node->child[x] = malloc(sizeof(struct collision_node));
- if (node->child[x]) {
- init_node(node->child[x]);
- }
- }
- qtins_auto(node->child[x],o,new_x0,new_x1,new_z0,new_z1);
- return;
- }
- }
- for (x = 0; x < 4; ++x) {
- gen_new_coords(x, x0, x1, z0, z1, &new_x0, &new_x1, &new_z0, &new_z1);
- struct object_bb new_bb;
- for (y = 0; y < node->object_count; ++y) {
- gen_bb(&new_bb,node->triangle[y]);
- if (object_fits_within(&new_bb,new_x0, new_x1, new_z0, new_z1)) {
- if (!node->child[x]) {
- node->child[x] = malloc(sizeof(struct collision_node));
- if (node->child[x] == NULL) {
- // malloc error
- } else {
- init_node(node->child[x]);
- }
- }
- qtins_auto(node->child[x], &new_bb, new_x0, new_x1, new_z0, new_z1);
- node->triangle[y] = o->tri;
- return;
- }
- }
- }
- }
- // couldn't find a target. resize our bucket and reinsert.
- const uint32_t new_size = (bottom_level) ? node->max_objects + 1 : node->max_objects * 2;
- union triangle *ptr = malloc(sizeof(union triangle) * (new_size));
- if (ptr == NULL) {
- // malloc error
- printf("malloc error\n");
- } else {
- memcpy(ptr,node->triangle,sizeof(union triangle) * node->max_objects);
- free(node->triangle);
- node->triangle = ptr;
- node->max_objects = new_size;
- qtins_auto(node,o,x0,x1,z0,z1);
- }
- }
- }
- // parent insert
- void qtins(struct Game *game, struct collision_node *node, union triangle tri) {
- struct object_bb obj_bb;
- gen_bb(&obj_bb,tri);
- const int64_t size = game->settings.max_width;
- qtins_auto(node, &obj_bb, -size, size, -size, size);
- }
- // wrapper function for inserting objects.
- void insert_tri(struct Game *game, struct collision_tree *tree, union triangle tri) {
- tree->num_objects++;
- qtins(game,&tree->parent_node, tri);
- }
- void init_tree(struct collision_tree *tree) {
- init_node(&tree->parent_node);
- tree->num_objects = 0;
- }
- void clear_map(struct collision_node *node) {
- int x;
- free(node->triangle);
- for (x = 0; x < 4; ++x) {
- if (node->child[x]) {
- clear_map(node->child[x]);
- free(node->child[x]);
- node->child[x] = NULL;
- }
- }
- }
- void print_node_debug_info(struct collision_node *node, int depth) {
- int x;
- for (x = 0; x < depth - 1; ++x) {
- if (x > 7) { printf("(%i)",depth); x = depth; }
- else printf("-");
- }
- printf(">%u/%u entities stored\n",node->object_count,node->max_objects);
- for (x = 0; x < 4; ++x) {
- if (node->child[x]) {
- printf("%i",x);
- print_node_debug_info(node->child[x],depth+1);
- }
- }
- }
- void print_tree_debug_info(struct collision_tree *tree) {
- printf("\n------------------------------------------\nDebug info for collision tree:\n %lu total objects imported\n",tree->num_objects);
- print_node_debug_info(&tree->parent_node, 0);
- printf("End of collision tree debug info\n\n");
- }
- void free_collision_tree(struct collision_tree *tree) {
- clear_map(&tree->parent_node);
- }
- union triangle conv_spheroid(const union triangle source, const union opt_vecf radii) {
- union triangle out;
- out.p[0] = vec3divide(source.p[0], radii);
- out.p[1] = vec3divide(source.p[1], radii);
- out.p[2] = vec3divide(source.p[2], radii);
- return out;
- }
- void check_triangle(struct collision_info *info, const union triangle tri) { //IN ESPACE
- struct tPlane triangle_plane = gen_tri_plane(tri);
- double t0, t1;
- bool embedded_in_plane = false;
- double signed_distance_to_triangle_plane = plane_signed_distance_to(info->base_point, triangle_plane);
- float normal_dot_velocity = dot(triangle_plane.normal,info->velocity);
- float slide_check = dot(triangle_plane.normal,vec3normalize(info->velocity));
- if (normal_dot_velocity == 0.f) {
- if (fabs(signed_distance_to_triangle_plane) >= 1.f) {
- return;
- } else {
- embedded_in_plane = true;
- t0 = 0.f; //spheroid is colliding with triangle for the entire time interval
- t1 = 1.f;
- }
- } else {
- t0 = (-1.f - signed_distance_to_triangle_plane) / normal_dot_velocity;
- t1 = ( 1.f - signed_distance_to_triangle_plane) / normal_dot_velocity;
- if (t0 > t1) {
- double temp = t1;
- t1 = t0;
- t0 = temp;
- }
- if (t0 > 1.f || t1 < 0.f) {
- return;
- }
- if (t0 < 0.f) t0 = 0.f;
- if (t1 < 0.f) t1 = 0.f;
- if (t0 > 1.f) t0 = 1.f;
- if (t1 > 1.f) t1 = 1.f;
- }
- union opt_vecf collision_point;
- union opt_vecf velocity = info->velocity;
- union opt_vecf base = info->base_point;
- bool found_collision = false;
- float t = 1.f;
- if (!embedded_in_plane) {
- union opt_vecf plane_intersection_point = vec3add(vec3sub(info->base_point, triangle_plane.normal), vec3multf(info->velocity,t0));
- if (check_point_in_triangle(plane_intersection_point, tri)) {
- found_collision = true;
- t = t0;
- collision_point = plane_intersection_point;
- }
- }
- if (!found_collision) {
- union opt_vecf p1_minus_base = vec3sub(tri.p[0],base);
- union opt_vecf p2_minus_base = vec3sub(tri.p[1],base);
- union opt_vecf p3_minus_base = vec3sub(tri.p[2],base);
- float velocity_squared_length = dot(velocity, velocity);
- float a,b,c, new_t;
- a = velocity_squared_length;
- b = 2.f * dot(velocity,vec3sub(base,tri.p[0]));
- c = dot(p1_minus_base,p1_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- t = new_t;
- found_collision = true;
- collision_point = tri.p[0];
- }
- b = 2.f * dot(velocity,vec3sub(base,tri.p[1]));
- c = dot(p2_minus_base,p2_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- t = new_t;
- found_collision = true;
- collision_point = tri.p[1];
- }
- b = 2.f * dot(velocity,vec3sub(base,tri.p[2]));
- c = dot(p3_minus_base,p3_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- t = new_t;
- found_collision = true;
- collision_point = tri.p[2];
- }
- union opt_vecf edge = vec3sub(tri.p[1], tri.p[0]);
- union opt_vecf base_to_vertex = vec3sub(tri.p[0], base);
- float edge_squared_length = dot(edge,edge);
- float edge_dot_velocity = dot(edge,velocity);
- float edge_dot_base_to_vertex = dot(edge,base_to_vertex);
- a = edge_squared_length * -velocity_squared_length +
- edge_dot_velocity * edge_dot_velocity;
- b = edge_squared_length * (2*dot(velocity,base_to_vertex)) -
- 2.0*edge_dot_velocity*edge_dot_base_to_vertex;
- c = edge_squared_length * (1-dot(base_to_vertex,base_to_vertex)) +
- edge_dot_base_to_vertex*edge_dot_base_to_vertex;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- float f = (edge_dot_velocity * new_t - edge_dot_base_to_vertex)/edge_squared_length;
- if (f >= 0.f && f <= 1.f) {
- t = new_t;
- found_collision = true;
- collision_point = vec3add(tri.p[0],vec3multf(edge,f));
- }
- }
- edge = vec3sub(tri.p[2], tri.p[1]);
- base_to_vertex = vec3sub(tri.p[1], base);
- edge_squared_length = dot(edge,edge);
- edge_dot_velocity = dot(edge,velocity);
- edge_dot_base_to_vertex = dot(edge,base_to_vertex);
- a = edge_squared_length * -velocity_squared_length +
- edge_dot_velocity * edge_dot_velocity;
- b = edge_squared_length * (2*dot(velocity,base_to_vertex)) -
- 2.0*edge_dot_velocity*edge_dot_base_to_vertex;
- c = edge_squared_length * (1-dot(base_to_vertex,base_to_vertex)) +
- edge_dot_base_to_vertex*edge_dot_base_to_vertex;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- const float f = (edge_dot_velocity * new_t - edge_dot_base_to_vertex)/edge_squared_length;
- if (f >= 0.f && f <= 1.f) {
- t = new_t;
- found_collision = true;
- collision_point = vec3add(tri.p[1],vec3multf(edge,f));
- }
- }
- edge = vec3sub(tri.p[0], tri.p[2]);
- base_to_vertex = vec3sub(tri.p[2], base);
- edge_squared_length = dot(edge,edge);
- edge_dot_velocity = dot(edge,velocity);
- edge_dot_base_to_vertex = dot(edge,base_to_vertex);
- a = edge_squared_length * -velocity_squared_length +
- edge_dot_velocity * edge_dot_velocity;
- b = edge_squared_length * (2*dot(velocity,base_to_vertex)) -
- 2.0*edge_dot_velocity*edge_dot_base_to_vertex;
- c = edge_squared_length * (1-dot(base_to_vertex,base_to_vertex)) +
- edge_dot_base_to_vertex*edge_dot_base_to_vertex;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- float f = (edge_dot_velocity * new_t - edge_dot_base_to_vertex)/edge_squared_length;
- if (f >= 0.f && f <= 1.f) {
- t = new_t;
- found_collision = true;
- collision_point = vec3add(tri.p[2],vec3multf(edge,f));
- }
- }
- }
- if (found_collision) {
- float distance_to_collision = t * vec3gen_length(info->velocity);
- if (!info->collision_found || distance_to_collision < info->nearest_distance) {
- info->nearest_distance = distance_to_collision;
- info->intersection_point = collision_point;
- info->collision_found = true;
- }
- }
- }
- void check_triangle_r3(struct collision_info_r3 *info, const union triangle tri) {
- struct tPlane triangle_plane = gen_tri_plane(tri);
- double signed_distance_to_triangle_plane = plane_signed_distance_to(info->r3_position, triangle_plane);
- float normal_dot_velocity = dot(triangle_plane.normal,info->r3_velocity);
- if (normal_dot_velocity == 0.f) {
- return;
- }
- double t = -signed_distance_to_triangle_plane / normal_dot_velocity;
- if(t > 1.f || t < 0.f) return;
- union opt_vecf plane_intersection_point = vec3add(info->r3_position, vec3multf(info->r3_velocity,t));
- if (check_point_in_triangle(plane_intersection_point, tri)) {
- float distance_to_collision = t * vec3gen_length(info->r3_velocity);
- if (!info->collision_found) {
- info->collision_found = true;
- }
- if (distance_to_collision < info->nearest_distance) {
- info->nearest_distance = distance_to_collision;
- info->intersection_point = plane_intersection_point;
- }
- }
- }
- void check_collision_recursive(struct collision_node *node, struct collision_info *info, const int64_t x0, const int64_t x1, const int64_t z0, const int64_t z1) {
- int x;
- int i;
- normalized_velocity = info->normalized_velocity;
- for (x = 0; x < node->object_count; ++x) {
- const union triangle new_tri = conv_spheroid(node->triangle[x],info->e_radius);
- check_triangle(info, new_tri);
- }
- //IMPLEMENT ACQUISITION OF MOVEMENT BOUND RECTANGE VERTICES
- //mb_x = movement bounds x coords
- //mb_z = movement bounds z coords
- /*info->velocity = e_space_velocity;
- info->normalized_velocity = vec3normalize(e_space_velocity);
- info->base_point = e_space_position;
- info->collision_found = false;
- info->normalized_velocity*/
- //create vector called perp_normalized_velocity, switch x and z, make one negative.
- //outer edges of ellipsoid perpendicular to movement vector + radius vector or velocity vector and radius vector
- //movement bounds vertices
- /*double mb_x[4], mb_z[4], n_x0, n_x1, n_z0, n_z1;
- mb_x[0] = info->base_point.x + perp_normalized_velocity.x - info->normalized_velocity.x;
- mb_y[0] = info->base_point.z + perp_normalized_velocity.z - info->normalized_velocity.z;
- mb_x[1] = info->base_point.x - perp_normalized_velocity.x - info->normalized_velocity.x;
- mb_y[1] = info->base_point.z - perp_normalized_velocity.z - info->normalized_velocity.z;
- mb_x[2] = info->base_point.x - perp_normalized_velocity.x + info->velocity.x + info->normalized_velocity.x;
- mb_y[2] = info->base_point.z - perp_normalized_velocity.z + info->velocity.z + info->normalized_velocity.z;
- mb_x[3] = info->base_point.x + perp_normalized_velocity.x + info->velocity.x + info->normalized_velocity.x;
- mb_y[3] = info->base_point.z + perp_normalized_velocity.z + info->velocity.z + info->normalized_velocity.z;*/
- uint8_t point2; //choose better data type
- bool up, down, left, right, in_x, in_y, checked;
- union opt_vecf normal1;
- union opt_vecf normal2;
- for (x = 0; x < 4; ++x ) {
- if (node->child[x]) {
- int64_t new_x0, new_x1, new_z0, new_z1;
- gen_new_coords(x,x0,x1,z0,z1,&new_x0,&new_x1,&new_z0,&new_z1);
- union opt_vecf base = info->base_point;
- union opt_vecf vel_y;
- bool embedded_in_plane;
- in_x = new_x0 <= base.x && base.x <= new_x1;
- in_y = new_z0 <= base.z && base.z <= new_z1;
- if (in_x && in_y ) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- }
- else {
- left = base.x < new_x0;
- right = base.x > new_x1;
- up = base.z < new_y0;
- down = base.z > new_y1;
- vel = info->e_space_velocity;
- vel_y = new_vec3(vel.x, 0, vel.z);
- double t0, t1;
- if(!in_x) {
- normal = new_vec3((float)(left * -1 + right * 1), 0, 0);
- embedded_in_plane = false;
- double signed_distance_to_line = plane_signed_distance_to(base, new_vec3((float)(new_x0 * (uint64_t)left + new_x1 * (uint64_t)right), 0, 0));
- float normal_dot_velocity = dot(normal, vel_y);
- if (normal_dot_velocity == 0.f) {
- if (fabs(signed_distance_to_line) <= 1.f) {
- embedded_in_plane = true;
- t0 = 0.f; //spheroid is colliding with triangle for the entire time interval
- t1 = 1.f;
- }
- } else {
- t0 = (-1.f - signed_distance_to_line) / normal_dot_velocity;
- t1 = ( 1.f - signed_distance_to_line) / normal_dot_velocity;
- if (t0 > t1) {
- double temp = t1;
- t1 = t0;
- t0 = temp;
- }
- if (t0 > 1.f || t1 < 0.f) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;//move to next line
- }
- if (t0 < 0.f) t0 = 0.f;
- if (t1 < 0.f) t1 = 0.f;
- if (t0 > 1.f) t0 = 1.f;
- if (t1 > 1.f) t1 = 1.f;
- }
- float t = 1.f;
- if (!embedded_in_plane) {
- union opt_vecf plane_intersection_point = vec3add(vec3sub(base, normal), vec3multf(vel_y, t0));
- if (plane_intersection_point.y >= y0 && plane_intersection_point.y <= y1) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;
- }
- }
- }
- if(!in_z) {
- normal = new_vec3(0, 0, (float)(up * 1 + down * -1));
- embedded_in_plane = false;
- double signed_distance_to_line = plane_signed_distance_to(base, new_vec3(0, 0, (float)(new_z0 * (uint64_t)down + new_z1 * (uint64_t)up));
- float normal_dot_velocity2 = dot(normal, vel_y);
- if (normal_dot_velocity == 0.f) {
- if (fabs(signed_distance_to_line) <= 1.f) {
- embedded_in_plane = true;
- t0 = 0.f; //spheroid is colliding with triangle for the entire time interval
- t1 = 1.f;
- }
- } else {
- t0 = (-1.f - signed_distance_to_line) / normal_dot_velocity;
- t1 = ( 1.f - signed_distance_to_line) / normal_dot_velocity;
- if (t0 > t1) {
- double temp = t1;
- t1 = t0;
- t0 = temp;
- }
- if (t0 > 1.f || t1 < 0.f) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;//move to next line
- }
- if (t0 < 0.f) t0 = 0.f;
- if (t1 < 0.f) t1 = 0.f;
- if (t0 > 1.f) t0 = 1.f;
- if (t1 > 1.f) t1 = 1.f;
- }
- float t = 1.f;
- if (!embedded_in_plane) {
- union opt_vecf plane_intersection_point = vec3add(vec3sub(base, normal), vec3multf(vel_y, t0));
- if (plane_intersection_point.y >= y0 && plane_intersection_point.y <= y1) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;
- }
- }
- }
- union opt_vecf p1 = new_vec3(new_x0,0,new_y0);
- union opt_vecf p2 = new_vec3(new_x0,0,new_y1);
- union opt_vecf p3 = new_vec3(new_x1,0,new_y1);
- union opt_vecf p4 = new_vec3(new_x0,0,new_y1);
- union opt_vecf p1_minus_base = vec3sub(p1,base);
- union opt_vecf p2_minus_base = vec3sub(p2,base);
- union opt_vecf p3_minus_base = vec3sub(p3,base);
- union opt_vecf p4_minus_base = vec3sub(p4,base);
- float velocity_squared_length = dot(velocity, velocity);
- float a,b,c, new_t;
- a = velocity_squared_length;
- b = 2.f * dot(velocity,vec3sub(base,p1);
- c = dot(p1_minus_base,p1_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;
- }
- b = 2.f * dot(velocity,vec3sub(base,p2));
- c = dot(p2_minus_base,p2_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;
- }
- b = 2.f * dot(velocity,vec3sub(base,tri.p3));
- c = dot(p3_minus_base,p3_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;
- }
- b = 2.f * dot(velocity,vec3sub(base,tri.p4));
- c = dot(p4_minus_base,p4_minus_base) - 1.f;
- if (get_lowest_root(a,b,c,t,&new_t)) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- continue;
- }
- }
- }
- }
- /*for (x = 0; x < 4; ++x ) {
- if (node->child[x]) {
- int64_t new_x0, new_x1, new_z0, new_z1;
- gen_new_coords(x,x0,x1,z0,z1,&new_x0,&new_x1,&new_z0,&new_z1);
- n_x0 = (double) *new_x0;
- n_x1 = (double) *new_x1;
- n_z0 = (double) *new_z0;
- n_z1 = (double) *new_z1;
- up = null;
- //case 0: no x or z overlap with quadrant => do not check quadrant. Skip to next iteration of for loop.
- for (int i = 0; i < 4; ++i) {
- //can eliminate if statements by storing bools in an array and adding the elements of the array. If the sum > 0 for x or z, in_x or in_z respectively must be true. Can experiment with this once implemented.
- if(mb_x[i] > n_x0 && mb_x[i] < n_x1) in_x = true; //if a movement bounds vertex lies within the x range, note it
- if(mb_z[i] > n_z0 && mb_z[i] < n_z1) in_z = true; //if a movement bounds vertex lies within the z range, note it
- }
- if(!(in_x || in_z)){ //if no x or z overlap, skip
- continue;
- }
- //case 1: a vertex lies in a quadrant => check quadrant
- for (i = 0; i < 4; ++i) {
- if (mb_x[i] >= n_x0 && mb_x[i] <= n_x1) {
- if(mb_z[i] >= n_z0 && mb_z[i] <= n_z1){
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- break;
- }
- }
- }
- //case 2: a line is parallel to a quadrant => simple check to determine if it's inside (remember no vertices lie within bounds)
- if (mb_x[0] == mb_x[1] || mb_y[0] == mb_y[1]) { //lines are parallel to quadrant
- up = false;
- down = false;
- left = false;
- right = false;
- checked = true; //marked so we don't re-check these booleans later
- for (int i = 0, i < 4, ++i) {
- //can eliminate if statements by storing bools in an array and adding the elements of the array. If the sum > 0 for any boolean's array dimension, the boolean is true. Can experiment with this once implemented.
- if (mb_x[i] > n_x1) right = true;
- if (mb_x[i] < n_x0) left = true;
- if (mb_z[i] > n_z1) up = true;
- if (mb_z[i] < n_z0) down = true;
- if (left && right || up && down) { //if the parallel movement bounds crosses the quadrant across either x or z (we know the movement bounds lie within the x or z ranges from the check above)
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- break;
- }
- }
- continue; //intersection impossible, do not check quadrant
- }
- //case 3: no vertex lies in a quadrant and no vertex is parallel
- //case 3a: one vertex lies inside x or z bounds, adjacent vertex lies inside other coordinate's bounds => check for solution of line formed by the two points with edge of quadrant
- //case 3b: 3a's condition is not met, intersection is impossible. Do not check quadrant.
- //REWRITE THIS. IT DOESN'T EVEN KIND OF WORK.
- for (i = 0; i < 4; ++i) { //CAN RUN IF STATEMENTS TO ELIMINATE SOME OR ALL OF THESE CHECKS
- point2 = (i+1)%4; //for the base case you take the vector from current point to point + 1, if i=3 you need a vector from the last point to the first point. This statement accomplishes this.
- if (!(n_x0 > mb_x[i] && n_x0 > mb_x[point2])) {
- //z_theta_new_x0 is the z value of the line from the first point to second point at new_x0, the leftmost vertical boundary of the quadrant. If z_theta lies within the z bounds of the quadrant and lies on the line segment, then the lines intersect.
- z_theta_new_x0 = (n_x0 - mb_x[i]) * (mb_z[point2] - mb_z[i]) / (mb_x[point2] - mb_x[i]) + mb_z[i];
- if (z_theta_new_x0 >= n_z0 && z_theta_new_x0 <= n_z1 ) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- break;
- }
- continue;
- }
- if (!(n_x1 < mb_x[i] && n_x1 < mb_x[point2])) {
- z_theta_new_x1 = (n_x1 - mb_x[i]) * (mb_z[point2] - mb_z[i]) / (mb_x[point2] - mb_x[i]) + mb_z[i];
- if (z_theta_new_x1 >= n_z0 && z_theta_new_x1 <= n_z1 ) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- break;
- }
- continue;
- }
- if (!(n_z0 > mb_z[i] && n_z0 > mb_z[point2])) {
- //x_theta_new_z0 is the x value of the line from the first point to second point at new_z0, the bottom horizontal boundary of the quadrant. If x_theta lies within the x bounds of the quadrant and lies on the line segment, then the lines intersect.
- x_theta_new_z0 = (n_z0 - mb_z[i]) * (mb_x[point2] - mb_x[i]) / (mb_z[point2] - mb_z[i]) + mb_x[i];
- if (x_theta_new_z0 >= n_x0 && x_theta_new_z0 <= n_x1 ) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- break;
- }
- continue;
- }
- if (!(n_z1 < mb_y[i] && n_z0 < mb_y[point2])) {
- x_theta_new_z1 = (n_z1 - mb_z[i]) * (mb_x[point2] - mb_x[i]) / (mb_z[point2] - mb_z[i]) + mb_x[i];
- if (x_theta_new_z1 >= n_x0 && x_theta_new_z1 <= n_x1 ) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- break;
- }
- continue;
- }
- }
- //case 4: movement bounds enclose quadrant => check quadrant
- if (checked = false) {
- up = false;
- down = false;
- left = false;
- right = false;
- for (int i = 0, i < 4, ++i) {
- if (mb_x[i] > n_x1) {
- right = true;
- }
- if (mb_x[i] < n_x0) {
- left = true;
- }
- if (mb_z[i] > n_z1) {
- up = true;
- }
- if (mb_z[i] < n_z0) {
- down = true;
- }
- }
- }
- if (up && down && left && right) {
- check_collision_recursive(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- }
- }
- }*/
- }
- void check_collision_recursive_r3(struct collision_node *node, struct collision_info_r3 *info, const int64_t x0, const int64_t x1, const int64_t z0, const int64_t z1) {
- uint32_t x;
- for (x = 0; x < node->object_count; ++x) {
- check_triangle_r3(info, node->triangle[x]);
- }
- //IMPLEMENT ACQUISITION OF RECTANGE VERTICES
- /*for (x = 0; x < 4; ++x ) {
- if (node->child[x]) {
- int64_t new_x0, new_x1, new_z0, new_z1;
- gen_new_coords(x,x0,x1,z0,z1,&new_x0,&new_x1,&new_z0,&new_z1);
- const float e = 100.f; // change this to movement speed
- if (info->r3_position.f[0] + e >= new_x0 && info->r3_position.f[0] - e <= new_x1) {
- if (info->r3_position.f[2] + e >= new_z0 && info->r3_position.f[2] - e <= new_z1) {
- check_collision_recursive_r3(node->child[x],info,new_x0,new_x1,new_z0,new_z1);
- }
- }
- }
- }*/
- }
- bool check_collision(struct collision_node *node, struct collision_info *info) {
- const int64_t max = game.settings.max_width;
- check_collision_recursive(node, info, -max, max, -max, max);
- return info->collision_found;
- }
- bool check_collision_r3(struct collision_node *node, struct collision_info_r3 *info) {
- const int64_t max = game.settings.max_width;
- check_collision_recursive_r3(node, info, -max, max, -max, max);
- return info->collision_found;
- }
- float gravity(struct Combat_entity *entity) {
- //edit constants
- const float acceleration = 0.0005f;
- const float max_speed = 0.95f;
- const float jump_speed = 0.171f;
- float gravity_speed;
- if (entity->jumping) {
- gravity_speed = jump_speed-acceleration*(game.current_time-entity->player_initial_fall_time-game.settings.target_tickrate);
- if (entity->touched_something_while_jumping && gravity_speed > 0.f) {
- entity->player_initial_fall_time = game.current_time;
- entity->jumping = false;
- return 0.f;
- }
- return gravity_speed;
- }
- if (entity->gravity_acting) {
- gravity_speed = -acceleration*(game.current_time-entity->player_initial_fall_time-game.settings.target_tickrate);
- if (gravity_speed <= -max_speed) {
- return -max_speed;
- }
- return gravity_speed;
- } else {
- return 0.f;
- }
- }
- union opt_vecf m(struct collision_node *node, struct collision_info *info, const uint8_t depth, union opt_vecf e_space_position, union opt_vecf e_space_velocity, struct Combat_entity *player) {
- if (depth > 4) {
- e_space_position.f[1] += 0.008f;
- puts("ERROR CONDITION OCCURED");fflush(stdout);
- return e_space_position;
- }
- //union opt_vecf original_velocity_vector;
- //if(depth == 0) {
- //original_velocity_vector = e_space_velocity;
- /*
- if(e_space_velocity.f[1] == 0.f) {
- //e_space_velocity.f[1] -= 0.1f; //adds some negative y vector fudge factor to keep you grounded if you travel downhill on a surface you can stand on.
- } //this should be changed to some generalized value to fit all cases
- */
- //} //the alternative to using a fudge factor is to use vector algebra to actually "snap" the player to the ground. I really cba.
- info->velocity = e_space_velocity;
- info->normalized_velocity = vec3normalize(e_space_velocity);
- info->base_point = e_space_position;
- info->collision_found = false;
- check_collision(node, info);
- if (!info->collision_found){
- return vec3add(e_space_position, e_space_velocity);
- }
- if (player->jumping) {
- player->touched_something_while_jumping = true;
- }
- if (vec3normalize(vec3sub(info->base_point,info->intersection_point)).f[1] > 0.8f) { //explain physical significance
- player->jumping = false;
- player->touched_something_while_jumping = false;
- player->gravity_acting = false;
- player->player_initial_fall_time = game.current_time;
- }
- if (vec3normalize(vec3sub(info->base_point,info->intersection_point)).f[1] < -0.93969262078f){ //explain physical significance
- player->jumping = false;
- player->player_initial_fall_time = game.current_time;
- }
- const float close_distance = 0.004f;
- union opt_vecf new_base_point = e_space_position;
- if (info->nearest_distance >= close_distance) {
- union opt_vecf v = vec3set_length(e_space_velocity,info->nearest_distance-close_distance);
- new_base_point = vec3add(info->base_point,v);
- v = vec3normalize(v);
- info->intersection_point = vec3sub(info->intersection_point,vec3multf(v,close_distance));
- }
- if (vec3normalize(vec3sub(info->base_point,info->intersection_point)).f[1] > 0.8f) {//if you're on a surface you can stand on
- if (player->gravity_acting && gravity(player) < -0.07f) { //if gravity is acting on you noticeably
- return new_base_point; //disallows sliding due to gravity
- }
- }
- if(depth == 0 && gravity(player) == 0.f) { //if you added a fudge factor to stay grounded earlier
- //e_space_velocity.f[1] += 0.1f; //subtracts out the y vector so it doesn't affect sliding.
- info->velocity = e_space_velocity; //corrects collision info information to account for this change
- //return m(node, info, depth+1, new_base_point, e_space_velocity, player);
- }
- union opt_vecf destination_point = vec3add(e_space_position, e_space_velocity); //calculates destination point with new, fudge factor-less velocity
- union opt_vecf new_velocity_vector;
- struct tPlane sliding_plane;
- sliding_plane.normal = vec3normalize(vec3sub(new_base_point,info->intersection_point));
- sliding_plane.origin = info->intersection_point;
- sliding_plane.equation[3] = -dot(sliding_plane.normal, sliding_plane.origin);
- if(vec3normalize(vec3sub(new_base_point,info->intersection_point)).f[1] > 0.8f && info->sliding_plane.normal.f[1] != 0.f || !player->gravity_acting) { //add comments explaining snapping
- union opt_vecf intersection_plus_velocity = vec3add(info->intersection_point, new_vec3(e_space_velocity.f[0], 0.f, e_space_velocity.f[2]));
- union opt_vecf snapped_destination = find_point_in_plane_xz(sliding_plane, intersection_plus_velocity.f[0], intersection_plus_velocity.f[2]);
- new_velocity_vector = vec3sub(snapped_destination, info->intersection_point);
- if (vec3gen_length(new_velocity_vector) < close_distance) {
- return new_base_point;
- }
- return m(node, info, depth+1, new_base_point, new_velocity_vector, player);
- }
- union opt_vecf new_destination_point = vec3sub(destination_point,vec3multf(sliding_plane.normal,plane_signed_distance_to(destination_point,sliding_plane)));
- new_velocity_vector = vec3sub(new_destination_point,info->intersection_point);
- /*if(!vec3normalize(vec3sub(info->base_point,info->intersection_point)).f[1] > 0.8f){
- new_velocity_vector.f[1] = 0;
- }*/
- if (vec3gen_length(new_velocity_vector) < close_distance) {
- return new_base_point;
- }
- return m(node, info, depth+1, new_base_point, new_velocity_vector, player);
- }
- bool check_los (struct collision_node *node, struct Combat_entity *player1, union opt_vecf r3_point) {
- struct collision_info_r3 info;
- info.r3_position = vec3add(player1->position, new_vec3(0.f,1.f,0.f)); //NEED TO STORE PLAYER RADII ON THE PLAYER OBJECT. ADD THE Y VALUE OF THE RADII VECTOR. ty dude
- info.r3_velocity = vec3sub(r3_point,player1->position);
- info.collision_found = false;
- check_collision_r3(node, &info);
- if (!info.collision_found) return true;
- return false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement