pioneer/src/Space.h

170 lines
4.8 KiB
C++

// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
#ifndef _SPACE_H
#define _SPACE_H
#include "Background.h"
#include "FrameId.h"
#include "IterationProxy.h"
#include "RefCounted.h"
#include "galaxy/StarSystem.h"
#include "vector3.h"
class Body;
class Frame;
class Game;
enum class ObjectType;
class Space {
public:
// empty space (eg for hyperspace)
Space(Game *game, RefCountedPtr<Galaxy> galaxy, Space *oldSpace = nullptr);
// initalise with system bodies
Space(Game *game, RefCountedPtr<Galaxy> galaxy, const SystemPath &path, Space *oldSpace = nullptr);
// initialise from save file
Space(Game *game, RefCountedPtr<Galaxy> galaxy, const Json &jsonObj, double at_time);
~Space();
void ToJson(Json &jsonObj);
// body/sbody indexing for save/load. valid after
// construction/ToJson(), invalidated by TimeStep(). they will assert
// if called while invalid
Body *GetBodyByIndex(Uint32 idx) const;
SystemBody *GetSystemBodyByIndex(Uint32 idx) const;
Uint32 GetIndexForBody(const Body *body) const;
Uint32 GetIndexForSystemBody(const SystemBody *sbody) const;
RefCountedPtr<StarSystem> GetStarSystem() const { return m_starSystem; }
FrameId GetRootFrame() const { return m_rootFrameId; }
void AddBody(Body *);
void RemoveBody(Body *);
void KillBody(Body *);
void TimeStep(float step);
void GetHyperspaceExitParams(const SystemPath &source, const SystemPath &dest,
vector3d &pos, vector3d &vel) const;
vector3d GetHyperspaceExitPoint(const SystemPath &source, const SystemPath &dest) const
{
vector3d pos, vel;
GetHyperspaceExitParams(source, dest, pos, vel);
return pos;
}
vector3d GetHyperspaceExitPoint(const SystemPath &source) const
{
return GetHyperspaceExitPoint(source, m_starSystem->GetPath());
}
Body *FindNearestTo(const Body *b, ObjectType t) const;
Body *FindBodyForPath(const SystemPath *path) const;
Uint32 GetNumBodies() const { return static_cast<Uint32>(m_bodies.size()); }
IterationProxy<std::vector<Body *>> GetBodies() { return MakeIterationProxy(m_bodies); }
const IterationProxy<const std::vector<Body *>> GetBodies() const { return MakeIterationProxy(m_bodies); }
Background::Container *GetBackground() { return m_background.get(); }
void RefreshBackground();
// body finder delegates
typedef const std::vector<Body *> BodyNearList;
BodyNearList GetBodiesMaybeNear(const Body *b, double dist)
{
return m_bodyNearFinder.GetBodiesMaybeNear(b, dist);
}
BodyNearList GetBodiesMaybeNear(const vector3d &pos, double dist)
{
return m_bodyNearFinder.GetBodiesMaybeNear(pos, dist);
}
void DebugDumpFrames(bool details);
private:
void GenSectorCache(RefCountedPtr<Galaxy> galaxy, const SystemPath *here);
void UpdateStarSystemCache(const SystemPath *here);
void GenBody(const double at_time, SystemBody *b, FrameId fId, std::vector<vector3d> &posAccum);
// make sure SystemBody* is in Pi::currentSystem
FrameId GetFrameWithSystemBody(const SystemBody *b) const;
void UpdateBodies();
void CollideFrame(FrameId fId);
FrameId m_rootFrameId;
RefCountedPtr<SectorCache::Slave> m_sectorCache;
RefCountedPtr<StarSystemCache::Slave> m_starSystemCache;
RefCountedPtr<StarSystem> m_starSystem;
Game *m_game;
// all the bodies we know about
std::vector<Body *> m_bodies;
// bodies that were removed/killed this timestep and need pruning at the end
enum class BodyAssignation {
KILL = 0,
REMOVE = 1
};
std::vector<std::pair<Body *, BodyAssignation>> m_assignedBodies;
void RebuildBodyIndex();
void RebuildSystemBodyIndex();
void AddSystemBodyToIndex(SystemBody *sbody);
bool m_bodyIndexValid, m_sbodyIndexValid;
std::vector<Body *> m_bodyIndex;
std::vector<SystemBody *> m_sbodyIndex;
//background (elements that are infinitely far away,
//e.g. starfield and milky way)
std::unique_ptr<Background::Container> m_background;
class BodyNearFinder {
public:
BodyNearFinder(const Space *space) :
m_space(space) {}
void Prepare();
BodyNearList GetBodiesMaybeNear(const Body *b, double dist);
BodyNearList GetBodiesMaybeNear(const vector3d &pos, double dist);
private:
struct BodyDist {
BodyDist(Body *_body, double _dist) :
body(_body),
dist(_dist) {}
Body *body;
double dist;
bool operator<(const BodyDist &a) const { return dist < a.dist; }
friend bool operator<(const BodyDist &a, double d) { return a.dist < d; }
friend bool operator<(double d, const BodyDist &a) { return d < a.dist; }
};
const Space *m_space;
std::vector<BodyDist> m_bodyDist;
std::vector<Body *> m_nearBodies;
};
BodyNearFinder m_bodyNearFinder;
#ifndef NDEBUG
//to check RemoveBody and KillBody are not called from within
//the NotifyRemoved callback (#735)
bool m_processingFinalizationQueue;
#endif
};
#endif /* _SPACE_H */