#ifndef _CBALLCAMERA #define _CBALLCAMERA #include "types.h" #include "MetroidPrime/Cameras/CCameraSpline.hpp" #include "MetroidPrime/Cameras/CGameCamera.hpp" #include "Kyoto/Math/CMath.hpp" class CCameraSpring { public: CCameraSpring(float k, float max, float tardis) : x0_k(k), x4_k2Sqrt(CMath::SqrtF(k) * 2.f), x8_max(max), xc_tardis(tardis), x10_dx(0.f) {} void Reset(); float ApplyDistanceSpringNoMax(float targetX, float curX, float dt); float ApplyDistanceSpring(float targetX, float curX, float dt); private: float x0_k; float x4_k2Sqrt; float x8_max; float xc_tardis; float x10_dx; }; class CCameraCollider { public: CCameraCollider(float radius, CVector3f vec, const CCameraSpring& spring, float scale) : x4_radius(radius) , x8_lastLocalPos(vec) , x14_localPos(vec) , x20_scaledWorldPos(vec) , x2c_lastWorldPos(vec) , x38_spring(spring) , x4c_occlusionCount(0) , x50_scale(scale) {} virtual ~CCameraCollider() {} float GetRadius() const { return x4_radius; } // TODO const CVector3f& GetRealPosition() const { return x2c_lastWorldPos; } const CVector3f& GetDesiredPosition() const { return x14_localPos; } const CVector3f& GetLookAtPosition() const { return x20_scaledWorldPos; } const CVector3f& GetLineOfSight() const; const CVector3f& GetPosition() const { return x8_lastLocalPos; } int GetOcclusionCount() const { return x4c_occlusionCount; } float GetScale() const { return x50_scale; } void SetRadius(float radius) { this->x4_radius = radius; } // TODO void SetPosition(CVector3f vec) { x8_lastLocalPos = vec; } void SetRealPosition(CVector3f vec) { x2c_lastWorldPos = vec; } void SetDesiredPosition(CVector3f vec) { x14_localPos = vec; } void SetLookAtPosition(CVector3f vec) { x20_scaledWorldPos = vec; } void SetLineOfSight(); void SetOcclusionCount(int val) { x4c_occlusionCount = val; } void SetScale(float val) { x50_scale = val; } private: float x4_radius; CVector3f x8_lastLocalPos; // position CVector3f x14_localPos; // desired position CVector3f x20_scaledWorldPos; // look at position CVector3f x2c_lastWorldPos; // real position CCameraSpring x38_spring; int x4c_occlusionCount; float x50_scale; }; class CBallCamera : public CGameCamera { public: enum EBallCameraState { kBCS_Default, kBCS_One, kBCS_Chase, kBCS_Boost, kBCS_ToBall, kBCS_FromBall, }; enum EBallCameraBehaviour { kBCB_Default, kBCB_FreezeLookPosition, // Unused kBCB_HintBallToCam, kBCB_HintInitializePosition, kBCB_HintFixedPosition, kBCB_HintFixedTransform, kBCB_PathCameraDesiredPos, // Unused kBCB_PathCamera, kBCB_SpindleCamera, }; enum ESplineState { kBSS_Invalid, kBSS_Nav, kBSS_Arc, }; CBallCamera(TUniqueId uid, TUniqueId watchedId, const CTransform4f& xf, float fovY, float nearZ, float farZ, float aspect); // CEntity ~CBallCamera() override; void Accept(IVisitor& visitor) override; void Think(float dt, CStateManager& mgr) override; void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; // CActor void Render(const CStateManager&) const override; // CGameCamera void ProcessInput(const CFinalInput&, CStateManager& mgr) override; void Reset(const CTransform4f&, CStateManager& mgr) override; // CBallCamera void SetupColliders(rstl::vector< CCameraCollider >& out, float xMag, float zMag, float radius, int count, float k, float max, float startAngle); void TeleportColliders(rstl::vector< CCameraCollider >& colliderList, CVector3f pos); void TeleportCamera(const CVector3f& pos, CStateManager& mgr); void TeleportCamera(const CTransform4f& xf, CStateManager& mgr); void TeleportLookAtStuff(CStateManager& mgr); void ResetToTweaks(CStateManager& mgr); CVector3f FindDesiredPosition(float distance, float elevation, CVector3f dir, CStateManager& mgr, bool fullTest); void UpdateCollidersDistances(rstl::vector< CCameraCollider >& colliderList, float xMag, float zMag, float angOffset); void UpdateColliders(const CTransform4f& xf, rstl::vector< CCameraCollider >& colliderList, int& idx, int count, float tolerance, const TEntityList& nearList, float dt, CStateManager& mgr); CVector3f CalculateCollidersCentroid(const rstl::vector< CCameraCollider >& colliderList, int numObscured) const; CVector3f ApplyColliders(); int CountObscuredColliders(const rstl::vector< CCameraCollider >& colliderList) const; CAABox CalculateCollidersBoundingBox(const rstl::vector< CCameraCollider >& colliderList, const CStateManager&) const; CVector3f AvoidGeometryFull(const CTransform4f& xf, const TEntityList& nearList, float dt, CStateManager& mgr); CVector3f AvoidGeometry(const CTransform4f& xf, const TEntityList& nearList, float dt, CStateManager& mgr); bool DetectCollision(const CVector3f& from, const CVector3f& to, float radius, float& d, CStateManager& mgr); CTransform4f FindDesiredTransform(CVector3f dir, CStateManager& mgr); const CVector3f& GetLookAtPosition() const { return x1d8_lookPos; } float GetDistance() const { return x190_curMinDistance; } float GetElevation() const { return x1a0_elevation; } void SetBehaviourType(EBallCameraBehaviour type) { x188_behaviour = type; } void SetAllowChaseCamera(bool v) { x18c_25_chaseAllowed = v; } void SetAllowBoostCamera(bool v) { x18c_26_boostAllowed = v; } // void SetLineOfSightCheck(bool v); void SetGeometryAvoidance(bool v) { x18c_27_obscureAvoidance = true; } void SetMinDistance(float v) { x194_targetMinDistance = v; } void SetMaxDistance(float v) { x198_maxDistance = v; } void SetBackwardsDistance(float v) { x19c_backwardsDistance = v; } void SetDistanceSpring(const CCameraSpring& spring) { x214_ballCameraSpring = spring; } void SetCentroidDistanceSpring(const CCameraSpring& spring) { x250_ballCameraCentroidDistanceSpring = spring; } void SetElevation(float v) { x1a0_elevation = v; } void SetLookAtOffset(CVector3f vec) { x1b4_lookAtOffset = vec; } void SetChaseLookAtOffset(CVector3f vec) { x410_chaseLookAtOffset = vec; } void SetWorldOffset(CVector3f vec); // TODO EBallCameraState GetState() const { return x400_state; } void SetState(EBallCameraState state); void OverrideCameraInfo(CStateManager& mgr); void UpdateLookAtPosition(float dt, CStateManager& mgr); void SetClampVelTimer(float v) { x470_clampVelTimer = v; } void SetClampVelRange(float v) { x474_clampVelRange = v; } private: struct SFailsafeState { CTransform4f x0_playerXf; CTransform4f x30_camXf; CVector3f x60_lookPos; CVector3f x6c_behindPos; CVector3f x78_; CVector3f x84_playerPos; rstl::vector< CVector3f > x90_splinePoints; SFailsafeState(); }; struct SUnknown { SUnknown(); }; EBallCameraBehaviour x188_behaviour; bool x18c_24_ : 1; bool x18c_25_chaseAllowed : 1; bool x18c_26_boostAllowed : 1; bool x18c_27_obscureAvoidance : 1; bool x18c_28_volumeCollider : 1; bool x18c_29_clampAttitude : 1; bool x18c_30_clampAzimuth : 1; bool x18c_31_clearLOS : 1; bool x18d_24_prevClearLOS : 1; bool x18d_25_avoidGeometryFull : 1; bool x18d_26_lookAtBall : 1; bool x18d_27_forceProcessing : 1; bool x18d_28_obtuseDirection : 1; bool x18d_29_noElevationInterp : 1; bool x18d_30_directElevation : 1; bool x18d_31_overrideLookDir : 1; bool x18e_24_noElevationVelClamp : 1; bool x18e_25_noSpline : 1; bool x18e_26_ : 1; bool x18e_27_nearbyDoorClosed : 1; bool x18e_28_nearbyDoorClosing : 1; float x190_curMinDistance; float x194_targetMinDistance; float x198_maxDistance; float x19c_backwardsDistance; float x1a0_elevation; float x1a4_curAnglePerSecond; float x1a8_targetAnglePerSecond; float x1ac_attitudeRange; float x1b0_azimuthRange; CVector3f x1b4_lookAtOffset; CVector3f x1c0_lookPosAhead; CVector3f x1cc_fixedLookPos; CVector3f x1d8_lookPos; CTransform4f x1e4_nextLookXf; CCameraSpring x214_ballCameraSpring; CCameraSpring x228_ballCameraCentroidSpring; CCameraSpring x23c_ballCameraLookAtSpring; CCameraSpring x250_ballCameraCentroidDistanceSpring; rstl::vector< CCameraCollider > x264_smallColliders; rstl::vector< CCameraCollider > x274_mediumColliders; rstl::vector< CCameraCollider > x284_largeColliders; CVector3f x294_dampedPos; CVector3f x2a0_smallCentroid; CVector3f x2ac_mediumCentroid; CVector3f x2b8_largeCentroid; int x2c4_smallCollidersObsCount; int x2c8_mediumCollidersObsCount; int x2cc_largeCollidersObsCount; int x2d0_smallColliderIt; int x2d4_mediumColliderIt; int x2d8_largeColliderIt; CVector3f x2dc_prevBallPos; float x2e8_ballVelFlat; float x2ec_maxBallVel; CVector3f x2f0_ballDelta; CVector3f x2fc_ballDeltaFlat; float x308_speedFactor; float x30c_speedingTime; CVector3f x310_idealLookVec; CVector3f x31c_predictedLookPos; int x328_avoidGeomCycle; float x32c_colliderMag; float x330_clearColliderThreshold; CAABox x334_collidersAABB; float x34c_obscuredTime; CMaterialList x350_obscuringMaterial; float x358_unobscureMag; CVector3f x35c_splineIntermediatePos; TUniqueId x368_obscuringObjectId; ESplineState x36c_splineState; bool x370_24_reevalSplineEnd : 1; float x374_splineCtrl; float x378_splineCtrlRange; CCameraSpline x37c_camSpline; CMaterialList x3c8_collisionExcludeList; bool x3d0_24_camBehindFloorOrWall : 1; float x3d4_elevInterpTimer; float x3d8_elevInterpStart; TUniqueId x3dc_tooCloseActorId; float x3e0_tooCloseActorDist; bool x3e4_pendingFailsafe; float x3e8_; float x3ec_; float x3f0_; float x3f4_; float x3f8_; float x3fc_; EBallCameraState x400_state; float x404_chaseElevation; float x408_chaseDistance; float x40c_chaseAnglePerSecond; CVector3f x410_chaseLookAtOffset; CCameraSpring x41c_ballCameraChaseSpring; float x430_boostElevation; float x434_boostDistance; float x438_boostAnglePerSecond; CVector3f x43c_boostLookAtOffset; CCameraSpring x448_ballCameraBoostSpring; CVector3f x45c_overrideBallToCam; float x468_conservativeDoorCamDistance; TUniqueId x46c_collisionActorId; float x470_clampVelTimer; float x474_clampVelRange; uint x478_shortMoveCount; rstl::single_ptr< SFailsafeState > x47c_failsafeState; rstl::single_ptr< SUnknown > x480_; }; CHECK_SIZEOF(CBallCamera, 0x488) #endif // _CBALLCAMERA