Index: ps/trunk/source/graphics/Decal.h
===================================================================
--- ps/trunk/source/graphics/Decal.h (revision 26248)
+++ ps/trunk/source/graphics/Decal.h (revision 26249)
@@ -1,92 +1,87 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* 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 .
*/
#ifndef INCLUDED_DECAL
#define INCLUDED_DECAL
#include "graphics/Material.h"
#include "graphics/ModelAbstract.h"
class CTerrain;
/**
* Terrain decal definition.
* Decals are rectangular textures that are projected vertically downwards
* onto the terrain.
*/
struct SDecal
{
SDecal(const CMaterial& material, float sizeX, float sizeZ, float angle,
float offsetX, float offsetZ, bool floating)
: m_Material(material), m_SizeX(sizeX), m_SizeZ(sizeZ), m_Angle(angle),
m_OffsetX(offsetX), m_OffsetZ(offsetZ), m_Floating(floating)
{
}
CMaterial m_Material;
float m_SizeX;
float m_SizeZ;
float m_Angle;
float m_OffsetX;
float m_OffsetZ;
bool m_Floating;
};
class CModelDecal : public CModelAbstract
{
public:
CModelDecal(CTerrain* terrain, const SDecal& decal)
: m_Terrain(terrain), m_Decal(decal)
{
ENSURE(terrain != NULL);
}
/// Dynamic cast
virtual CModelDecal* ToCModelDecal()
{
return this;
}
virtual CModelAbstract* Clone() const;
- virtual void SetDirtyRec(int dirtyflags)
- {
- SetDirty(dirtyflags);
- }
-
virtual void SetTerrainDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1);
virtual void CalcBounds();
virtual void ValidatePosition();
virtual void InvalidatePosition();
virtual void SetTransform(const CMatrix3D& transform);
// remove shadow receiving
void RemoveShadows();
/**
* Compute the terrain vertex indexes that bound the decal's
* projection onto the terrain.
* The returned indexes are clamped to the terrain size.
*/
void CalcVertexExtents(ssize_t& i0, ssize_t& j0, ssize_t& i1, ssize_t& j1);
CTerrain* m_Terrain;
SDecal m_Decal;
};
#endif // INCLUDED_DECAL
Index: ps/trunk/source/graphics/GameView.cpp
===================================================================
--- ps/trunk/source/graphics/GameView.cpp (revision 26248)
+++ ps/trunk/source/graphics/GameView.cpp (revision 26249)
@@ -1,423 +1,400 @@
/* 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 .
*/
#include "precompiled.h"
#include "GameView.h"
#include "graphics/CameraController.h"
#include "graphics/CinemaManager.h"
#include "graphics/ColladaManager.h"
#include "graphics/HFTracer.h"
#include "graphics/LOSTexture.h"
#include "graphics/LightEnv.h"
#include "graphics/MiniMapTexture.h"
#include "graphics/Model.h"
#include "graphics/ObjectManager.h"
#include "graphics/Patch.h"
#include "graphics/SkeletonAnimManager.h"
#include "graphics/SmoothedValue.h"
#include "graphics/Terrain.h"
#include "graphics/TerrainTextureManager.h"
#include "graphics/TerritoryTexture.h"
#include "graphics/Unit.h"
#include "graphics/UnitManager.h"
#include "lib/input.h"
#include "lib/timer.h"
#include "lobby/IXmppClient.h"
#include "maths/BoundingBoxAligned.h"
#include "maths/MathUtil.h"
#include "maths/Matrix3D.h"
#include "maths/Quaternion.h"
#include "ps/ConfigDB.h"
#include "ps/Filesystem.h"
#include "ps/Game.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "ps/Loader.h"
#include "ps/LoaderThunks.h"
#include "ps/Profile.h"
#include "ps/Pyrogenesis.h"
#include "ps/TouchInput.h"
#include "ps/World.h"
#include "renderer/Renderer.h"
#include "renderer/SceneRenderer.h"
#include "renderer/WaterManager.h"
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpPosition.h"
#include "simulation2/components/ICmpRangeManager.h"
#include
class CGameViewImpl
{
NONCOPYABLE(CGameViewImpl);
public:
CGameViewImpl(CGame* game)
: Game(game),
ColladaManager(g_VFS), MeshManager(ColladaManager), SkeletonAnimManager(ColladaManager),
ObjectManager(MeshManager, SkeletonAnimManager, *game->GetSimulation2()),
LOSTexture(*game->GetSimulation2()),
TerritoryTexture(*game->GetSimulation2()),
MiniMapTexture(*game->GetSimulation2()),
ViewCamera(),
CullCamera(),
LockCullCamera(false),
Culling(true),
CameraController(new CCameraController(ViewCamera))
{
}
CGame* Game;
CColladaManager ColladaManager;
CMeshManager MeshManager;
CSkeletonAnimManager SkeletonAnimManager;
CObjectManager ObjectManager;
CLOSTexture LOSTexture;
CTerritoryTexture TerritoryTexture;
CMiniMapTexture MiniMapTexture;
/**
* this camera controls the eye position when rendering
*/
CCamera ViewCamera;
/**
* this camera controls the frustum that is used for culling
* and shadow calculations
*
* Note that all code that works with camera movements should only change
* m_ViewCamera. The render functions automatically sync the cull camera to
* the view camera depending on the value of m_LockCullCamera.
*/
CCamera CullCamera;
/**
* When @c true, the cull camera is locked in place.
* When @c false, the cull camera follows the view camera.
*
* Exposed to JS as gameView.lockCullCamera
*/
bool LockCullCamera;
/**
* When @c true, culling is enabled so that only models that have a chance of
* being visible are sent to the renderer.
* Otherwise, the entire world is sent to the renderer.
*
* Exposed to JS as gameView.culling
*/
bool Culling;
/**
* Cache global lighting environment. This is used to check whether the
* environment has changed during the last frame, so that vertex data can be updated etc.
*/
CLightEnv CachedLightEnv;
CCinemaManager CinemaManager;
/**
* Controller of the view's camera. We use a std::unique_ptr for an easy
* on the fly replacement. It's guaranteed that the pointer is never nulllptr.
*/
std::unique_ptr CameraController;
};
#define IMPLEMENT_BOOLEAN_SETTING(NAME) \
bool CGameView::Get##NAME##Enabled() const \
{ \
return m->NAME; \
} \
\
void CGameView::Set##NAME##Enabled(bool Enabled) \
{ \
m->NAME = Enabled; \
}
IMPLEMENT_BOOLEAN_SETTING(Culling);
IMPLEMENT_BOOLEAN_SETTING(LockCullCamera);
bool CGameView::GetConstrainCameraEnabled() const
{
return m->CameraController->GetConstrainCamera();
}
void CGameView::SetConstrainCameraEnabled(bool enabled)
{
m->CameraController->SetConstrainCamera(enabled);
}
#undef IMPLEMENT_BOOLEAN_SETTING
CGameView::CGameView(CGame *pGame):
m(new CGameViewImpl(pGame))
{
m->CullCamera = m->ViewCamera;
g_Renderer.GetSceneRenderer().SetSceneCamera(m->ViewCamera, m->CullCamera);
}
CGameView::~CGameView()
{
UnloadResources();
delete m;
}
void CGameView::SetViewport(const SViewPort& vp)
{
m->CameraController->SetViewport(vp);
}
CObjectManager& CGameView::GetObjectManager()
{
return m->ObjectManager;
}
CCamera* CGameView::GetCamera()
{
return &m->ViewCamera;
}
CCinemaManager* CGameView::GetCinema()
{
return &m->CinemaManager;
}
CLOSTexture& CGameView::GetLOSTexture()
{
return m->LOSTexture;
}
CTerritoryTexture& CGameView::GetTerritoryTexture()
{
return m->TerritoryTexture;
}
CMiniMapTexture& CGameView::GetMiniMapTexture()
{
return m->MiniMapTexture;
}
int CGameView::Initialize()
{
m->CameraController->LoadConfig();
return 0;
}
void CGameView::RegisterInit()
{
// CGameView init
RegMemFun(this, &CGameView::Initialize, L"CGameView init", 1);
RegMemFun(g_TexMan.GetSingletonPtr(), &CTerrainTextureManager::LoadTerrainTextures, L"LoadTerrainTextures", 60);
}
void CGameView::BeginFrame()
{
if (m->LockCullCamera == false)
{
// Set up cull camera
m->CullCamera = m->ViewCamera;
}
g_Renderer.GetSceneRenderer().SetSceneCamera(m->ViewCamera, m->CullCamera);
- CheckLightEnv();
-
m->Game->CachePlayerColors();
}
void CGameView::Render()
{
g_Renderer.GetSceneRenderer().RenderScene(g_Renderer.GetDeviceCommandContext(), *this);
}
///////////////////////////////////////////////////////////
// This callback is part of the Scene interface
// Submit all objects visible in the given frustum
void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
{
{
PROFILE3("submit terrain");
CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain();
float waterHeight = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight + 0.001f;
const ssize_t patchesPerSide = pTerrain->GetPatchesPerSide();
// find out which patches will be drawn
for (ssize_t j=0; jGetPatch(i,j); // can't fail
// If the patch is underwater, calculate a bounding box that also contains the water plane
CBoundingBoxAligned bounds = patch->GetWorldBounds();
if(bounds[1].Y < waterHeight)
bounds[1].Y = waterHeight;
if (!m->Culling || frustum.IsBoxVisible(bounds))
c->Submit(patch);
}
}
}
m->Game->GetSimulation2()->RenderSubmit(*c, frustum, m->Culling);
}
-
-void CGameView::CheckLightEnv()
-{
- if (m->CachedLightEnv == g_LightEnv)
- return;
-
- m->CachedLightEnv = g_LightEnv;
- CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain();
-
- if (!pTerrain)
- return;
-
- PROFILE("update light env");
- pTerrain->MakeDirty(RENDERDATA_UPDATE_COLOR);
-
- const std::vector& units = m->Game->GetWorld()->GetUnitManager().GetUnits();
- for (size_t i = 0; i < units.size(); ++i)
- units[i]->GetModel().SetDirtyRec(RENDERDATA_UPDATE_COLOR);
-}
-
-
void CGameView::UnloadResources()
{
g_TexMan.UnloadTerrainTextures();
g_Renderer.GetSceneRenderer().GetWaterManager().UnloadWaterTextures();
}
void CGameView::Update(const float deltaRealTime)
{
m->MiniMapTexture.Update(deltaRealTime);
// If camera movement is being handled by the touch-input system,
// then we should stop to avoid conflicting with it
if (g_TouchInput.IsEnabled())
return;
if (!g_app_has_focus)
return;
m->CinemaManager.Update(deltaRealTime);
if (m->CinemaManager.IsEnabled())
return;
m->CameraController->Update(deltaRealTime);
}
CVector3D CGameView::GetCameraPivot() const
{
return m->CameraController->GetCameraPivot();
}
CVector3D CGameView::GetCameraPosition() const
{
return m->CameraController->GetCameraPosition();
}
CVector3D CGameView::GetCameraRotation() const
{
return m->CameraController->GetCameraRotation();
}
float CGameView::GetCameraZoom() const
{
return m->CameraController->GetCameraZoom();
}
void CGameView::SetCamera(const CVector3D& pos, float rotX, float rotY, float zoom)
{
m->CameraController->SetCamera(pos, rotX, rotY, zoom);
}
void CGameView::MoveCameraTarget(const CVector3D& target)
{
m->CameraController->MoveCameraTarget(target);
}
void CGameView::ResetCameraTarget(const CVector3D& target)
{
m->CameraController->ResetCameraTarget(target);
}
void CGameView::FollowEntity(entity_id_t entity, bool firstPerson)
{
m->CameraController->FollowEntity(entity, firstPerson);
}
entity_id_t CGameView::GetFollowedEntity()
{
return m->CameraController->GetFollowedEntity();
}
InReaction game_view_handler(const SDL_Event_* ev)
{
// put any events that must be processed even if inactive here
if (!g_app_has_focus || !g_Game || !g_Game->IsGameStarted() || g_Game->GetView()->GetCinema()->IsEnabled())
return IN_PASS;
CGameView *pView=g_Game->GetView();
return pView->HandleEvent(ev);
}
InReaction CGameView::HandleEvent(const SDL_Event_* ev)
{
switch(ev->ev.type)
{
case SDL_HOTKEYPRESS:
{
std::string hotkey = static_cast(ev->ev.user.data1);
CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
if (hotkey == "wireframe")
{
if (g_XmppClient && g_rankedGame == true)
break;
else if (sceneRenderer.GetModelRenderMode() == SOLID)
{
sceneRenderer.SetTerrainRenderMode(EDGED_FACES);
sceneRenderer.SetWaterRenderMode(EDGED_FACES);
sceneRenderer.SetModelRenderMode(EDGED_FACES);
sceneRenderer.SetOverlayRenderMode(EDGED_FACES);
}
else if (sceneRenderer.GetModelRenderMode() == EDGED_FACES)
{
sceneRenderer.SetTerrainRenderMode(WIREFRAME);
sceneRenderer.SetWaterRenderMode(WIREFRAME);
sceneRenderer.SetModelRenderMode(WIREFRAME);
sceneRenderer.SetOverlayRenderMode(WIREFRAME);
}
else
{
sceneRenderer.SetTerrainRenderMode(SOLID);
sceneRenderer.SetWaterRenderMode(SOLID);
sceneRenderer.SetModelRenderMode(SOLID);
sceneRenderer.SetOverlayRenderMode(SOLID);
}
return IN_HANDLED;
}
}
}
return m->CameraController->HandleEvent(ev);
}
Index: ps/trunk/source/graphics/GameView.h
===================================================================
--- ps/trunk/source/graphics/GameView.h (revision 26248)
+++ ps/trunk/source/graphics/GameView.h (revision 26249)
@@ -1,103 +1,100 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* 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 .
*/
#ifndef INCLUDED_GAMEVIEW
#define INCLUDED_GAMEVIEW
#include "renderer/Scene.h"
#include "simulation2/system/Entity.h"
#include "lib/input.h" // InReaction - can't forward-declare enum
class CCamera;
class CCinemaManager;
class CGame;
class CObjectManager;
class CVector3D;
struct SViewPort;
class CGameViewImpl;
class CGameView : private Scene
{
NONCOPYABLE(CGameView);
public:
CGameView(CGame *pGame);
~CGameView();
void SetViewport(const SViewPort& vp);
void RegisterInit();
int Initialize();
/**
* Updates all the view information (i.e. rotate camera, scroll, whatever). This will *not* change any
* World information - only the *presentation*.
*
* @param deltaRealTime Elapsed real time since the last frame.
*/
void Update(const float deltaRealTime);
void BeginFrame();
void Render();
InReaction HandleEvent(const SDL_Event_* ev);
CVector3D GetCameraPivot() const;
CVector3D GetCameraPosition() const;
CVector3D GetCameraRotation() const;
float GetCameraZoom() const;
void SetCamera(const CVector3D& pos, float rotX, float rotY, float zoom);
void MoveCameraTarget(const CVector3D& target);
void ResetCameraTarget(const CVector3D& target);
void FollowEntity(entity_id_t entity, bool firstPerson);
entity_id_t GetFollowedEntity();
#define DECLARE_BOOLEAN_SETTING(NAME) \
bool Get##NAME##Enabled() const; \
void Set##NAME##Enabled(bool Enabled);
DECLARE_BOOLEAN_SETTING(Culling);
DECLARE_BOOLEAN_SETTING(LockCullCamera);
DECLARE_BOOLEAN_SETTING(ConstrainCamera);
#undef DECLARE_BOOLEAN_SETTING
CCamera* GetCamera();
CCinemaManager* GetCinema();
CObjectManager& GetObjectManager();
// Implementations of Scene
void EnumerateObjects(const CFrustum& frustum, SceneCollector* c) override;
CLOSTexture& GetLOSTexture() override;
CTerritoryTexture& GetTerritoryTexture() override;
CMiniMapTexture& GetMiniMapTexture() override;
private:
// Unloads all graphics resources loaded by RegisterInit.
void UnloadResources();
- // Checks whether lighting environment has changed and update vertex data if necessary.
- void CheckLightEnv();
-
CGameViewImpl* m;
};
extern InReaction game_view_handler(const SDL_Event_* ev);
#endif // INCLUDED_GAMEVIEW
Index: ps/trunk/source/graphics/Model.h
===================================================================
--- ps/trunk/source/graphics/Model.h (revision 26248)
+++ ps/trunk/source/graphics/Model.h (revision 26249)
@@ -1,306 +1,298 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* 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 .
*/
/*
* Mesh object with texture and skinning information
*/
#ifndef INCLUDED_MODEL
#define INCLUDED_MODEL
#include "graphics/Material.h"
#include "graphics/MeshManager.h"
#include "graphics/ModelAbstract.h"
#include
struct SPropPoint;
class CObjectEntry;
class CSkeletonAnim;
class CSkeletonAnimDef;
class CSkeletonAnimManager;
class CSimulation2;
#define MODELFLAG_CASTSHADOWS (1<<0)
#define MODELFLAG_NOLOOPANIMATION (1<<1)
#define MODELFLAG_SILHOUETTE_DISPLAY (1<<2)
#define MODELFLAG_SILHOUETTE_OCCLUDER (1<<3)
#define MODELFLAG_IGNORE_LOS (1<<4)
#define MODELFLAG_FLOATONWATER (1<<5)
///////////////////////////////////////////////////////////////////////////////
// CModel: basically, a mesh object - holds the texturing and skinning
// information for a model in game
class CModel : public CModelAbstract
{
NONCOPYABLE(CModel);
public:
struct Prop
{
Prop() : m_MinHeight(0.f), m_MaxHeight(0.f), m_Point(0), m_Model(0), m_ObjectEntry(0), m_Hidden(false), m_Selectable(true) {}
float m_MinHeight;
float m_MaxHeight;
/**
* Location of the prop point within its parent model, relative to either a bone in the parent model or to the
* parent model's origin. See the documentation for @ref SPropPoint for more details.
* @see SPropPoint
*/
const SPropPoint* m_Point;
/**
* Pointer to the model associated with this prop. Note that the transform matrix held by this model is the full object-to-world
* space transform, taking into account all parent model positioning (see @ref CModel::ValidatePosition for positioning logic).
* @see CModel::ValidatePosition
*/
CModelAbstract* m_Model;
CObjectEntry* m_ObjectEntry;
bool m_Hidden; ///< Should this prop be temporarily removed from rendering?
bool m_Selectable; /// < should this prop count in the selection size?
};
public:
// constructor
CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation);
// destructor
~CModel();
/// Dynamic cast
virtual CModel* ToCModel()
{
return this;
}
// setup model from given geometry
bool InitModel(const CModelDefPtr& modeldef);
// update this model's state; 'time' is the absolute time since the start of the animation, in MS
void UpdateTo(float time);
// get the model's geometry data
const CModelDefPtr& GetModelDef() { return m_pModelDef; }
// set the model's material
void SetMaterial(const CMaterial &material);
// set the model's player ID, recursively through props
void SetPlayerID(player_id_t id);
// set the models mod color
virtual void SetShadingColor(const CColor& color);
// get the model's material
CMaterial& GetMaterial() { return m_Material; }
// set the given animation as the current animation on this model
bool SetAnimation(CSkeletonAnim* anim, bool once = false);
// get the currently playing animation, if any
CSkeletonAnim* GetAnimation() const { return m_Anim; }
// set the animation state to be the same as from another; both models should
// be compatible types (same type of skeleton)
void CopyAnimationFrom(CModel* source);
// set object flags
void SetFlags(int flags) { m_Flags=flags; }
// get object flags
int GetFlags() const { return m_Flags; }
// add object flags, recursively through props
void AddFlagsRec(int flags);
// remove shadow casting and receiving, recursively through props
// TODO: replace with more generic shader define + flags setting
void RemoveShadowsRec();
- // recurse down tree setting dirty bits
- virtual void SetDirtyRec(int dirtyflags) {
- SetDirty(dirtyflags);
- for (size_t i=0;iSetDirtyRec(dirtyflags);
- }
- }
-
virtual void SetTerrainDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1)
{
for (size_t i = 0; i < m_Props.size(); ++i)
m_Props[i].m_Model->SetTerrainDirty(i0, j0, i1, j1);
}
virtual void SetEntityVariable(const std::string& name, float value)
{
for (size_t i = 0; i < m_Props.size(); ++i)
m_Props[i].m_Model->SetEntityVariable(name, value);
}
// --- WORLD/OBJECT SPACE BOUNDS -----------------------------------------------------------------
/// Overridden to calculate both the world-space and object-space bounds of this model, and stores the result in
/// m_Bounds and m_ObjectBounds, respectively.
virtual void CalcBounds();
/// Returns the object-space bounds for this model, excluding its children.
const CBoundingBoxAligned& GetObjectBounds()
{
RecalculateBoundsIfNecessary(); // recalculates both object-space and world-space bounds if necessary
return m_ObjectBounds;
}
virtual const CBoundingBoxAligned GetWorldBoundsRec(); // reimplemented here
/// Auxiliary method; calculates object space bounds of this model, based solely on vertex positions, and stores
/// the result in m_ObjectBounds. Called by CalcBounds (instead of CalcAnimatedObjectBounds) if it has been determined
/// that the object-space bounds are static.
void CalcStaticObjectBounds();
/// Auxiliary method; calculate object-space bounds encompassing all vertex positions for given animation, and stores
/// the result in m_ObjectBounds. Called by CalcBounds (instead of CalcStaticBounds) if it has been determined that the
/// object-space bounds need to take animations into account.
void CalcAnimatedObjectBounds(CSkeletonAnimDef* anim,CBoundingBoxAligned& result);
// --- SELECTION BOX/BOUNDS ----------------------------------------------------------------------
/// Reimplemented here since proper models should participate in selection boxes.
virtual const CBoundingBoxAligned GetObjectSelectionBoundsRec();
/**
* Set transform of this object.
*
* @note In order to ensure that all child props are updated properly,
* you must call ValidatePosition().
*/
virtual void SetTransform(const CMatrix3D& transform);
/**
* Return whether this is a skinned/skeletal model. If it is, Get*BoneMatrices()
* will return valid non-NULL arrays.
*/
bool IsSkinned() { return (m_BoneMatrices != NULL); }
// return the models bone matrices; 16-byte aligned for SSE reads
const CMatrix3D* GetAnimatedBoneMatrices() {
ENSURE(m_PositionValid);
return m_BoneMatrices;
}
/**
* Load raw animation frame animation from given file, and build an
* animation specific to this model.
* @param pathname animation file to load
* @param name animation name (e.g. "idle")
* @param ID specific ID of the animation, to sync with props
* @param frequency influences the random choices
* @param speed animation speed as a factor of the default animation speed
* @param actionpos offset of 'action' event, in range [0, 1]
* @param actionpos2 offset of 'action2' event, in range [0, 1]
* @param sound offset of 'sound' event, in range [0, 1]
* @return new animation, or NULL on error
*/
CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, const CStr& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos);
/**
* Add a prop to the model on the given point.
*/
void AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry, float minHeight = 0.f, float maxHeight = 0.f, bool selectable = true);
/**
* Add a prop to the model on the given point, and treat it as the ammo prop.
* The prop will be hidden by default.
*/
void AddAmmoProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry);
/**
* Show the ammo prop (if any), and hide any other props on that prop point.
*/
void ShowAmmoProp();
/**
* Hide the ammo prop (if any), and show any other props on that prop point.
*/
void HideAmmoProp();
/**
* Find the first prop used for ammo, by this model or its own props.
*/
CModelAbstract* FindFirstAmmoProp();
// return prop list
std::vector& GetProps() { return m_Props; }
const std::vector& GetProps() const { return m_Props; }
// return a clone of this model
virtual CModelAbstract* Clone() const;
/**
* Ensure that both the transformation and the bone
* matrices are correct for this model and all its props.
*/
virtual void ValidatePosition();
/**
* Mark this model's position and bone matrices,
* and all props' positions as invalid.
*/
virtual void InvalidatePosition();
private:
// delete anything allocated by the model
void ReleaseData();
// Needed for terrain aligned props
CSimulation2& m_Simulation;
// object flags
int m_Flags;
// model's material
CMaterial m_Material;
// pointer to the model's raw 3d data
CModelDefPtr m_pModelDef;
// object space bounds of model - accounts for bounds of all possible animations
// that can play on a model. Not always up-to-date - currently CalcBounds()
// updates it when necessary.
CBoundingBoxAligned m_ObjectBounds;
// animation currently playing on this model, if any
CSkeletonAnim* m_Anim;
// time (in MS) into the current animation
float m_AnimTime;
/**
* Current state of all bones on this model; null if associated modeldef isn't skeletal.
* Props may attach to these bones by means of the SPropPoint::m_BoneIndex field; in this case their
* transformation matrix held is relative to the bone transformation (see @ref SPropPoint and
* @ref CModel::ValidatePosition).
*
* @see SPropPoint
*/
CMatrix3D* m_BoneMatrices;
// list of current props on model
std::vector m_Props;
/**
* The prop point to which the ammo prop is attached, or NULL if none
*/
const SPropPoint* m_AmmoPropPoint;
/**
* If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop
*/
size_t m_AmmoLoadedProp;
// manager object which can load animations for us
CSkeletonAnimManager& m_SkeletonAnimManager;
};
#endif
Index: ps/trunk/source/graphics/ModelAbstract.h
===================================================================
--- ps/trunk/source/graphics/ModelAbstract.h (revision 26248)
+++ ps/trunk/source/graphics/ModelAbstract.h (revision 26249)
@@ -1,195 +1,192 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* 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 .
*/
#ifndef INCLUDED_MODELABSTRACT
#define INCLUDED_MODELABSTRACT
#include "graphics/Color.h"
#include "graphics/RenderableObject.h"
#include "maths/BoundingBoxOriented.h"
#include "simulation2/helpers/Player.h"
class CModelDummy;
class CModel;
class CModelDecal;
class CModelParticleEmitter;
/**
* Abstract base class for graphical objects that are used by units,
* or as props attached to other CModelAbstract objects.
* This includes meshes, terrain decals, and sprites.
* These objects exist in a tree hierarchy.
*/
class CModelAbstract : public CRenderableObject
{
NONCOPYABLE(CModelAbstract);
public:
/**
* Describes a custom selection shape to be used for a model's selection box instead of the default
* recursive bounding boxes.
*/
struct CustomSelectionShape
{
enum EType {
/// The selection shape is determined by an oriented box of custom, user-specified size.
BOX,
/// The selection shape is determined by a cylinder of custom, user-specified size.
CYLINDER
};
EType m_Type; ///< Type of shape.
float m_Size0; ///< Box width if @ref BOX, or radius if @ref CYLINDER
float m_Size1; ///< Box depth if @ref BOX, or radius if @ref CYLINDER
float m_Height; ///< Box height if @ref BOX, cylinder height if @ref CYLINDER
};
public:
CModelAbstract()
: m_Parent(NULL), m_PositionValid(false), m_ShadingColor(1, 1, 1, 1), m_PlayerID(INVALID_PLAYER),
m_SelectionBoxValid(false), m_CustomSelectionShape(NULL)
{ }
~CModelAbstract()
{
delete m_CustomSelectionShape; // allocated and set externally by CCmpVisualActor, but our responsibility to clean up
}
virtual CModelAbstract* Clone() const = 0;
/// Dynamic cast
virtual CModelDummy* ToCModelDummy() { return nullptr; }
/// Dynamic cast
virtual CModel* ToCModel() { return nullptr; }
/// Dynamic cast
virtual CModelDecal* ToCModelDecal() { return nullptr; }
/// Dynamic cast
virtual CModelParticleEmitter* ToCModelParticleEmitter() { return nullptr; }
// (This dynamic casting is a bit ugly, but we won't have many subclasses
// and this seems the easiest way to integrate with other code that wants
// type-specific processing)
- /// Calls SetDirty on this model and all child objects.
- virtual void SetDirtyRec(int dirtyflags) = 0;
-
/// Returns world space bounds of this object and all child objects.
virtual const CBoundingBoxAligned GetWorldBoundsRec() { return GetWorldBounds(); } // default implementation
/**
* Returns the world-space selection box of this model. Used primarily for hittesting against against a selection ray. The
* returned selection box may be empty to indicate that it does not wish to participate in the selection process.
*/
virtual const CBoundingBoxOriented& GetSelectionBox();
virtual void InvalidateBounds()
{
m_BoundsValid = false;
// a call to this method usually means that the model's transform has changed, i.e. it has moved or rotated, so we'll also
// want to update the selection box accordingly regardless of the shape it is built from.
m_SelectionBoxValid = false;
}
/// Sets a custom selection shape as described by a @p descriptor. Argument may be NULL
/// if you wish to keep the default behaviour of using the recursively-calculated bounding boxes.
void SetCustomSelectionShape(CustomSelectionShape* descriptor)
{
if (m_CustomSelectionShape != descriptor)
{
m_CustomSelectionShape = descriptor;
m_SelectionBoxValid = false; // update the selection box when it is next requested
}
}
/**
* Returns the (object-space) bounds that should be used to construct a selection box for this model and its children.
* May return an empty bound to indicate that this model and its children should not be selectable themselves, or should
* not be included in its parent model's selection box. This method is used for constructing the default selection boxes,
* as opposed to any boxes of custom shape specified by @ref m_CustomSelectionShape.
*
* If you wish your model type to be included in selection boxes, override this method and have it return the object-space
* bounds of itself, augmented recursively (via this method) with the object-space selection bounds of its children.
*/
virtual const CBoundingBoxAligned GetObjectSelectionBoundsRec() { return CBoundingBoxAligned::EMPTY; }
/**
* Called when terrain has changed in the given inclusive bounds.
* Might call SetDirty if the change affects this model.
*/
virtual void SetTerrainDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1) = 0;
/**
* Called when the entity tries to set some variable to affect the display of this model
* and/or its child objects.
*/
virtual void SetEntityVariable(const std::string& UNUSED(name), float UNUSED(value)) { }
/**
* Ensure that both the transformation and the bone matrices are correct for this model and all its props.
*/
virtual void ValidatePosition() = 0;
/**
* Mark this model's position and bone matrices, and all props' positions as invalid.
*/
virtual void InvalidatePosition() = 0;
virtual void SetPlayerID(player_id_t id) { m_PlayerID = id; }
// get the model's player ID; initial default is INVALID_PLAYER
virtual player_id_t GetPlayerID() const { return m_PlayerID; }
virtual void SetShadingColor(const CColor& color) { m_ShadingColor = color; }
virtual CColor GetShadingColor() const { return m_ShadingColor; }
protected:
void CalcSelectionBox();
public:
/// If non-null, points to the model that we are attached to.
CModelAbstract* m_Parent;
/// True if both transform and and bone matrices are valid.
bool m_PositionValid;
player_id_t m_PlayerID;
/// Modulating color
CColor m_ShadingColor;
protected:
/// Selection box for this model.
CBoundingBoxOriented m_SelectionBox;
/// Is the current selection box valid?
bool m_SelectionBoxValid;
/// Pointer to a descriptor for a custom-defined selection box shape. If no custom selection box is required, this is NULL
/// and the standard recursive-bounding-box-based selection box is used. Otherwise, a custom selection box described by this
/// field will be used.
/// @see SetCustomSelectionShape
CustomSelectionShape* m_CustomSelectionShape;
};
#endif // INCLUDED_MODELABSTRACT
Index: ps/trunk/source/graphics/ModelDummy.h
===================================================================
--- ps/trunk/source/graphics/ModelDummy.h (revision 26248)
+++ ps/trunk/source/graphics/ModelDummy.h (revision 26249)
@@ -1,45 +1,44 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* 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 .
*/
#ifndef INCLUDED_MODELDUMMY
#define INCLUDED_MODELDUMMY
#include "graphics/ModelAbstract.h"
/**
* Empty placeholder ModelAbstract implementation, to render nothing.
*/
class CModelDummy final : public CModelAbstract
{
NONCOPYABLE(CModelDummy);
public:
CModelDummy() = default;
virtual ~CModelDummy() = default;
virtual CModelAbstract* Clone() const { return new CModelDummy(); }
virtual CModelDummy* ToCModelDummy() { return this; }
virtual void CalcBounds() {};
- virtual void SetDirtyRec(int) {};
virtual void SetTerrainDirty(ssize_t, ssize_t, ssize_t, ssize_t) {}
virtual void ValidatePosition() {};
virtual void InvalidatePosition() {};
};
#endif // INCLUDED_MODELDUMMY
Index: ps/trunk/source/graphics/ParticleEmitter.h
===================================================================
--- ps/trunk/source/graphics/ParticleEmitter.h (revision 26248)
+++ ps/trunk/source/graphics/ParticleEmitter.h (revision 26249)
@@ -1,209 +1,204 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* 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 .
*/
#ifndef INCLUDED_PARTICLEEMITTER
#define INCLUDED_PARTICLEEMITTER
#include "graphics/ModelAbstract.h"
#include "graphics/ParticleEmitterType.h"
#include "maths/Quaternion.h"
#include "renderer/VertexArray.h"
#include