bbox_t *box_offset_to(bbox_t *aa, bbox_t *bb, double x, double y, double z) { bb->x1 = aa->x1 + x; bb->x2 = aa->x2 + x; bb->y1 = aa->y1 + y; bb->y2 = aa->y2 + y; bb->z1 = aa->z1 + z; bb->z2 = aa->z2 + z; return bb; } bbox_t *box_add_coord(bbox_t *aa, bbox_t *bb, double x, double y, double z) { if(aa) AABB_PCOPY(aa, bb); if(x < 0.0D) bb->x1 += x; else if(x > 0.0D) bb->x2 += x; if(y < 0.0D) bb->y1 += y; else if(y > 0.0D) bb->y2 += y; if(z < 0.0D) bb->z1 += z; else if(z > 0.0D) bb->z2 += z; return bb; } bbox_t *box_union(bbox_t *aa, bbox_t *bb, double x, double y, double z) { if(aa) AABB_PCOPY(aa, bb); bb->x1 = MIN_VALUE(bb->x1, x); bb->y1 = MIN_VALUE(bb->y1, y); bb->z1 = MIN_VALUE(bb->z1, z); bb->x2 = MAX_VALUE(bb->x2, x); bb->y2 = MAX_VALUE(bb->y2, y); bb->z2 = MAX_VALUE(bb->z2, z); return bb; } #define BOX_OFFSET_FUNC(cc, cd, ce) \ double box_calc_ ## cc ## off(bbox_t *aa, bbox_t *bb, double offset) { \ if(bb->cd ## 2 > aa->cd ## 1 && bb->cd ## 1 < aa->cd ## 2 && bb->ce ## 2 > aa->ce ## 1 && bb->ce ## 1 < aa->ce ## 2) { \ if(offset > 0.0 && bb->cc ## 2 <= aa->cc ## 1) { \ double pdelta = aa->cc ## 1 - bb->cc ## 2; \ if(pdelta < offset) \ offset = pdelta; \ } \ else if(offset < 0.0 && bb->cc ## 1 >= aa->cc ## 2) { \ double ndelta = aa->cc ## 2 - bb->cc ## 1; \ if(ndelta > offset) \ offset = ndelta; \ } \ return offset; \ } \ else { \ return offset; \ } \ } BOX_OFFSET_FUNC(x, y, z) BOX_OFFSET_FUNC(y, x, z) BOX_OFFSET_FUNC(z, x, y) byte box_intersects(bbox_t *aa, bbox_t *bb) { return bb->x2 > aa->x1 && bb->x1 < aa->x2 && bb->y2 > aa->y1 && bb->y1 < aa->y2 && bb->z2 > aa->z1 && bb->z1 < aa->z2; } chunk_t *chunk_get(world_t *world, int x, int y, int z, byte load); int box_get_colliding(world_t *world, bbox_t **listptr, bbox_t *box) { bbox_t *list = sys.collision_list; int x1 = ((int)(double)(box->x1 + (box->x2 - box->x1) / 2.0)) / CHUNK_SIZE; int y1 = ((int)(double)(box->y1 + (box->y2 - box->y1) / 2.0)) / CHUNK_SIZE; int z1 = ((int)(double)(box->z1 + (box->z2 - box->z1) / 2.0)) / CHUNK_SIZE; int x2 = x1 + 2; int y2 = y1 + 2; int z2 = z1 + 2; x1 -= 2; y1 -= 2; z1 -= 2; // x1 = CHUNK_CLAMP(world, x1, x); // y1 = CHUNK_CLAMP(world, y1, y); // z1 = CHUNK_CLAMP(world, z1, z); // x2 = CHUNK_CLAMP(world, x2, x); // y2 = CHUNK_CLAMP(world, y2, y); // z2 = CHUNK_CLAMP(world, z2, z); int boxes = 0; ulong pos = 0; chunk_t *chunk; // = &world->global; geometry_t **gptr; geometry_t *geom; if(listptr) *listptr = list; while(gptr = tbl_iter(&world->global_geom, &pos)) { geom = *gptr; if(box_intersects(&geom->collision, box)) { list[boxes++] = geom->collision; if(boxes == COLL_MAX) return boxes; } } for(int cx = x1; cx <= x2; cx++) { for(int cz = z1; cz <= z2; cz++) { for(int cy = y1; cy <= y2; cy++) { if(!(chunk = chunk_get(world, cx, cy, cz, 0))) continue; pos = 0; while(geom = tbl_iter(&chunk->obj_table, &pos)) { if(!geom->global && box_intersects(&geom->collision, box)) { list[boxes++] = geom->collision; if(boxes == COLL_MAX) return boxes; } } } } } return boxes; } byte box_check_intersect(vec3 origin, vec3 dir, chunk_t *chunk, polygon_t *poly, float *dist) { vec3 vects[3]; for(int n = 0; n < 3; n++) { VEC3_SET(vects[n], poly->vertices[n].pos X + (float)chunk->box.x1, poly->vertices[n].pos Y + (float)chunk->box.y1, poly->vertices[n].pos Z + (float)chunk->box.z1); } return glm_ray_triangle(origin, dir, vects[0], vects[1], vects[2], dist); } ulong box_get_pointed(world_t *world, camera_t *cam, vec3 pos) { vec3 origin; ulong iter = 0; ulong id = 0; float dist; float mdist = 1000000.0f; chunk_t *chunk; geometry_t **gptr; geometry_t *geom; polygon_t *poly; int x = (int)NEG_OFFSET(cam->pos_x, CHUNK_SIZE); int y = (int)NEG_OFFSET(cam->pos_y, CHUNK_SIZE); int z = (int)NEG_OFFSET(cam->pos_z, CHUNK_SIZE); VEC3_SET(origin, (float)cam->pos_x, (float)cam->pos_y, (float)cam->pos_z); while(gptr = tbl_iter(&world->global_geom, &iter)) { geom = *gptr; if(!(chunk = chunk_get(world, geom->chunk_x, geom->chunk_y, geom->chunk_z, 0))) continue; poly = &chunk->poly_pool[geom->polys]; while(poly) { if(box_check_intersect(origin, cam->front, chunk, poly, &dist) && (dist < mdist)) { mdist = dist; id = geom->id; if(pos) { glm_vec3_scale(cam->front, dist, pos); glm_vec3_add(origin, pos, pos); } } poly = (poly->next == 0xffffffff) ? NULL : &chunk->poly_pool[poly->next]; } } for(int cx = -1; cx <= 1; cx++) { for(int cz = -1; cz <= 1; cz++) { for(int cy = -1; cy <= 1; cy++) { if(!(chunk = chunk_get(world, x + cx, y + cy, z + cz, 0))) continue; iter = 0; while(geom = tbl_iter(&chunk->obj_table, &iter)) { if(!geom->global) { poly = &chunk->poly_pool[geom->polys]; while(poly) { if(box_check_intersect(origin, cam->front, chunk, poly, &dist) && (dist < mdist)) { mdist = dist; id = geom->id; if(pos) { glm_vec3_scale(cam->front, dist, pos); glm_vec3_add(origin, pos, pos); } } poly = (poly->next == 0xffffffff) ? NULL : &chunk->poly_pool[poly->next]; } } } } } } return id; }