Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpUnitRenderer.h
- This file was added.
/* Copyright (C) 2022 Wildfire Games. | |||||
* This file is part of 0 A.D. | |||||
* | |||||
* 0 A.D. is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* 0 A.D. is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef INCLUDED_CCMPUNITRENDERER | |||||
#define INCLUDED_CCMPUNITRENDERER | |||||
#include "ICmpUnitRenderer.h" | |||||
#include "graphics/Overlay.h" | |||||
#include "maths/BoundingSphere.h" | |||||
#include "simulation2/components/ICmpRangeManager.h" | |||||
class SceneCollector; | |||||
/** | |||||
* Efficiently(ish) renders all the units in the world. | |||||
* | |||||
* The class maintains a list of all units that currently exist, and the data | |||||
* needed for frustum-culling them. To minimise the amount of work done per | |||||
* frame (despite a unit's interpolated position changing every frame), the | |||||
* culling data is only updated once per turn: we store the position at the | |||||
* start of the turn, and the position at the end of the turn, and assume the | |||||
* unit might be anywhere between those two points (linearly). | |||||
* | |||||
* (Note this is a slightly invalid assumption: units don't always move linearly, | |||||
* since their interpolated position depends on terrain and water. But over a | |||||
* single turn it's probably going to be a good enough approximation, and will | |||||
* only break for units that both start and end the turn off-screen.) | |||||
* | |||||
* We want to ignore rotation entirely, since it's a complex function of | |||||
* interpolated position and terrain. So we store a bounding sphere, which | |||||
* is rotation-independent, instead of a bounding box. | |||||
*/ | |||||
class CCmpUnitRenderer final : public ICmpUnitRenderer | |||||
{ | |||||
public: | |||||
struct SUnit | |||||
{ | |||||
CEntityHandle entity; | |||||
CUnit* actor; | |||||
int flags; | |||||
/** | |||||
* m_FrameNumber from when the model's transform was last updated. | |||||
* This is used to avoid recomputing it multiple times per frame | |||||
* if a model is visible in multiple cull groups. | |||||
*/ | |||||
int lastTransformFrame; | |||||
/** | |||||
* Worst-case bounding shape, relative to position. Needs to account | |||||
* for all possible animations, orientations, etc. | |||||
*/ | |||||
CBoundingSphere boundsApprox; | |||||
/** | |||||
* Cached LOS visibility status. | |||||
*/ | |||||
LosVisibility visibility; | |||||
bool visibilityDirty; | |||||
/** | |||||
* Whether the unit has a valid position. If false, pos0 and pos1 | |||||
* are meaningless. | |||||
*/ | |||||
bool inWorld; | |||||
/** | |||||
* World-space positions to interpolate between. | |||||
*/ | |||||
CVector3D pos0; | |||||
CVector3D pos1; | |||||
/** | |||||
* Bounds encompassing the unit's bounds when it is anywhere between | |||||
* pos0 and pos1. | |||||
*/ | |||||
CBoundingSphere sweptBounds; | |||||
/** | |||||
* For debug overlay. | |||||
*/ | |||||
bool culled; | |||||
}; | |||||
static constexpr int typeId{CID_UnitRenderer}; | |||||
std::vector<SUnit> m_Units; | |||||
std::vector<tag_t> m_UnitTagsFree; | |||||
int m_FrameNumber; | |||||
float m_FrameOffset; | |||||
bool m_EnableDebugOverlays; | |||||
std::vector<SOverlaySphere> m_DebugSpheres; | |||||
static void ClassInit(CComponentManager& componentManager); | |||||
static IComponent* Allocate(const ScriptInterface&, JS::HandleValue); | |||||
static void Deallocate(IComponent* cmp); | |||||
int GetComponentTypeId() const override; | |||||
static std::string GetSchema(); | |||||
void Init(const CParamNode& UNUSED(paramNode)) override; | |||||
void Deinit() override; | |||||
void Serialize(ISerializer& UNUSED(serialize)) override; | |||||
void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) override; | |||||
void HandleMessage(const CMessage& msg, bool UNUSED(global)) override; | |||||
SUnit* LookupUnit(tag_t tag); | |||||
tag_t AddUnit(CEntityHandle entity, CUnit* actor, const CBoundingSphere& boundsApprox, int flags) | |||||
override; | |||||
void RemoveUnit(tag_t tag) override; | |||||
void RecomputeSweptBounds(SUnit* unit); | |||||
void UpdateUnit(tag_t tag, CUnit* actor, const CBoundingSphere& boundsApprox) override; | |||||
void UpdateUnitPos(tag_t tag, bool inWorld, const CVector3D& pos0, const CVector3D& pos1) override; | |||||
void TurnStart(); | |||||
void Interpolate(float frameTime, float frameOffset); | |||||
void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling); | |||||
void UpdateVisibility(SUnit& unit) const; | |||||
float GetFrameOffset() const override; | |||||
void SetDebugOverlay(bool enabled) override; | |||||
void PickAllEntitiesAtPoint(std::vector<std::pair<CEntityHandle, CVector3D> >& outEntities, | |||||
const CVector3D& origin, const CVector3D& dir, bool allowEditorSelectables) const override; | |||||
}; | |||||
#endif // INCLUDED_CCMPUNITRENDERER |
Wildfire Games · Phabricator