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