aabb2 cast_aabb(game* g, aabb2 self, vec2 delta, int* clipped) { aabb2 bounds(expand_toward(self, delta)); int x0 = fast_floor(bounds.min.x); int y0 = fast_floor(bounds.min.y); int x1 = fast_floor(bounds.max.x); int y1 = fast_floor(bounds.max.y); vec2 clipped_delta = delta; for(int x = x0; x <= x1; x++) { for(int y = y0; y <= y1; y++) { if (g->get_tile(x, y) != TT_EMPTY) { clipped_delta.x = clip_x(aabb2(vec2((float)x, (float)y), vec2((float)(x + 1), (float)(y + 1))), self, clipped_delta.x); } } } self.min.x += clipped_delta.x; self.max.x += clipped_delta.x; for(int x = x0; x <= x1; x++) { for(int y = y0; y <= y1; y++) { if (g->get_tile(x, y) != TT_EMPTY) { clipped_delta.y = clip_y(aabb2(vec2((float)x, (float)y), vec2((float)(x + 1), (float)(y + 1))), self, clipped_delta.y); } } } self.min.y += clipped_delta.y; self.max.y += clipped_delta.y; if (clipped) { *clipped = 0; if (delta.x != clipped_delta.x) *clipped |= (delta.x > 0.0f) ? CLIPPED_XP : CLIPPED_XN; if (delta.y != clipped_delta.y) *clipped |= (delta.y > 0.0f) ? CLIPPED_YP : CLIPPED_YN; } return self; }
bool clip_cg_line ( sk_cg_geometry *source, int x_min, int y_min, int x_max, int y_max ) { if (!source) { return false; } UINT_8 code_a = cohen_code_cg_point(&source->geometry.line.a, x_min, y_min, x_max, y_max); UINT_8 code_b = cohen_code_cg_point(&source->geometry.line.b, x_min, y_min, x_max, y_max); if (code_a & code_b) { // If line segments are completely outside the window, // c_0 & c_1 != 0 return false; } UINT_8 code = code_a ^ code_b; UINT_64 x_c = 0; UINT_64 y_c = 0; while (code) { if (code & 0x1) { clip_x(&source->geometry.line.a, &source->geometry.line.b, code_a & 0x1 ? &source->geometry.line.a : &source->geometry.line.b, x_min); } else if (code & 0x2) { clip_x(&source->geometry.line.a, &source->geometry.line.b, code_a & 0x2 ? &source->geometry.line.a : &source->geometry.line.b, x_max); } else if (code & 0x4) { clip_y(&source->geometry.line.a, &source->geometry.line.b, code_a & 0x4 ? &source->geometry.line.a : &source->geometry.line.b, y_min); } else if (code & 0x8) { clip_y(&source->geometry.line.a, &source->geometry.line.b, code_a & 0x8 ? &source->geometry.line.a : &source->geometry.line.b, y_max); } code_a = cohen_code_cg_point(&source->geometry.line.a, x_min, y_min, x_max, y_max); code_b = cohen_code_cg_point(&source->geometry.line.b, x_min, y_min, x_max, y_max); code = code_a ^ code_b; continue; } return !(code_a & code_b); }