1 module re.math.bounds; 2 3 import std.algorithm.comparison; 4 static import raymath; 5 import re.math; 6 7 static class Bounds { 8 /** based on 9 calculate bounds for an object in 2d space taking into account its transform 10 https://github.com/prime31/Nez/blob/0e97e68bd9df191fb3b893eb69e54238c30fcc80/Nez.Portable/Utils/Extensions/Bounds.cs#L184 11 */ 12 public static Rectangle calculate(ref Transform transform, Vector2 origin, 13 float width, float height) { 14 auto rotation = transform.rotation_z; 15 auto position = transform.position2; 16 auto scale = transform.scale2; 17 if (rotation == 0) { 18 return Rectangle(cast(int)(position.x - (origin.x * scale.x)), 19 cast(int)(position.y - (origin.y * scale.y)), 20 cast(int)(width * scale.x), cast(int)(height * scale.y)); 21 } else { 22 auto tmp1 = Matrix4.init; 23 24 // set the reference point to world reference taking origin into account 25 auto transform_mat = raymath.MatrixTranslate(-position.x - origin.x, 26 -position.y - origin.y, 0); 27 tmp1 = raymath.MatrixScale(scale.x, scale.y, 1); // scale -> 28 transform_mat = raymath.MatrixMultiply(transform_mat, tmp1); 29 tmp1 = raymath.MatrixRotateZ(rotation); // rotate -> 30 transform_mat = raymath.MatrixMultiply(transform_mat, tmp1); 31 tmp1 = raymath.MatrixTranslate(position.x, position.y, 0); // translate back 32 transform_mat = raymath.MatrixMultiply(transform_mat, tmp1); 33 34 // get all four corners in world space 35 auto top_left_w = Vector3(position.x, position.y, 0); 36 auto top_right_w = Vector3(position.x + width, position.y, 0); 37 auto btm_left_w = Vector3(position.x, position.y + height, 0); 38 auto btm_right_w = Vector3(position.x + width, position.y + height, 0); 39 40 // transform the corners into our work space 41 auto top_left = raymath.Vector3Transform(top_left_w, transform_mat); 42 auto top_right = raymath.Vector3Transform(top_right_w, transform_mat); 43 auto btm_left = raymath.Vector3Transform(btm_left_w, transform_mat); 44 auto btm_right = raymath.Vector3Transform(btm_right_w, transform_mat); 45 46 // find the min and max values so we can concoct our bounding box 47 auto min_x = cast(int) min(top_left.x, btm_right.x, top_right.x, btm_left.x); 48 auto max_x = cast(int) max(top_left.x, btm_right.x, top_right.x, btm_left.x); 49 auto min_y = cast(int) min(top_left.y, btm_right.y, top_right.y, btm_left.y); 50 auto max_y = cast(int) max(top_left.y, btm_right.y, top_right.y, btm_left.y); 51 52 return Rectangle(min_x, min_y, max_x - min_x, max_y - min_y); 53 } 54 } 55 56 /// calculate the new bounding box by applying the transform to the raw bounding box 57 public static BoundingBox calculate(BoundingBox bounds, ref Transform transform) { 58 auto t_min = raymath.Vector3Transform(bounds.min, transform.local_to_world_transform); 59 auto t_max = raymath.Vector3Transform(bounds.max, transform.local_to_world_transform); 60 return BoundingBox(t_min, t_max); 61 62 // this is a crappy workaround, using dlib 63 // import re.util.dlib; 64 65 // auto rot_quat = transform.orientation; 66 // auto dl_rot_quat = convert_quat(rot_quat); 67 // auto dl_rot_mat = dl_rot_quat.toMatrix4x4(); 68 // auto t_min = convert_vec3(bounds.min) * dl_rot_mat; 69 // auto t_max = convert_vec3(bounds.max) * dl_rot_mat; 70 // auto dl_tf = convert_mat(transform.local_to_world_transform); 71 // auto t_min = convert_vec3(bounds.min) * dl_tf; 72 // auto t_max = convert_vec3(bounds.max) * dl_tf; 73 74 // return BoundingBox(convert_vec3(t_min), convert_vec3(t_max)); 75 // return BoundingBox(bounds.min * 1.1f, bounds.max * 1.1f); 76 } 77 }