A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
KColData.hh
1#pragma once
2
4
5#include <egg/math/BoundBox.hh>
6#include <egg/math/Matrix.hh>
7
8// Credit: em-eight/mkw
9// Credit: stblr/Hanachan
10
11namespace Kinoko::Field {
12
14 EGG::BoundBox3f bbox;
15 EGG::Vector3f tangentOff;
16
17 void update(const EGG::Vector3f &offset) {
18 bbox.min = bbox.min.minimize(offset);
19 bbox.max = bbox.max.maximize(offset);
20 }
21};
22
24 EGG::BoundBox3f bbox;
25 EGG::Vector3f tangentOff;
26 EGG::Vector3f floorNrm;
27 EGG::Vector3f wallNrm;
28 EGG::Vector3f roadVelocity;
29 f32 floorDist;
30 f32 wallDist;
31 f32 movingFloorDist;
32 f32 perpendicularity;
33
34 void updateFloor(f32 dist, const EGG::Vector3f &fnrm) {
35 if (dist > floorDist) {
36 floorDist = dist;
37 floorNrm = fnrm;
38 }
39 }
40
41 void updateWall(f32 dist, const EGG::Vector3f &fnrm) {
42 if (dist > wallDist) {
43 wallDist = dist;
44 wallNrm = fnrm;
45 }
46 }
47
48 void reset() {
49 bbox.setZero();
50 movingFloorDist = -std::numeric_limits<f32>::min();
51 wallDist = -std::numeric_limits<f32>::min();
52 floorDist = -std::numeric_limits<f32>::min();
53 perpendicularity = 0.0f;
54 }
55
56 void update(f32 now_dist, const EGG::Vector3f &offset, const EGG::Vector3f &fnrm,
57 u32 kclAttributeTypeBit);
58 void transformInfo(CollisionInfo &rhs, const EGG::Matrix34f &mtx, const EGG::Vector3f &v);
59};
60
63class KColData {
64public:
65 enum class CollisionCheckType {
66 Edge,
67 Plane,
68 Movement,
69 };
70
71 struct KCollisionPrism {
72 KCollisionPrism();
73 KCollisionPrism(f32 height, u16 posIndex, u16 faceNormIndex, u16 edge1NormIndex,
74 u16 edge2NormIndex, u16 edge3NormIndex, u16 attribute);
75
76 f32 height;
77 u16 pos_i;
78 u16 fnrm_i;
79 u16 enrm1_i;
80 u16 enrm2_i;
81 u16 enrm3_i;
82 u16 attribute;
83 };
84 STATIC_ASSERT(sizeof(KCollisionPrism) == 0x10);
85
98 STATIC_ASSERT(sizeof(KCollisionPrismGeometry) == 0x40);
99
100 KColData(const void *file);
101 ~KColData();
102
103 void narrowScopeLocal(const EGG::Vector3f &pos, f32 radius, KCLTypeMask mask);
104 void narrowPolygon_EachBlock(const u16 *prismArray);
105
106 void computeBBox();
107 [[nodiscard]] bool checkPointCollision(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut);
108 [[nodiscard]] bool checkSphereCollision(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut);
109 [[nodiscard]] bool checkSphere(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut);
110 [[nodiscard]] bool checkSphereSingle(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut);
111
112 void lookupPoint(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos, KCLTypeMask typeMask);
113 void lookupSphere(f32 radius, const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
114 KCLTypeMask typeMask);
115 void lookupSphereCached(const EGG::Vector3f &p1, const EGG::Vector3f &p2, u32 typeMask,
116 f32 radius);
117
118 [[nodiscard]] const u16 *searchBlock(const EGG::Vector3f &pos);
119
121 [[nodiscard]] const EGG::BoundBox3f &bbox() const {
122 return m_bbox;
123 }
124
125 [[nodiscard]] u16 prismCache(u32 idx) const {
126 return m_prismCache[idx];
127 }
129
130 [[nodiscard]] static EGG::Vector3f GetVertex(f32 height, const EGG::Vector3f &vertex1,
131 const EGG::Vector3f &fnrm, const EGG::Vector3f &enrm3, const EGG::Vector3f &enrm);
132
133private:
135
136 template <CollisionCheckType Type>
137 [[nodiscard]] bool checkCollision(u16 prismIdx, f32 *distOut, EGG::Vector3f *fnrmOut,
138 u16 *flagsOut);
139
140 [[nodiscard]] bool checkPointCollision(u16 prismIdx, f32 *distOut, EGG::Vector3f *fnrmOut,
141 u16 *flagsOut, bool movement);
142 [[nodiscard]] bool checkSphereMovement(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *attributeOut);
143 [[nodiscard]] bool checkPointMovement(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *attributeOut);
144 [[nodiscard]] bool checkPoint(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *attributeOut);
145
146 const void *m_posData;
147 const void *m_nrmData;
148 const void *m_prismData;
149 const void *m_blockData;
150 f32 m_prismThickness;
151 EGG::Vector3f m_areaMinPos;
159 EGG::Vector3f m_pos;
160 EGG::Vector3f m_prevPos;
161 EGG::Vector3f m_movement;
162 f32 m_radius;
163 KCLTypeMask m_typeMask;
164 const u16 *m_prismIter;
165 EGG::BoundBox3f m_bbox;
166 std::array<u16, 256> m_prismCache;
167 u16 *m_prismCacheTop;
168 u16 *m_cachedPrismArray;
169 EGG::Vector3f m_cachedPos;
170 f32 m_cachedRadius;
171
175
180};
181
182} // namespace Kinoko::Field
A 3 x 4 matrix.
Definition Matrix.hh:10
void narrowPolygon_EachBlock(const u16 *prismArray)
Definition KColData.cc:73
void lookupSphere(f32 radius, const EGG::Vector3f &pos, const EGG::Vector3f &prevPos, KCLTypeMask typeMask)
Sets members in preparation of a subsequent sphere collision check call.
Definition KColData.cc:190
u32 m_areaYWidthMask
The y dimension of the octree's bounding box.
Definition KColData.hh:153
owning_span< u16 > m_prismAttributes
One-indexed array of each prism's KCL attribute.
Definition KColData.hh:179
const u16 * searchBlock(const EGG::Vector3f &pos)
Finds the data block corresponding to the provided position.
Definition KColData.cc:224
bool checkSphere(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut)
Iterates the list of looked-up triangles to see if we are colliding.
Definition KColData.cc:128
u32 m_areaXWidthMask
The x dimension of the octree's bounding box.
Definition KColData.hh:152
bool checkSphereMovement(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *attributeOut)
Iterates the local data block to check for directional collision.
Definition KColData.cc:604
static EGG::Vector3f GetVertex(f32 height, const EGG::Vector3f &vertex1, const EGG::Vector3f &fnrm, const EGG::Vector3f &enrm3, const EGG::Vector3f &enrm)
Computes a prism vertex based off of the triangle's normal vectors.
Definition KColData.cc:282
u32 m_areaXBlocksShift
Used to initialize octree navigation.
Definition KColData.hh:156
u32 m_blockWidthShift
Used to initialize octree navigation.
Definition KColData.hh:155
f32 m_sphereRadius
Clamps the sphere we check collision against.
Definition KColData.hh:158
owning_span< KCollisionPrismGeometry > m_prismGeometry
One-indexed array of each prism's geometry.
Definition KColData.hh:174
bool checkCollision(u16 prismIdx, f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut)
This is a combination of the three collision checks in the base game.
Definition KColData.cc:349
void lookupPoint(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos, KCLTypeMask typeMask)
Sets members in preparation of a subsequent point collision check call.
Definition KColData.cc:179
void computeBBox()
Calculates a EGG::BoundBox3f that describes the boundary of the track's KCL.
Definition KColData.cc:90
u32 m_areaZWidthMask
The z dimension of the octree's bounding box.
Definition KColData.hh:154
u32 m_areaXYBlocksShift
Used to initialize octree navigation.
Definition KColData.hh:157
void preloadPrismGeometry()
Resolves each prism's vertex, height, and normal indices into a contiguous struct.
Definition KColData.cc:295
A contiguous storage container that manages the lifecycle of a buffer of a given size.
Definition Types.hh:32
Pertains to collision.
A representation of a bounding cuboid.
Definition BoundBox.hh:37
A 3D float vector.
Definition Vector.hh:107
constexpr Vector3f minimize(const Vector3f &rhs) const
Returns a vector whose elements are the min of the elements of both vectors.
Definition Vector.hh:327
constexpr Vector3f maximize(const Vector3f &rhs) const
Returns a vector whose elements are the max of the elements of both vectors.
Definition Vector.hh:315
Stores the vertex, height and normals of a collision prism.
Definition KColData.hh:90
EGG::Vector3f vtx
The first vertex of the tri.
Definition KColData.hh:91
EGG::Vector3f enrm2
The second edge's normal.
Definition KColData.hh:93
EGG::Vector3f enrm1
The first edge's normal.
Definition KColData.hh:92
EGG::Vector3f enrm3
The third edge's normal.
Definition KColData.hh:94