diff --git a/include/JSystem/JGeometry/Matrix.h b/include/JSystem/JGeometry/Matrix.h index 60cc19f..27d96a3 100644 --- a/include/JSystem/JGeometry/Matrix.h +++ b/include/JSystem/JGeometry/Matrix.h @@ -194,6 +194,22 @@ namespace JGeometry { rDest.set(x, y, z); } + inline void getYDirInline(TVec3f &rDest) const + { + f32 z = this->mMtx[2][1]; + f32 y = this->mMtx[1][1]; + f32 x = this->mMtx[0][1]; + rDest.set(x, y, z); + } + + inline void getZDirInline(TVec3f &rDest) const + { + f32 z = this->mMtx[2][2]; + f32 y = this->mMtx[1][2]; + f32 x = this->mMtx[0][2]; + rDest.set(x, y, z); + } + #ifdef NON_MATCHING inline void mult33Inline(const TVec3f &rSrc, TVec3f &rDest) const { diff --git a/include/JSystem/JSupport/JSUList.h b/include/JSystem/JSupport/JSUList.h index ab6ad09..303cc71 100644 --- a/include/JSystem/JSupport/JSUList.h +++ b/include/JSystem/JSupport/JSUList.h @@ -72,6 +72,7 @@ class JSUList : public JSUPtrList JSULink *getFirst() const { return (JSULink *)getFirstLink(); } JSULink *getLast() const { return (JSULink *)getLastLink(); } + JSULink *getNth(u32 index) const { return (JSULink *)getNthLink(index); } JSULink *getEnd() const { return nullptr; } u32 getNumLinks() const { return mLinkCount; } diff --git a/include/Kaneshige/Course/CrsArea.h b/include/Kaneshige/Course/CrsArea.h index 8c8415e..696460e 100644 --- a/include/Kaneshige/Course/CrsArea.h +++ b/include/Kaneshige/Course/CrsArea.h @@ -28,6 +28,7 @@ class CrsArea void searchLight(const JGeometry::TVec3f &p1) { search(7, p1); } bool isInside() const { return mArea != nullptr; } + Course::Area *getArea() const { return mArea; } f32 getRate() const { return mRate; } f32 getShadowRate() const { return getRate(); } diff --git a/include/Sato/StringObj.h b/include/Sato/StringObj.h new file mode 100644 index 0000000..7ac109b --- /dev/null +++ b/include/Sato/StringObj.h @@ -0,0 +1,105 @@ +#ifndef STRINGOBJ_H +#define STRINGOBJ_H + +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/J3DU/J3DUClipper.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JSupport/JSUList.h" +#include "Kaneshige/DarkAnmMgr.h" +#include "Kaneshige/ExModel.h" + +// Forward declarations +class ExStringNodeManager; +class StringNodeManager; + +class StringObj { + StringObj(u8, bool); + virtual ~StringObj() { return; }; + void createModel(JKRSolidHeap *, u32); + void loadmodel(J3DModelData *); + void reset(); + virtual void calc(); + void update(); + void setCurrentViewNo(u32); + void drawSimpleModel(u32, Mtx, J3DUClipper *, Mtx); + +public: + // VTBL: 0x0 + StringNodeManager *mStringNodeMgr; // 0x4 + ExModel *mExModel; // 0x8 + u32 _c; + f32 mScale; // 0x10 + Mtx *_14; + u8 _18; + u8 _19[3]; // Padding? + ItemDarkAnmPlayer **mItemDarkAnmPlayer; // 0x1c +}; + +class StringNode { +public: + StringNode(); + ~StringNode(); + void calc(); + + JGeometry::TVec3f mVel; // 0x0 + JGeometry::TVec3f mPos; // 0xc + JGeometry::TVec3f _18; // 0x18 + JGeometry::TVec3f _24; // 0x24 + u8 _30; // 0x30 + u8 _31; // 0x31 + u8 _32[2]; // Padding? + f32 _34; // 0x34 + JSULink _38; // 0x38 +}; + +class StringNodeManager { +public: + StringNodeManager(u8, f32, bool, bool, u8); + virtual ~StringNodeManager(); + + void setAllNodePos(const JGeometry::TVec3f &); + void calc(); + virtual void calcBetweenNodePosAll(f32); + void calcBetweenNodePos(StringNode *, StringNode *, f32, f32); + void resetNodeAll(JGeometry::TVec3f *); + void moveNodeAll(); + void doAirFricG(f32, f32); + void doHeightCol(); + void getNodeVel(u32, JGeometry::TVec3f *); + void getNodePos(u32, JGeometry::TVec3f *); + void addNodeVel(u32, JGeometry::TVec3f); + void setNodeVel(u32, JGeometry::TVec3f); + void addNodePos(u32, JGeometry::TVec3f); + void setNodePos(u32, JGeometry::TVec3f); + + // VTBL: 0x0 + JSUList mStrNodeList; // 0x4 + f32 _10; + f32 _14; + f32 _18; + f32 _1c; + f32 _20; // Scaling multiplier of some sort. + f32 _24; // Something related to distance calculations...? + Vec _28; + StringNode *_34; + GameAudio::ObjectSoundMgr *mObjSoundMgr; // 0x38 + u32 _3c; + u8 _40; + u8 _41[3]; // Padding? + f32 _44; + CrsGround *mCrsGround; // 0x48 + u8 _4c; + u8 _4d[3]; // Padding? +}; + +class ExStringNodeManager : public StringNodeManager { +public: + ExStringNodeManager(); + ~ExStringNodeManager(); + virtual void calcBetweenNodePosAll(f32); + void setNodeLengthAll(f32); + + f32 _50; +}; + +#endif // STRINGOBJ_H diff --git a/src/Sato/StringObj.cpp b/src/Sato/StringObj.cpp index e69de29..ea0e2cc 100644 --- a/src/Sato/StringObj.cpp +++ b/src/Sato/StringObj.cpp @@ -0,0 +1,327 @@ +#include "Sato/StringObj.h" +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JMath/JMath.h" +#include "JSystem/JSupport/JSUList.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/Course.h" +#include "Kaneshige/Course/CrsGround.h" +#include "Kaneshige/DarkAnmMgr.h" +#include "Kaneshige/ExModel.h" +#include "Kaneshige/RaceMgr.h" +#include "Kaneshige/SimpleDrawer.h" +#include "Kaneshige/TexLODControl.h" +#include "Sato/ObjUtility.h" +#include "dolphin/mtx.h" +#include "JSystem/JGeometry/Util.h" +#include "types.h" + + +StringNodeManager::StringNodeManager(u8 count, f32 speed, bool makeSoundMgr, bool makeCrsGround, u8 someFlag) { + mCrsGround = nullptr; + _10 = speed; + + _34 = new StringNode[count]; + StringNode* node = _34; + + for (u8 i = 0; i < count; i++, node++) { + mStrNodeList.append(&node->_38); + } + + _24 = 0.8f; + _20 = 0.97f; + _1c = -1.0f; + _14 = 30.0f; + _18 = 0.0f; + _28.x = 0.0f; + _28.y = 1.0f; + _28.z = 0.0f; + _44 = 100.0f; + _3c = 0; + _40 = 0; + + mObjSoundMgr = makeSoundMgr + ? new GameAudio::ObjectSoundMgr(&mStrNodeList.getNth(_40)->getObject()->mPos, nullptr) + : nullptr; + + if (makeCrsGround) { + mCrsGround = new CrsGround(RaceMgr::sRaceManager->getCourse()); + } + + _4c = someFlag; +} + +StringNode::~StringNode() {} + +StringNode::StringNode() : _38(this) { + mVel.zero(); + mPos.zero(); + _18.zero(); + _24.zero(); + _30 = true; + _31 = false; + _34 = 0.0f; +} + +void StringNodeManager::setAllNodePos(const JGeometry::TVec3f ¶m_1) { + for (u8 i = 0; i < mStrNodeList.getNumLinks(); i++) { + setNodePos(i, param_1); + } +} + +void StringNodeManager::calc() { + doAirFricG(_20, _1c); + moveNodeAll(); + calcBetweenNodePosAll(_24); + doHeightCol(); + if (mObjSoundMgr != nullptr) { + mObjSoundMgr->frameWork(); + } +} + +void StringNodeManager::calcBetweenNodePosAll(f32 param_1) { +} + +void StringNodeManager::calcBetweenNodePos(StringNode *strNodeOne, StringNode *strNodeTwo, f32 f1, f32 f2) { + JGeometry::TVec3f vecInput = strNodeTwo->mPos; // TODO: Declaration is needed, but why is this unused...? + JGeometry::TVec3f vecDiff; + JGeometry::TVec3f vecNormalised; + JGeometry::TVec3f vecScaled; + JGeometry::TVec3f vecFinal; + + PSVECSubtract(&strNodeOne->mPos, &strNodeTwo->mPos, &vecDiff); + f32 magnitude = PSVECMag(&vecDiff); + + if (magnitude > f2) { + PSVECNormalize(&vecDiff, &vecNormalised); + PSVECScale(&vecNormalised, &vecScaled, -f2); + PSVECAdd(&strNodeOne->mPos, &vecScaled, &strNodeTwo->mPos); + + f32 fVar1 = vecDiff.squared(); + if (fVar1 <= JGeometry::TUtilf::epsilon()) { + vecFinal.zero(); + } else { + fVar1 = JGeometry::TUtilf::inv_sqrt(fVar1); + vecFinal.scale(fVar1, vecDiff); + } + + f32 fVar2 = (f1 * (magnitude - f2)); + f32 fVar3 = fVar2 > _44 ? _44 : fVar2; + + vecFinal.scale(fVar3); + strNodeTwo->mVel += vecFinal; + } +} + +void StringNodeManager::resetNodeAll(JGeometry::TVec3f *param_1) { +} + +void StringNodeManager::moveNodeAll() { + for (JSULink *link = mStrNodeList.getFirst()->getNext(); link != nullptr; link = link->getNext()) { + StringNode *stringNode = link->getObject(); + PSVECAdd(&stringNode->mPos, &stringNode->mVel, &stringNode->mPos); + } +} + +void StringNodeManager::doAirFricG(f32 friction, f32 globalScale) { + for (JSULink *link = mStrNodeList.getFirst()->getNext(); link != nullptr; link = link->getNext()) { + link->getObject()->mVel.scale((f32)friction); + JMAVECScaleAdd(&_28, &link->getObject()->mVel, &link->getObject()->mVel, globalScale); + } +} + +void StringNodeManager::doHeightCol() { + JSULink *node; + CrsArea crsArea; + u8 someCount = 0; + + for (node = mStrNodeList.getFirst()->getNext(); node != nullptr; node = node->getNext()) { + if (node->getObject()->_30 != 0) { + bool someCheck = false; + crsArea.search(2, node->getObject()->mPos); + + if (crsArea.getArea() != nullptr) { + JGeometry::TVec3f roofPos; + crsArea.getRoofPosition(&roofPos); + + if (node->getObject()->mPos.y + 100.0f > roofPos.y) { + someCheck = true; + node->getObject()->mVel.y = 0.0f; + node->getObject()->mVel.x *= _18; + node->getObject()->mVel.z *= _18; + node->getObject()->mPos.y = roofPos.y - 100.0f; + } + } + + CrsGround crsGroundInit(RaceMgr::sRaceManager->getCourse()); + CrsGround *crsGround = &crsGroundInit; + + if ((mCrsGround != nullptr) && (someCount == _4c)) { + crsGround = mCrsGround; + } + + crsGround->search(node->getObject()->mPos, node->getObject()->_18); + + if (crsGround->getAttribute() != 10) { + if (crsGround->getHeight() > (node->getObject()->mPos.y - _14)) { + JGeometry::TVec3f crsGroundNormal; + crsGround->getNormal(&crsGroundNormal); + + f32 crsHeight = crsGround->getHeight(); + f32 newScale = crsHeight - (node->getObject()->mPos.y - _14); + crsGroundNormal.scale(newScale * _18); + node->getObject()->mVel.add(crsGroundNormal); + + StringNode *stringNode = node->getObject(); + crsHeight = crsGround->getHeight(); + someCheck = true; + stringNode->mPos.y = _14 + crsHeight; + } + } + + if (someCheck) { + node->getObject()->_31 = true; + if ((mObjSoundMgr != nullptr) && (someCount == _40)) { + mObjSoundMgr->setSe(_3c); + } + + } else { + node->getObject()->_31 = false; + } + + crsGround->getNormal(&node->getObject()->_24); + node->getObject()->_18 = node->getObject()->mPos; + } + + someCount++; + } +} + +void StringNodeManager::getNodeVel(u32 num, JGeometry::TVec3f *vel) { +#line 421 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + *vel = mStrNodeList.getNth(num)->getObject()->mVel; +} + +void StringNodeManager::getNodePos(u32 num, JGeometry::TVec3f *pos) { +#line 434 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + *pos = mStrNodeList.getNth(num)->getObject()->mPos; +} + +void StringNodeManager::addNodeVel(u32 num, JGeometry::TVec3f newVel) { +#line 448 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + mStrNodeList.getNth(num)->getObject()->mVel += newVel; +} + +void StringNodeManager::setNodeVel(u32 num, JGeometry::TVec3f newVel) { +#line 461 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + mStrNodeList.getNth(num)->getObject()->mVel = newVel; +} + +void StringNodeManager::addNodePos(u32 num, JGeometry::TVec3f newPos) { +#line 474 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + mStrNodeList.getNth(num)->getObject()->mPos += newPos; +} + +void StringNodeManager::setNodePos(u32 num, JGeometry::TVec3f newPos) { +#line 487 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + mStrNodeList.getNth(num)->getObject()->mPos = newPos; +} + +void ExStringNodeManager::calcBetweenNodePosAll(f32 param_1) { +} + +void ExStringNodeManager::setNodeLengthAll(f32 newLength) { + for (JSULink *link = mStrNodeList.getFirst(); link != nullptr; link = link->getNext()) { + link->getObject()->_34 = newLength; + } +} + +StringObj::StringObj(u8 nodeCount, bool someFlag) { +} + +StringNodeManager::~StringNodeManager() { + delete[] _34; +} + +void StringObj::createModel(JKRSolidHeap *, u32) { + return; +} + +void StringObj::loadmodel(J3DModelData *modelData) { + ExModel *exModel = mExModel; + u32 i = 0; + while (i < mStringNodeMgr->mStrNodeList.getNumLinks()) { + exModel->setModelData(modelData); + RaceMgr::sRaceManager->getCourse()->setFogInfo(exModel); + exModel->setLODBias( + TexLODControl::getManager()->getLODBias(TexLODControl::cLODBiasID_3) + ); + i++; + exModel++; + } +} + +void StringObj::reset() { + for (u32 i = 0; i < mStringNodeMgr->mStrNodeList.getNumLinks(); i++) { + mItemDarkAnmPlayer[i]->reset(); + } +} + +void StringObj::calc() { + +} + +void StringObj::update() { + ExModel *exModel = mExModel; + + for (u32 i = 0; i < mStringNodeMgr->mStrNodeList.getNumLinks() - 1; i++, exModel++) { + exModel->update(0); + } +} + +void StringObj::setCurrentViewNo(u32 viewNo) { + u32 num = 0; + ExModel *exModel = mExModel; + + while (num < mStringNodeMgr->mStrNodeList.getNumLinks() - 1) { + exModel->setCurrentViewNo(viewNo); + + JGeometry::TVec3f pos; + mStringNodeMgr->getNodePos(viewNo, &pos); + + Mtx lightMtx; + ObjUtility::getCamDependLightMtx(viewNo, pos, lightMtx); + mExModel[num].setEffectMtx(lightMtx, 0); + num++; + exModel++; + } +} + +void StringObj::drawSimpleModel(u32 p1, Mtx mtx1, J3DUClipper *j3duClipper, Mtx mtx2) { + SimpleDrawer simpleDrawer; + + if (!mExModel->getModelData()) return; + + simpleDrawer.drawInit(mExModel); + + while (simpleDrawer.loadPreDrawSetting()) { + for (u32 num = 0; num < mStringNodeMgr->mStrNodeList.getNumLinks() - 1; num++) { + JGeometry::TVec3f pos; + mStringNodeMgr->getNodePos(num, &pos); + f32 radius = pos.x; // FIX: should be `pos.z`, but this reorders instructions weirdly...? + + mExModel[num].clipBySphere(p1, j3duClipper, mtx1, radius); + mItemDarkAnmPlayer[num]->setTevColor(&mExModel[num]); + mExModel[num].simpleDraw(p1, mtx2, 1); + } + } +} + +ExStringNodeManager::~ExStringNodeManager() {}