diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 54e081c13a..902f3dfc7a 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -164,13 +164,13 @@ static paint_struct * sub_9819_c(paint_session * session, uint32 image_id, Locat break; } - ps->bound_box_x_end = boundBoxSize.x + boundBoxOffset.x + session->SpritePosition.x; - ps->bound_box_z = boundBoxOffset.z; - ps->bound_box_z_end = boundBoxOffset.z + boundBoxSize.z; - ps->bound_box_y_end = boundBoxSize.y + boundBoxOffset.y + session->SpritePosition.y; + ps->bounds.x_end = boundBoxSize.x + boundBoxOffset.x + session->SpritePosition.x; + ps->bounds.z = boundBoxOffset.z; + ps->bounds.z_end = boundBoxOffset.z + boundBoxSize.z; + ps->bounds.y_end = boundBoxSize.y + boundBoxOffset.y + session->SpritePosition.y; ps->flags = 0; - ps->bound_box_x = boundBoxOffset.x + session->SpritePosition.x; - ps->bound_box_y = boundBoxOffset.y + session->SpritePosition.y; + ps->bounds.x = boundBoxOffset.x + session->SpritePosition.x; + ps->bounds.y = boundBoxOffset.y + session->SpritePosition.y; ps->attached_ps = nullptr; ps->var_20 = nullptr; ps->sprite_type = session->InteractionType; @@ -294,36 +294,58 @@ void paint_session_generate(paint_session * session) } } -static bool is_bbox_intersecting(uint8 rotation, const paint_struct_bound_box& initialBBox, +template static bool check_bounding_box(const paint_struct_bound_box& initialBBox, const paint_struct_bound_box& currentBBox) { - bool result = false; - switch (rotation) { - case 0: - if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end >= currentBBox.y && initialBBox.x_end >= currentBBox.x - && !(initialBBox.z < currentBBox.z_end && initialBBox.y < currentBBox.y_end && initialBBox.x < currentBBox.x_end)) - result = true; - break; - case 1: - if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end >= currentBBox.y && initialBBox.x_end < currentBBox.x - && !(initialBBox.z < currentBBox.z_end && initialBBox.y < currentBBox.y_end && initialBBox.x >= currentBBox.x_end)) - result = true; - break; - case 2: - if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end < currentBBox.y && initialBBox.x_end < currentBBox.x - && !(initialBBox.z < currentBBox.z_end && initialBBox.y >= currentBBox.y_end && initialBBox.x >= currentBBox.x_end)) - result = true; - break; - case 3: - if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end < currentBBox.y && initialBBox.x_end >= currentBBox.x - && !(initialBBox.z < currentBBox.z_end && initialBBox.y >= currentBBox.y_end && initialBBox.x < currentBBox.x_end)) - result = true; - break; - } - return result; + return false; } -paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadrantIndex, uint8 flag) +template<> bool check_bounding_box<0>(const paint_struct_bound_box& initialBBox, + const paint_struct_bound_box& currentBBox) +{ + if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end >= currentBBox.y && initialBBox.x_end >= currentBBox.x + && !(initialBBox.z < currentBBox.z_end && initialBBox.y < currentBBox.y_end && initialBBox.x < currentBBox.x_end)) + { + return true; + } + return false; +} + +template<> bool check_bounding_box<1>(const paint_struct_bound_box& initialBBox, + const paint_struct_bound_box& currentBBox) +{ + if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end >= currentBBox.y && initialBBox.x_end < currentBBox.x + && !(initialBBox.z < currentBBox.z_end && initialBBox.y < currentBBox.y_end && initialBBox.x >= currentBBox.x_end)) + { + return true; + } + return false; +} + +template<> bool check_bounding_box<2>(const paint_struct_bound_box& initialBBox, + const paint_struct_bound_box& currentBBox) +{ + if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end < currentBBox.y && initialBBox.x_end < currentBBox.x + && !(initialBBox.z < currentBBox.z_end && initialBBox.y >= currentBBox.y_end && initialBBox.x >= currentBBox.x_end)) + { + return true; + } + return false; +} + +template<> bool check_bounding_box<3>(const paint_struct_bound_box& initialBBox, + const paint_struct_bound_box& currentBBox) +{ + if (initialBBox.z_end >= currentBBox.z && initialBBox.y_end < currentBBox.y && initialBBox.x_end >= currentBBox.x + && !(initialBBox.z < currentBBox.z_end && initialBBox.y >= currentBBox.y_end && initialBBox.x < currentBBox.x_end)) + { + return true; + } + return false; +} + +template +static paint_struct * paint_arrange_structs_helper_rotation(paint_struct * ps_next, uint16 quadrantIndex, uint8 flag) { paint_struct * ps; paint_struct * ps_temp; @@ -357,7 +379,6 @@ paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadr } while (ps->quadrant_index <= quadrantIndex + 1); ps = ps_temp; - uint8 rotation = get_current_rotation(); while (true) { while (true) @@ -372,16 +393,7 @@ paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadr ps_next->quadrant_flags &= ~PAINT_QUADRANT_FLAG_IDENTICAL; ps_temp = ps; - const paint_struct_bound_box initialBBox = - { - ps_next->bound_box_x, - ps_next->bound_box_y, - ps_next->bound_box_z, - ps_next->bound_box_x_end, - ps_next->bound_box_y_end, - ps_next->bound_box_z_end - }; - + const paint_struct_bound_box& initialBBox = ps_next->bounds; while (true) { @@ -391,17 +403,9 @@ paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadr if (ps_next->quadrant_flags & PAINT_QUADRANT_FLAG_BIGGER) break; if (!(ps_next->quadrant_flags & PAINT_QUADRANT_FLAG_NEXT)) continue; - const paint_struct_bound_box currentBBox = - { - ps_next->bound_box_x, - ps_next->bound_box_y, - ps_next->bound_box_z, - ps_next->bound_box_x_end, - ps_next->bound_box_y_end, - ps_next->bound_box_z_end - }; + const paint_struct_bound_box& currentBBox = ps_next->bounds; - bool compareResult = is_bbox_intersecting(rotation, initialBBox, currentBBox); + const bool compareResult = check_bounding_box<_TRotation>(initialBBox, currentBBox); if (compareResult) { @@ -417,6 +421,22 @@ paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadr } } +paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadrantIndex, uint8 flag, uint8 rotation) +{ + switch (rotation) + { + case 0: + return paint_arrange_structs_helper_rotation<0>(ps_next, quadrantIndex, flag); + case 1: + return paint_arrange_structs_helper_rotation<1>(ps_next, quadrantIndex, flag); + case 2: + return paint_arrange_structs_helper_rotation<2>(ps_next, quadrantIndex, flag); + case 3: + return paint_arrange_structs_helper_rotation<3>(ps_next, quadrantIndex, flag); + } + return nullptr; +} + /** * * rct2: 0x00688217 @@ -427,6 +447,7 @@ paint_struct paint_session_arrange(paint_session * session) paint_struct * ps = &psHead; ps->next_quadrant_ps = nullptr; uint32 quadrantIndex = session->QuadrantBackIndex; + const uint8 rotation = get_current_rotation(); if (quadrantIndex != UINT32_MAX) { do @@ -439,18 +460,20 @@ paint_struct paint_session_arrange(paint_session * session) { ps = ps_next; ps_next = ps_next->next_quadrant_ps; + } while (ps_next != nullptr); } } while (++quadrantIndex <= session->QuadrantFrontIndex); - paint_struct * ps_cache = paint_arrange_structs_helper(&psHead, session->QuadrantBackIndex & 0xFFFF, PAINT_QUADRANT_FLAG_NEXT); + paint_struct * ps_cache = paint_arrange_structs_helper(&psHead, session->QuadrantBackIndex & 0xFFFF, PAINT_QUADRANT_FLAG_NEXT, rotation); quadrantIndex = session->QuadrantBackIndex; while (++quadrantIndex < session->QuadrantFrontIndex) { - ps_cache = paint_arrange_structs_helper(ps_cache, quadrantIndex & 0xFFFF, 0); + ps_cache = paint_arrange_structs_helper(ps_cache, quadrantIndex & 0xFFFF, 0, rotation); } } + return psHead; } @@ -535,65 +558,65 @@ static void paint_ps_image_with_bounding_boxes(rct_drawpixelinfo * dpi, paint_st const LocationXYZ16 frontTop = { - (sint16)ps->bound_box_x_end, - (sint16)ps->bound_box_y_end, - (sint16)ps->bound_box_z_end + (sint16)ps->bounds.x_end, + (sint16)ps->bounds.y_end, + (sint16)ps->bounds.z_end }; const LocationXY16 screenCoordFrontTop = coordinate_3d_to_2d(&frontTop, rotation); const LocationXYZ16 frontBottom = { - (sint16)ps->bound_box_x_end, - (sint16)ps->bound_box_y_end, - (sint16)ps->bound_box_z + (sint16)ps->bounds.x_end, + (sint16)ps->bounds.y_end, + (sint16)ps->bounds.z }; const LocationXY16 screenCoordFrontBottom = coordinate_3d_to_2d(&frontBottom, rotation); const LocationXYZ16 leftTop = { - (sint16)ps->bound_box_x, - (sint16)ps->bound_box_y_end, - (sint16)ps->bound_box_z_end + (sint16)ps->bounds.x, + (sint16)ps->bounds.y_end, + (sint16)ps->bounds.z_end }; const LocationXY16 screenCoordLeftTop = coordinate_3d_to_2d(&leftTop, rotation); const LocationXYZ16 leftBottom = { - (sint16)ps->bound_box_x, - (sint16)ps->bound_box_y_end, - (sint16)ps->bound_box_z + (sint16)ps->bounds.x, + (sint16)ps->bounds.y_end, + (sint16)ps->bounds.z }; const LocationXY16 screenCoordLeftBottom = coordinate_3d_to_2d(&leftBottom, rotation); const LocationXYZ16 rightTop = { - (sint16)ps->bound_box_x_end, - (sint16)ps->bound_box_y, - (sint16)ps->bound_box_z_end + (sint16)ps->bounds.x_end, + (sint16)ps->bounds.y, + (sint16)ps->bounds.z_end }; const LocationXY16 screenCoordRightTop = coordinate_3d_to_2d(&rightTop, rotation); const LocationXYZ16 rightBottom = { - (sint16)ps->bound_box_x_end, - (sint16)ps->bound_box_y, - (sint16)ps->bound_box_z + (sint16)ps->bounds.x_end, + (sint16)ps->bounds.y, + (sint16)ps->bounds.z }; const LocationXY16 screenCoordRightBottom = coordinate_3d_to_2d(&rightBottom, rotation); const LocationXYZ16 backTop = { - (sint16)ps->bound_box_x, - (sint16)ps->bound_box_y, - (sint16)ps->bound_box_z_end + (sint16)ps->bounds.x, + (sint16)ps->bounds.y, + (sint16)ps->bounds.z_end }; const LocationXY16 screenCoordBackTop = coordinate_3d_to_2d(&backTop, rotation); const LocationXYZ16 backBottom = { - (sint16)ps->bound_box_x, - (sint16)ps->bound_box_y, - (sint16)ps->bound_box_z + (sint16)ps->bounds.x, + (sint16)ps->bounds.y, + (sint16)ps->bounds.z }; const LocationXY16 screenCoordBackBottom = coordinate_3d_to_2d(&backBottom, rotation); @@ -805,12 +828,12 @@ extern "C" coord_3d.x += session->SpritePosition.x; coord_3d.y += session->SpritePosition.y; - ps->bound_box_x_end = coord_3d.x + boundBox.x; - ps->bound_box_y_end = coord_3d.y + boundBox.y; + ps->bounds.x_end = coord_3d.x + boundBox.x; + ps->bounds.y_end = coord_3d.y + boundBox.y; // TODO: check whether this is right. edx is ((bound_box_length_z + z_offset) << 16 | z_offset) - ps->bound_box_z = coord_3d.z; - ps->bound_box_z_end = (boundBox.z + coord_3d.z); + ps->bounds.z = coord_3d.z; + ps->bounds.z_end = (boundBox.z + coord_3d.z); LocationXY16 map = coordinate_3d_to_2d(&coord_3d, rotation); @@ -831,8 +854,8 @@ extern "C" if (bottom >= (dpi->y + dpi->height)) return nullptr; ps->flags = 0; - ps->bound_box_x = coord_3d.x; - ps->bound_box_y = coord_3d.y; + ps->bounds.x = coord_3d.x; + ps->bounds.y = coord_3d.y; ps->attached_ps = nullptr; ps->var_20 = nullptr; ps->sprite_type = session->InteractionType; @@ -907,8 +930,8 @@ extern "C" LocationXY16 attach = { - (sint16)ps->bound_box_x, - (sint16)ps->bound_box_y + (sint16)ps->bounds.x, + (sint16)ps->bounds.y }; rotate_map_coordinates(&attach.x, &attach.y, rotation); diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index 60f9efa14f..528e282be5 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -51,6 +51,15 @@ enum PAINT_QUADRANT_FLAGS { PAINT_QUADRANT_FLAG_NEXT = (1 << 1), }; +typedef struct paint_struct_bound_box { + uint16 x; + uint16 y; + uint16 z; + uint16 x_end; + uint16 y_end; + uint16 z_end; +} paint_struct_bound_box; + /* size 0x34 */ struct paint_struct { uint32 image_id; // 0x00 @@ -59,12 +68,7 @@ struct paint_struct { // If masked image_id is masked_id uint32 colour_image_id; // 0x04 }; - uint16 bound_box_x; // 0x08 - uint16 bound_box_y; // 0x0A - uint16 bound_box_z; // 0x0C - uint16 bound_box_z_end; // 0x0E - uint16 bound_box_x_end; // 0x10 - uint16 bound_box_y_end; // 0x12 + paint_struct_bound_box bounds; // 0x08 uint16 x; // 0x14 uint16 y; // 0x16 uint16 quadrant_index; @@ -114,15 +118,6 @@ typedef struct sprite_bb { LocationXYZ16 bb_size; } sprite_bb; -typedef struct paint_struct_bound_box { - uint16 x; - uint16 y; - uint16 z; - uint16 x_end; - uint16 y_end; - uint16 z_end; -} paint_struct_bound_box; - enum PAINT_STRUCT_FLAGS { PAINT_STRUCT_FLAG_IS_MASKED = (1 << 0) }; @@ -209,7 +204,7 @@ paint_session * paint_session_alloc(rct_drawpixelinfo * dpi); void paint_session_free(paint_session *); void paint_session_generate(paint_session * session); paint_struct paint_session_arrange(paint_session * session); -paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadrantIndex, uint8 flag); +paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 quadrantIndex, uint8 flag, uint8 rotation); void paint_draw_structs(rct_drawpixelinfo * dpi, paint_struct * ps, uint32 viewFlags); void paint_draw_money_structs(rct_drawpixelinfo * dpi, paint_string_struct * ps);