1#include "MapdataArea.hh"
3#include "game/system/CourseMap.hh"
8MapdataAreaBase::MapdataAreaBase(
const SData *data, s16 index) : m_rawData(data), m_index(index) {
9 EGG::RamStream stream = EGG::RamStream(data,
10 CourseMap::Instance()->version() > 2200 ?
sizeof(SData) :
sizeof(SData) - 4);
13 m_sqBoundingSphereRadius = 0.0f;
14 m_ellipseAspectRatio = 0.0f;
15 m_ellipseRadiusSq = 0.0f;
16 m_dimensions = EGG::Vector3f::zero;
17 m_right = EGG::Vector3f::zero;
18 m_up = EGG::Vector3f::zero;
19 m_forward = EGG::Vector3f::zero;
22void MapdataAreaBase::read(EGG::Stream &stream) {
24 m_type =
static_cast<Type
>(stream.read_s8());
26 m_priority = stream.read_u8();
27 m_position.read(stream);
28 m_rotation.read(stream);
31 for (
auto ¶m : m_params) {
32 param = stream.read_s16();
35 if (CourseMap::Instance()->version() > 2200) {
36 m_railId = stream.read_s8();
41MapdataPointInfo *MapdataAreaBase::getPointInfo()
const {
43 auto *courseMap = CourseMap::Instance();
44 if (courseMap->version() < 2200) {
48 return courseMap->getPointInfo(m_railId);
52MapdataAreaBox::MapdataAreaBox(
const SData *data, s16 index) : MapdataAreaBase(data, index) {
53 m_dimensions.x = 0.5f * (10000.0f * m_scale.x);
54 m_dimensions.y = 10000.0f * m_scale.y;
55 m_dimensions.z = 0.5f * (10000.0f * m_scale.z);
57 m_ellipseAspectRatio = 0.0f;
58 m_ellipseRadiusSq = 0.0f;
59 m_sqBoundingSphereRadius = m_dimensions.squaredLength();
61 EGG::Quatf rotation = EGG::Quatf::FromRPY(DEG2RAD * m_rotation.x, DEG2RAD * m_rotation.y,
62 DEG2RAD * m_rotation.z);
64 m_right = rotation.rotateVector(EGG::Vector3f::ex);
65 m_up = rotation.rotateVector(EGG::Vector3f::ey);
66 m_forward = rotation.rotateVector(EGG::Vector3f::ez);
70bool MapdataAreaBox::testImpl(
const EGG::Vector3f &pos)
const {
71 EGG::Vector3f relPos = pos - m_position;
73 f32 u = relPos.dot(m_up);
74 if (u > m_dimensions.y || u < 0.0f) {
78 f32 r = relPos.dot(m_right);
79 if (r > m_dimensions.x || r < -m_dimensions.x) {
83 f32 f = relPos.dot(m_forward);
84 if (f > m_dimensions.z || f < -m_dimensions.z) {
92MapdataAreaCylinder::MapdataAreaCylinder(
const SData *data, s16 index)
93 : MapdataAreaBase(data, index) {
94 m_dimensions = m_scale * 5000.0f;
95 m_ellipseRadiusSq = m_dimensions.x * m_dimensions.x;
96 m_sqBoundingSphereRadius = m_dimensions.x * m_dimensions.x + m_dimensions.z * m_dimensions.z;
97 m_ellipseAspectRatio = m_scale.x / m_scale.z;
99 EGG::Quatf rotation = EGG::Quatf::FromRPY(DEG2RAD * m_rotation.x, DEG2RAD * m_rotation.y,
100 DEG2RAD * m_rotation.z);
102 m_right = rotation.rotateVector(EGG::Vector3f::ex);
103 m_up = rotation.rotateVector(EGG::Vector3f::ey);
104 m_forward = rotation.rotateVector(EGG::Vector3f::ez);
108bool MapdataAreaCylinder::testImpl(
const EGG::Vector3f &pos)
const {
109 EGG::Vector3f relPos = pos - m_position;
111 if (relPos.dot(m_up) > m_dimensions.y) {
115 f32 f = m_ellipseAspectRatio * relPos.dot(m_forward);
116 f32 r = relPos.dot(m_right);
117 if (r * r + f * f < m_ellipseRadiusSq) {
125MapdataAreaAccessor::MapdataAreaAccessor(
const MapSectionHeader *header)
126 : MapdataAccessorBase<MapdataAreaBase, MapdataAreaBase::SData>(header) {
127 init(
reinterpret_cast<const MapdataAreaBase::SData *
>(m_sectionHeader + 1),
128 parse<u16>(m_sectionHeader->count));
130 m_sortedEntries = owning_span<MapdataAreaBase *>(m_entryCount);
134MapdataAreaAccessor::~MapdataAreaAccessor() =
default;
136void MapdataAreaAccessor::init(
const MapdataAreaBase::SData *start, u16 count) {
138 m_entryCount = count;
139 m_entries =
new MapdataAreaBase *[count];
142 for (u16 i = 0; i < count; ++i) {
144 const MapdataAreaBase::SData *data = CourseMap::Instance()->version() > 2200 ?
146 reinterpret_cast<const MapdataAreaBase::SData *
>(
147 reinterpret_cast<uintptr_t
>(start) +
148 i * (
sizeof(MapdataAreaBase::SData) - 4));
151 MapdataAreaBase::Shape shape =
static_cast<MapdataAreaBase::Shape
>(data->shape);
154 case MapdataAreaBase::Shape::Box:
155 m_entries[i] =
new MapdataAreaBox(data, i);
157 case MapdataAreaBase::Shape::Cylinder:
158 m_entries[i] =
new MapdataAreaCylinder(data, i);
161 PANIC(
"Invalid area shape!");
168void MapdataAreaAccessor::sort() {
169 for (
size_t i = 0; i < m_entryCount; ++i) {
170 m_sortedEntries[i] = get(i);
173 for (
size_t i = 1; i < m_entryCount; ++i) {
175 for (; j > 0 && m_sortedEntries[j - 1]->priority() < m_sortedEntries[i]->priority(); --j) {
176 m_sortedEntries[j] = m_sortedEntries[j - 1];
High-level handling for generic system operations, such as input reading, race configuration,...