1#include "Library/Area/AreaShape.h"
2
3#include <math/seadVector.h>
4
5#include "Library/Area/AreaShapeCube.h"
6#include "Library/Area/AreaShapeCylinder.h"
7#include "Library/Area/AreaShapeInfinite.h"
8#include "Library/Area/AreaShapeOval.h"
9#include "Library/Math/MathUtil.h"
10#include "Library/Matrix/MatrixUtil.h"
11
12namespace al {
13
14AreaShape::AreaShape() {}
15
16void AreaShape::setBaseMtxPtr(const sead::Matrix34f* baseMtxPtr) {
17 mBaseMtxPtr = baseMtxPtr;
18}
19
20void AreaShape::setScale(const sead::Vector3f& scale) {
21 mScale = scale;
22}
23
24bool AreaShape::calcLocalPos(sead::Vector3f* localPos, const sead::Vector3f& trans) const {
25 if (isNearZero(value: mScale.x, tolerance: 0.001))
26 return false;
27 if (isNearZero(value: mScale.y, tolerance: 0.001))
28 return false;
29 if (isNearZero(value: mScale.z, tolerance: 0.001))
30 return false;
31
32 if (mBaseMtxPtr)
33 calcMtxLocalTrans(localPos, *mBaseMtxPtr, trans);
34 else
35 localPos->e = trans.e;
36
37 f32 localX = localPos->x;
38 localPos->x = localX / mScale.x;
39 f32 localY = localPos->y;
40 localPos->y = localY / mScale.y;
41 f32 localZ = localPos->z;
42 localPos->z = localZ / mScale.z;
43
44 return true;
45}
46
47bool AreaShape::calcWorldPos(sead::Vector3f* worldPos, const sead::Vector3f& trans) const {
48 if (isNearZero(value: mScale.x))
49 return false;
50 if (isNearZero(value: mScale.y))
51 return false;
52 if (isNearZero(value: mScale.z))
53 return false;
54
55 worldPos->x = trans.x * mScale.x;
56 worldPos->y = trans.y * mScale.y;
57 worldPos->z = trans.z * mScale.z;
58
59 if (mBaseMtxPtr)
60 worldPos->setMul(m: *mBaseMtxPtr, a: *worldPos);
61
62 return true;
63}
64
65bool AreaShape::calcWorldDir(sead::Vector3f* worldDir, const sead::Vector3f& trans) const {
66 if (isNearZero(value: mScale.x))
67 return false;
68 if (isNearZero(value: mScale.y))
69 return false;
70 if (isNearZero(value: mScale.z))
71 return false;
72
73 worldDir->x = trans.x * mScale.x;
74 worldDir->y = trans.y * mScale.y;
75 worldDir->z = trans.z * mScale.z;
76
77 if (mBaseMtxPtr)
78 worldDir->setRotated(m: *mBaseMtxPtr, a: *worldDir);
79
80 tryNormalizeOrZero(out: worldDir);
81
82 return true;
83}
84
85void AreaShape::calcTrans(sead::Vector3f* trans) const {
86 if (mBaseMtxPtr)
87 mBaseMtxPtr->getTranslation(o&: *trans);
88 else
89 trans->e = sead::Vector3f::zero.e;
90}
91
92template <typename T>
93AreaShape* createAreaShapeFunction() {
94 return new T;
95}
96
97static NameToCreator<AreaShapeCreatorFunction> sAreaShapeEntries[] = {
98 {.name: "AreaCubeBase", .creationFunction: *createAreaShapeFunction<AreaShapeCubeBase>},
99 {.name: "AreaCubeCenter", .creationFunction: createAreaShapeFunction<AreaShapeCubeCenter>},
100 {.name: "AreaCubeTop", .creationFunction: createAreaShapeFunction<AreaShapeCubeTop>},
101 {.name: "AreaSphere", .creationFunction: createAreaShapeFunction<AreaShapeOval>},
102 {.name: "AreaCylinder", .creationFunction: createAreaShapeFunction<AreaShapeCylinderBase>},
103 {.name: "AreaCylinderCenter", .creationFunction: createAreaShapeFunction<AreaShapeCylinderCenter>},
104 {.name: "AreaCylinderTop", .creationFunction: createAreaShapeFunction<AreaShapeCylinderTop>},
105 {.name: "AreaInfinite", .creationFunction: createAreaShapeFunction<AreaShapeInfinite>},
106};
107
108AreaShapeFactory::AreaShapeFactory(const char* factoryName)
109 : Factory<AreaShape* (*)()>(factoryName, sAreaShapeEntries) {}
110
111} // namespace al
112