Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : /*
19 : * Base class for renderable objects
20 : */
21 :
22 : #ifndef INCLUDED_RENDERABLEOBJECT
23 : #define INCLUDED_RENDERABLEOBJECT
24 :
25 :
26 : #include "maths/BoundingBoxAligned.h"
27 : #include "maths/Matrix3D.h"
28 :
29 :
30 : // dirty flags - used as notification to the renderer that some bit of data
31 : // need updating
32 : #define RENDERDATA_UPDATE_VERTICES (1<<1)
33 : #define RENDERDATA_UPDATE_INDICES (1<<2)
34 :
35 :
36 : ///////////////////////////////////////////////////////////////////////////////
37 : // CRenderData: base class of all the renderer's renderdata classes - the
38 : // derived class stores necessary information for rendering an object of a
39 : // particular type
40 : class CRenderData
41 : {
42 : public:
43 0 : CRenderData() : m_UpdateFlags(0) {}
44 0 : virtual ~CRenderData() {}
45 :
46 : int m_UpdateFlags;
47 : };
48 :
49 : ///////////////////////////////////////////////////////////////////////////////
50 : // CRenderableObject: base class of all renderable objects - patches, models,
51 : // sprites, etc; stores position and bound information, and a pointer to
52 : // some renderdata necessary for the renderer to actually render it
53 : class CRenderableObject
54 : {
55 : NONCOPYABLE(CRenderableObject);
56 :
57 : public:
58 : // constructor
59 269 : CRenderableObject() : m_RenderData(0), m_BoundsValid(false)
60 : {
61 269 : m_Transform.SetIdentity();
62 269 : }
63 : // destructor
64 269 : virtual ~CRenderableObject() { delete m_RenderData; }
65 :
66 : // set object transform
67 0 : virtual void SetTransform(const CMatrix3D& transform)
68 : {
69 0 : if (m_Transform == transform)
70 0 : return;
71 : // store transform, calculate inverse
72 0 : m_Transform=transform;
73 0 : m_Transform.GetInverse(m_InvTransform);
74 : // normal recalculation likely required on transform change; flag it
75 0 : SetDirty(RENDERDATA_UPDATE_VERTICES);
76 : // need to rebuild world space bounds
77 0 : InvalidateBounds();
78 : }
79 : // get object to world space transform
80 0 : const CMatrix3D& GetTransform() const { return m_Transform; }
81 : // get world to object space transform
82 0 : const CMatrix3D& GetInvTransform() const { return m_InvTransform; }
83 :
84 : // mark some part of the renderdata as dirty, and requiring
85 : // an update on next render
86 1024 : void SetDirty(u32 dirtyflags)
87 : {
88 1024 : if (m_RenderData)
89 0 : m_RenderData->m_UpdateFlags |= dirtyflags;
90 1024 : }
91 :
92 : /**
93 : * (Re)calculates and stores any bounds or bound-dependent data for this object. At this abstraction level, this is only the world-space
94 : * bounds stored in @ref m_WorldBounds; subclasses may use this method to (re)compute additional bounds if necessary, or any data that
95 : * depends on the bounds. Whenever bound-dependent data is requested through a public interface, @ref RecalculateBoundsIfNecessary should
96 : * be called first to ensure bound correctness, which will in turn call this method if it turns out that they're outdated.
97 : *
98 : * @see m_BoundsValid
99 : * @see RecalculateBoundsIfNecessary
100 : */
101 : virtual void CalcBounds() = 0;
102 :
103 : /// Returns the world-space axis-aligned bounds of this object.
104 0 : const CBoundingBoxAligned& GetWorldBounds()
105 : {
106 0 : RecalculateBoundsIfNecessary();
107 0 : return m_WorldBounds;
108 : }
109 :
110 : /**
111 : * Marks the bounds as invalid. This will trigger @ref RecalculateBoundsIfNecessary to recompute any bound-related data the next time
112 : * any bound-related data is requested through a public interface -- at least, if you've made sure to call it before returning the
113 : * stored data.
114 : */
115 269 : virtual void InvalidateBounds() { m_BoundsValid = false; }
116 :
117 : // Set the object renderdata and free previous renderdata, if any.
118 0 : void SetRenderData(CRenderData* renderdata)
119 : {
120 0 : delete m_RenderData;
121 0 : m_RenderData = renderdata;
122 0 : }
123 :
124 : /// Return object renderdata - can be null if renderer hasn't yet created the renderdata
125 0 : CRenderData* GetRenderData() { return m_RenderData; }
126 :
127 : protected:
128 : /// Factored out so subclasses don't need to repeat this if they want to add additional getters for bounds-related methods
129 : /// (since they'll have to make sure to recalc the bounds if necessary before they return it).
130 0 : void RecalculateBoundsIfNecessary()
131 : {
132 0 : if (!m_BoundsValid) {
133 0 : CalcBounds();
134 0 : m_BoundsValid = true;
135 : }
136 0 : }
137 :
138 : protected:
139 : /// World-space bounds of this object
140 : CBoundingBoxAligned m_WorldBounds;
141 : // local->world space transform
142 : CMatrix3D m_Transform;
143 : // world->local space transform
144 : CMatrix3D m_InvTransform;
145 : // object renderdata
146 : CRenderData* m_RenderData;
147 :
148 : /**
149 : * Remembers whether any bounds need to be recalculated. Subclasses that add any data that depends on the bounds should
150 : * take care to consider the validity of the bounds and recalculate their data when necessary -- overriding @ref CalcBounds
151 : * to do so would be a good idea, since it's already set up to be called by @ref RecalculateBoundsIfNecessary whenever the
152 : * bounds are marked as invalid. The latter should then be called before returning any bounds or bounds-derived data through
153 : * a public interface (see the implementation of @ref GetWorldBounds for an example).
154 : *
155 : * @see CalcBounds
156 : * @see InvalidateBounds
157 : * @see RecalculateBoundsIfNecessary
158 : */
159 : bool m_BoundsValid;
160 : };
161 :
162 : #endif
|