Cleanup vehicle drawing code part 3 (#16968)

* Cleanup vehicle drawing code part 3

* Create functions to convert between rotation amounts

* Add regions to ease code navigation
This commit is contained in:
spacek531 2022-04-29 23:56:23 -07:00 committed by GitHub
parent c7a26a5921
commit 5659d43f46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 352 additions and 187 deletions

View File

@ -945,8 +945,8 @@ static void WindowRideDrawTabVehicle(rct_drawpixelinfo* dpi, rct_window* w)
auto imageIndex = 32;
if (w->page == WINDOW_RIDE_PAGE_VEHICLE)
imageIndex += w->frame_no;
imageIndex /= (rideVehicleEntry->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES) ? 4 : 2;
imageIndex &= rideVehicleEntry->rotation_frame_mask;
imageIndex = rideVehicleEntry->SpriteByYaw(imageIndex / 2);
imageIndex &= rideVehicleEntry->TabRotationMask;
imageIndex *= rideVehicleEntry->base_num_frames;
imageIndex += rideVehicleEntry->base_image_id;
auto imageId = ImageId(imageIndex, vehicleColour.Body, vehicleColour.Trim, vehicleColour.Tertiary);
@ -2960,10 +2960,8 @@ static void WindowRideVehicleScrollpaint(rct_window* w, rct_drawpixelinfo* dpi,
}
VehicleColour vehicleColour = ride_get_vehicle_colour(ride, vehicleColourIndex);
ImageIndex imageIndex = 16;
if (rideVehicleEntry->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES)
imageIndex /= 2;
imageIndex &= rideVehicleEntry->rotation_frame_mask;
ImageIndex imageIndex = rideVehicleEntry->SpriteByYaw(16);
imageIndex &= rideVehicleEntry->TabRotationMask;
imageIndex *= rideVehicleEntry->base_num_frames;
imageIndex += rideVehicleEntry->base_image_id;
@ -4831,9 +4829,8 @@ static void WindowRideColourScrollpaint(rct_window* w, rct_drawpixelinfo* dpi, i
screenCoords.y += rideVehicleEntry->tab_height;
// Draw the coloured spinning vehicle
ImageIndex imageIndex = (rideVehicleEntry->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES) ? w->frame_no / 4
: w->frame_no / 2;
imageIndex &= rideVehicleEntry->rotation_frame_mask;
ImageIndex imageIndex = rideVehicleEntry->SpriteByYaw(w->frame_no / 2);
imageIndex &= rideVehicleEntry->TabRotationMask;
imageIndex *= rideVehicleEntry->base_num_frames;
imageIndex += rideVehicleEntry->base_image_id;
auto imageId = ImageId(imageIndex, vehicleColour.Body, vehicleColour.Trim, vehicleColour.Tertiary);

View File

@ -0,0 +1,45 @@
/*****************************************************************************
* Copyright (c) 2014-2022 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include <cstdint>
namespace OpenRCT2::Entity::Yaw
{
constexpr const int32_t BaseRotation = 32;
// smallest precision is 4 frames
constexpr const uint8_t PrecisionOffset[] = { 3, 2, 1, 0, 0, 0, 0, 0 };
constexpr int32_t YawTo4(int32_t yaw)
{
return yaw >> 3;
}
constexpr int32_t YawTo8(int32_t yaw)
{
return yaw >> 2;
}
constexpr int32_t YawTo16(int32_t yaw)
{
return yaw >> 1;
}
constexpr int32_t YawTo32(int32_t yaw)
{
return yaw;
}
constexpr int32_t YawToPrecision(int32_t yaw, uint8_t precision)
{
return yaw >> PrecisionOffset[precision];
}
constexpr uint8_t NumSpritesPrecision(uint8_t precision)
{
return 4 << precision;
}
} // namespace OpenRCT2::Entity::Yaw

View File

@ -222,6 +222,7 @@
<ClInclude Include="entity\PatrolArea.h" />
<ClInclude Include="entity\Peep.h" />
<ClInclude Include="entity\Staff.h" />
<ClInclude Include="entity\Yaw.hpp" />
<ClInclude Include="FileClassifier.h" />
<ClInclude Include="Game.h" />
<ClInclude Include="GameState.h" />
@ -957,4 +958,4 @@
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -217,8 +217,7 @@ void RideObject::Load()
if (vehicleEntry->PaintStyle != VEHICLE_VISUAL_RIVER_RAPIDS)
{
const auto numRotationFrames = vehicleEntry->GetNumRotationFrames();
vehicleEntry->NumRotationFrames = numRotationFrames;
const auto numRotationFrames = vehicleEntry->NumRotationFrames();
uint32_t b = vehicleEntry->base_num_frames * numRotationFrames;
image_index += b;
@ -435,7 +434,7 @@ void RideObject::SetRepositoryItem(ObjectRepositoryItem* item) const
void RideObject::ReadLegacyVehicle(
[[maybe_unused]] IReadObjectContext* context, IStream* stream, rct_ride_entry_vehicle* vehicle)
{
vehicle->rotation_frame_mask = stream->ReadValue<uint16_t>();
vehicle->TabRotationMask = stream->ReadValue<uint16_t>();
stream->Seek(2 * 1, STREAM_SEEK_CURRENT);
vehicle->spacing = stream->ReadValue<uint32_t>();
vehicle->car_mass = stream->ReadValue<uint16_t>();
@ -463,6 +462,12 @@ void RideObject::ReadLegacyVehicle(
vehicle->draw_order = stream->ReadValue<uint8_t>();
vehicle->num_vertical_frames_override = stream->ReadValue<uint8_t>();
stream->Seek(4, STREAM_SEEK_CURRENT);
vehicle->SpriteYawPrecision = 3;
if (vehicle->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES)
vehicle->SpriteYawPrecision = 2;
if (vehicle->flags & VEHICLE_SPRITE_FLAG_USE_4_ROTATION_FRAMES)
vehicle->SpriteYawPrecision = 0;
}
uint8_t RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle* vehicleEntry)
@ -729,7 +734,8 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(json_t& jCar)
Guard::Assert(jCar.is_object(), "RideObject::ReadJsonCar expects parameter jCar to be object");
rct_ride_entry_vehicle car = {};
car.rotation_frame_mask = Json::GetNumber<uint16_t>(jCar["rotationFrameMask"]);
car.TabRotationMask = Json::GetNumber<uint16_t>(jCar["rotationFrameMask"]);
car.SpriteYawPrecision = 3;
car.spacing = Json::GetNumber<uint32_t>(jCar["spacing"]);
car.car_mass = Json::GetNumber<uint16_t>(jCar["mass"]);
car.tab_height = Json::GetNumber<int8_t>(jCar["tabOffset"]);
@ -820,8 +826,11 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(json_t& jCar)
{ "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS },
{ "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION },
{ "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL },
{ "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_USE_4_ROTATION_FRAMES },
});
if (jFrames.contains("VEHICLE_SPRITE_FLAG_15") && Json::GetBoolean(jFrames, "VEHICLE_SPRITE_FLAG_15"))
{
car.SpriteYawPrecision = 0;
}
}
car.flags |= Json::GetFlags<uint32_t>(
@ -837,7 +846,6 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(json_t& jCar)
{ "hasDodgemInUseLights", VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS },
{ "hasAdditionalColour2", VEHICLE_ENTRY_FLAG_ENABLE_TERNARY_COLOUR },
{ "recalculateSpriteBounds", VEHICLE_ENTRY_FLAG_RECALCULATE_SPRITE_BOUNDS },
{ "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES },
{ "overrideNumberOfVerticalFrames", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES },
{ "spriteBoundsIncludeInvertedSet", VEHICLE_ENTRY_FLAG_SPRITE_BOUNDS_INCLUDE_INVERTED_SET },
{ "hasAdditionalSpinningFrames", VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES },
@ -890,6 +898,8 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(json_t& jCar)
{ "VEHICLE_ENTRY_FLAG_GO_KART", VEHICLE_ENTRY_FLAG_GO_KART },
{ "VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT", VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT },
});
if (jCar.contains("VEHICLE_ENTRY_FLAG_11") && Json::GetBoolean(jCar, "VEHICLE_ENTRY_FLAG_11"))
car.SpriteYawPrecision = 2;
return car;
}

View File

@ -121,9 +121,9 @@
// clang-format off
const rct_ride_entry_vehicle CableLiftVehicle = {
/* .rotation_frame_mask = */ 31,
/* .num_vertical_frames = */ 0,
/* .num_horizontal_frames = */ 0,
/* .TabRotationMask = */ 31,
/* .SpriteYawPrecision = */ 3,
/* .pad_03 = */ 0,
/* .spacing = */ 0,
/* .car_mass = */ 0,
/* .tab_height = */ 0,

View File

@ -20,6 +20,7 @@
#include "../core/Memory.hpp"
#include "../entity/EntityRegistry.h"
#include "../entity/Particle.h"
#include "../entity/Yaw.hpp"
#include "../interface/Viewport.h"
#include "../localisation/Formatter.h"
#include "../localisation/Localisation.h"
@ -9871,3 +9872,13 @@ void Vehicle::Serialise(DataSerialiser& stream)
stream << BoatLocation;
stream << IsCrashedVehicle;
}
uint32_t rct_ride_entry_vehicle::NumRotationFrames() const
{
return OpenRCT2::Entity::Yaw::NumSpritesPrecision(SpriteYawPrecision);
}
int32_t rct_ride_entry_vehicle::SpriteByYaw(int32_t yaw) const
{
return OpenRCT2::Entity::Yaw::YawToPrecision(yaw, SpriteYawPrecision);
}

View File

@ -11,6 +11,7 @@
#include "../audio/AudioMixer.h"
#include "../common.h"
#include "../entity/Yaw.hpp"
#include <array>
#include <vector>
@ -92,9 +93,9 @@ enum : uint32_t
*/
struct rct_ride_entry_vehicle
{
uint16_t rotation_frame_mask;
uint8_t NumRotationFrames;
uint8_t num_horizontal_frames; // Appears to be unused, except as a temporary variable in RCT2 (not needed for OpenRCT2)
uint16_t TabRotationMask;
uint8_t SpriteYawPrecision;
uint8_t pad_03;
uint32_t spacing;
uint16_t car_mass;
int8_t tab_height;
@ -144,13 +145,6 @@ struct rct_ride_entry_vehicle
std::vector<std::array<CoordsXY, 3>> peep_loading_waypoints = {};
std::vector<int8_t> peep_loading_positions = {};
constexpr uint32_t GetNumRotationFrames() const
{
if (flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES)
return 16;
if (sprite_flags & VEHICLE_SPRITE_FLAG_USE_4_ROTATION_FRAMES)
return 4;
return 32;
}
uint32_t NumRotationFrames() const;
int32_t SpriteByYaw(int32_t yaw) const;
};

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ static uint32_t SubmarineVehicleGetBaseImageId(
{
if ((vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION) && !(imageDirection & 3))
{
result /= 8;
result = OpenRCT2::Entity::Yaw::YawTo4(result);
result += ((vehicle->restraints_position - 64) / 64) * 4;
result *= vehicleEntry->base_num_frames;
result += vehicleEntry->restraint_image_id;
@ -32,17 +32,8 @@ static uint32_t SubmarineVehicleGetBaseImageId(
}
else
{
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES)
{
result /= 2;
}
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_USE_4_ROTATION_FRAMES)
{
result /= 8;
}
result *= vehicleEntry->base_num_frames;
result += vehicleEntry->base_image_id;
result += vehicle->SwingSprite;
result = (vehicleEntry->SpriteByYaw(result) * vehicleEntry->base_num_frames) + vehicleEntry->base_image_id
+ vehicle->SwingSprite;
}
return result;
}
@ -66,7 +57,7 @@ void vehicle_visual_submarine(
imageId1 = ImageId(baseImageId + 1).WithRemap(FilterPaletteID::Palette44);
}
const auto& bb = VehicleBoundboxes[vehicleEntry->draw_order][imageDirection / 2];
const auto& bb = VehicleBoundboxes[vehicleEntry->draw_order][OpenRCT2::Entity::Yaw::YawTo16(imageDirection)];
PaintAddImageAsParent(
session, imageId0, { 0, 0, z }, { bb.length_x, bb.length_y, bb.length_z },
{ bb.offset_x, bb.offset_y, bb.offset_z + z });

View File

@ -208,7 +208,7 @@ namespace OpenRCT2::Scripting
auto entry = GetEntry();
if (entry != nullptr)
{
return entry->rotation_frame_mask;
return entry->TabRotationMask;
}
return 0;
}
@ -220,11 +220,6 @@ namespace OpenRCT2::Scripting
uint8_t numHorizontalFrames_get() const
{
auto entry = GetEntry();
if (entry != nullptr)
{
return entry->num_horizontal_frames;
}
return 0;
}