1#include "ObjectPoihana.hh"
3#include "game/field/CollisionDirector.hh"
9 : StateManager(this, {}), ObjectCollidable(params), m_walkState(WalkState::NeedTarget),
10 m_heightOffset(0.0f), m_radius(150.0f), m_targetPos(EGG::Vector3f::zero) {}
13ObjectPoihanaBase::~ObjectPoihanaBase() =
default;
16void ObjectPoihanaBase::init() {
17 m_workMat = EGG::Matrix34f::ident;
21 m_curRot = EGG::Vector3f::ey;
22 m_up = EGG::Vector3f::ez;
23 m_floorNrm = EGG::Vector3f::ey;
24 m_walkState = WalkState::NeedTarget;
25 m_workMat.setBase(3, m_pos);
30 : StateManager(this, STATE_ENTRIES), ObjectPoihanaBase(params) {}
33ObjectPoihana::~ObjectPoihana() =
default;
36void ObjectPoihana::init() {
37 ObjectPoihanaBase::init();
40 m_dir = EGG::Vector3f::ez;
41 m_targetVel.setZero();
44 m_heightOffset = -160.0f;
49void ObjectPoihana::calcCurRot(f32 t) {
50 m_curRot = Interpolate(t, m_curRot, m_floorNrm);
51 if (m_curRot.squaredLength() > std::numeric_limits<f32>::epsilon()) {
52 m_curRot.normalise2();
54 m_curRot = EGG::Vector3f::ey;
59void ObjectPoihana::calcOrthonormalBasis() {
63 if (side.
squaredLength() <= std::numeric_limits<f32>::epsilon()) {
64 side = EGG::Vector3f::ex;
70 m_workMat.setBase(0, side);
71 m_workMat.setBase(1, m_curRot);
72 m_workMat.setBase(2, up);
76void ObjectPoihana::calcCollision() {
80 bool hasCol = CollisionDirector::Instance()->checkSphereFull(m_radius, pos, EGG::Vector3f::inf,
81 KCL_TYPE_64EBDFFF, &info,
nullptr, 0);
87 m_workMat.setBase(3, m_workMat.base(3) + info.tangentOff);
89 if (info.wallDist > -std::numeric_limits<f32>::min()) {
90 m_extVel += Project(m_extVel, info.wallNrm) * -2.0f;
93 if (info.floorDist > -std::numeric_limits<f32>::min()) {
94 m_floorNrm = info.floorNrm;
100void ObjectPoihana::calcStep() {
101 constexpr f32 COARSE_SCALAR = 0.1f;
102 constexpr f32 FINE_SCALAR = 100.0f;
103 constexpr f32 CLAMP = 0.5f;
104 constexpr s32 MOD = 100;
105 constexpr f32 INV_MOD = 1.0f /
static_cast<f32
>(MOD);
106 constexpr f32 SPEED = 7.0f;
107 constexpr f32 RAND_POS_MAX = 2000.0f;
108 constexpr f32 RAND_POS_MIN = 1000.0f;
109 constexpr f32 RAND_POS_RANGE = RAND_POS_MAX - RAND_POS_MIN;
110 constexpr f32 TARGET_DIST_THRESHOLD = 200.0f;
112 if (m_walkState == WalkState::NeedTarget) {
115 f32 sum = EGG::Mathf::abs(pos.x + pos.z);
116 s32 tmp1 =
static_cast<s32
>(COARSE_SCALAR * sum);
117 s32 tmp2 =
static_cast<s32
>(FINE_SCALAR * sum);
118 s32 remSum = (tmp1 % MOD) + (tmp2 % MOD);
119 f32 x = INV_MOD *
static_cast<f32
>(remSum % MOD);
120 f32 z = INV_MOD *
static_cast<f32
>(remSum * 7 % MOD);
125 f32 scalar = RAND_POS_RANGE * (INV_MOD *
static_cast<f32
>(remSum * 3 % MOD)) + RAND_POS_MIN;
126 m_targetPos = m_initPos + dir * scalar;
130 m_walkState = WalkState::HasTarget;
133 if (m_walkState == WalkState::HasTarget) {
138 if (delta.
squaredLength() > std::numeric_limits<f32>::epsilon()) {
142 m_targetVel = delta * SPEED;
144 if (len < TARGET_DIST_THRESHOLD) {
145 m_walkState = WalkState::NeedTarget;
152 m_vel = Interpolate(0.05f, m_vel, m_targetVel);
156void ObjectPoihana::calcDir() {
159 if (delta.
squaredLength() > std::numeric_limits<f32>::epsilon()) {
166void ObjectPoihana::calcUp() {
167 EGG::Vector3f up = Interpolate(0.1f, m_workMat.base(2), m_dir);
168 if (up.
squaredLength() > std::numeric_limits<f32>::epsilon()) {
171 up = EGG::Vector3f::ez;
f32 normalise()
Normalizes the vector and returns the original length.
f32 squaredLength() const
The dot product between the vector and itself.