1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-28 09:14:58 +01:00

Use templates for bounding box test, better branch prediction

This commit is contained in:
ZehMatt
2018-01-07 00:03:17 +01:00
committed by Richard Jenkins
parent d25c46ef93
commit df9854813f
2 changed files with 121 additions and 103 deletions

View File

@@ -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<uint8_t> 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<uint8 _TRotation>
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);

View File

@@ -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);