1
1
forked from 0ad/0ad
0ad/source/graphics/RenderableObject.h
wraitii 330b570ba8 Remove RENDERDATA_UPDATE_COLOR, which is not used, and cleanup.
RENDERDATA_UPDATE_COLOR was used to precompute lightEnv-dependent data
on the CPU. This is no longer done following engine upgrades, and in
particular d7d02a4740 which explictly always did this on the GPU.

ModelAbstract had a 'SetDirtyRec' hack for it because of decals, which
can also be removed. The 'dirty' bit of CRenderableObject is renderdata
for the specific item, never its props, so it never actually needs to be
recursive.

CheckLightEnv is also useless as a result, and removed.

Differential Revision: https://code.wildfiregames.com/D4453
This was SVN commit r26249.
2022-01-25 16:59:29 +00:00

163 lines
5.5 KiB
C++

/* 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/>.
*/
/*
* Base class for renderable objects
*/
#ifndef INCLUDED_RENDERABLEOBJECT
#define INCLUDED_RENDERABLEOBJECT
#include "maths/BoundingBoxAligned.h"
#include "maths/Matrix3D.h"
// dirty flags - used as notification to the renderer that some bit of data
// need updating
#define RENDERDATA_UPDATE_VERTICES (1<<1)
#define RENDERDATA_UPDATE_INDICES (1<<2)
///////////////////////////////////////////////////////////////////////////////
// CRenderData: base class of all the renderer's renderdata classes - the
// derived class stores necessary information for rendering an object of a
// particular type
class CRenderData
{
public:
CRenderData() : m_UpdateFlags(0) {}
virtual ~CRenderData() {}
int m_UpdateFlags;
};
///////////////////////////////////////////////////////////////////////////////
// CRenderableObject: base class of all renderable objects - patches, models,
// sprites, etc; stores position and bound information, and a pointer to
// some renderdata necessary for the renderer to actually render it
class CRenderableObject
{
NONCOPYABLE(CRenderableObject);
public:
// constructor
CRenderableObject() : m_RenderData(0), m_BoundsValid(false)
{
m_Transform.SetIdentity();
}
// destructor
virtual ~CRenderableObject() { delete m_RenderData; }
// set object transform
virtual void SetTransform(const CMatrix3D& transform)
{
if (m_Transform == transform)
return;
// store transform, calculate inverse
m_Transform=transform;
m_Transform.GetInverse(m_InvTransform);
// normal recalculation likely required on transform change; flag it
SetDirty(RENDERDATA_UPDATE_VERTICES);
// need to rebuild world space bounds
InvalidateBounds();
}
// get object to world space transform
const CMatrix3D& GetTransform() const { return m_Transform; }
// get world to object space transform
const CMatrix3D& GetInvTransform() const { return m_InvTransform; }
// mark some part of the renderdata as dirty, and requiring
// an update on next render
void SetDirty(u32 dirtyflags)
{
if (m_RenderData)
m_RenderData->m_UpdateFlags |= dirtyflags;
}
/**
* (Re)calculates and stores any bounds or bound-dependent data for this object. At this abstraction level, this is only the world-space
* bounds stored in @ref m_WorldBounds; subclasses may use this method to (re)compute additional bounds if necessary, or any data that
* depends on the bounds. Whenever bound-dependent data is requested through a public interface, @ref RecalculateBoundsIfNecessary should
* be called first to ensure bound correctness, which will in turn call this method if it turns out that they're outdated.
*
* @see m_BoundsValid
* @see RecalculateBoundsIfNecessary
*/
virtual void CalcBounds() = 0;
/// Returns the world-space axis-aligned bounds of this object.
const CBoundingBoxAligned& GetWorldBounds()
{
RecalculateBoundsIfNecessary();
return m_WorldBounds;
}
/**
* Marks the bounds as invalid. This will trigger @ref RecalculateBoundsIfNecessary to recompute any bound-related data the next time
* any bound-related data is requested through a public interface -- at least, if you've made sure to call it before returning the
* stored data.
*/
virtual void InvalidateBounds() { m_BoundsValid = false; }
// Set the object renderdata and free previous renderdata, if any.
void SetRenderData(CRenderData* renderdata)
{
delete m_RenderData;
m_RenderData = renderdata;
}
/// Return object renderdata - can be null if renderer hasn't yet created the renderdata
CRenderData* GetRenderData() { return m_RenderData; }
protected:
/// Factored out so subclasses don't need to repeat this if they want to add additional getters for bounds-related methods
/// (since they'll have to make sure to recalc the bounds if necessary before they return it).
void RecalculateBoundsIfNecessary()
{
if (!m_BoundsValid) {
CalcBounds();
m_BoundsValid = true;
}
}
protected:
/// World-space bounds of this object
CBoundingBoxAligned m_WorldBounds;
// local->world space transform
CMatrix3D m_Transform;
// world->local space transform
CMatrix3D m_InvTransform;
// object renderdata
CRenderData* m_RenderData;
/**
* Remembers whether any bounds need to be recalculated. Subclasses that add any data that depends on the bounds should
* take care to consider the validity of the bounds and recalculate their data when necessary -- overriding @ref CalcBounds
* to do so would be a good idea, since it's already set up to be called by @ref RecalculateBoundsIfNecessary whenever the
* bounds are marked as invalid. The latter should then be called before returning any bounds or bounds-derived data through
* a public interface (see the implementation of @ref GetWorldBounds for an example).
*
* @see CalcBounds
* @see InvalidateBounds
* @see RecalculateBoundsIfNecessary
*/
bool m_BoundsValid;
};
#endif