1 /* Copyright (C) 2012 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 #define RENDERDATA_UPDATE_COLOR (1<<4) 35 36 37 /////////////////////////////////////////////////////////////////////////////// 38 // CRenderData: base class of all the renderer's renderdata classes - the 39 // derived class stores necessary information for rendering an object of a 40 // particular type 41 class CRenderData 42 { 43 public: CRenderData()44 CRenderData() : m_UpdateFlags(0) {} ~CRenderData()45 virtual ~CRenderData() {} 46 47 int m_UpdateFlags; 48 }; 49 50 /////////////////////////////////////////////////////////////////////////////// 51 // CRenderableObject: base class of all renderable objects - patches, models, 52 // sprites, etc; stores position and bound information, and a pointer to 53 // some renderdata necessary for the renderer to actually render it 54 class CRenderableObject 55 { 56 NONCOPYABLE(CRenderableObject); 57 58 public: 59 // constructor CRenderableObject()60 CRenderableObject() : m_RenderData(0), m_BoundsValid(false) 61 { 62 m_Transform.SetIdentity(); 63 } 64 // destructor ~CRenderableObject()65 virtual ~CRenderableObject() { delete m_RenderData; } 66 67 // set object transform SetTransform(const CMatrix3D & transform)68 virtual void SetTransform(const CMatrix3D& transform) 69 { 70 if (m_Transform == transform) 71 return; 72 // store transform, calculate inverse 73 m_Transform=transform; 74 m_Transform.GetInverse(m_InvTransform); 75 // normal recalculation likely required on transform change; flag it 76 SetDirty(RENDERDATA_UPDATE_VERTICES); 77 // need to rebuild world space bounds 78 InvalidateBounds(); 79 } 80 // get object to world space transform GetTransform()81 const CMatrix3D& GetTransform() const { return m_Transform; } 82 // get world to object space transform GetInvTransform()83 const CMatrix3D& GetInvTransform() const { return m_InvTransform; } 84 85 // mark some part of the renderdata as dirty, and requiring 86 // an update on next render SetDirty(u32 dirtyflags)87 void SetDirty(u32 dirtyflags) 88 { 89 if (m_RenderData) 90 m_RenderData->m_UpdateFlags |= dirtyflags; 91 } 92 93 /** 94 * (Re)calculates and stores any bounds or bound-dependent data for this object. At this abstraction level, this is only the world-space 95 * bounds stored in @ref m_WorldBounds; subclasses may use this method to (re)compute additional bounds if necessary, or any data that 96 * depends on the bounds. Whenever bound-dependent data is requested through a public interface, @ref RecalculateBoundsIfNecessary should 97 * be called first to ensure bound correctness, which will in turn call this method if it turns out that they're outdated. 98 * 99 * @see m_BoundsValid 100 * @see RecalculateBoundsIfNecessary 101 */ 102 virtual void CalcBounds() = 0; 103 104 /// Returns the world-space axis-aligned bounds of this object. GetWorldBounds()105 const CBoundingBoxAligned& GetWorldBounds() 106 { 107 RecalculateBoundsIfNecessary(); 108 return m_WorldBounds; 109 } 110 111 /** 112 * Marks the bounds as invalid. This will trigger @ref RecalculateBoundsIfNecessary to recompute any bound-related data the next time 113 * any bound-related data is requested through a public interface -- at least, if you've made sure to call it before returning the 114 * stored data. 115 */ InvalidateBounds()116 virtual void InvalidateBounds() { m_BoundsValid = false; } 117 118 // Set the object renderdata and free previous renderdata, if any. SetRenderData(CRenderData * renderdata)119 void SetRenderData(CRenderData* renderdata) 120 { 121 delete m_RenderData; 122 m_RenderData = renderdata; 123 } 124 125 /// Return object renderdata - can be null if renderer hasn't yet created the renderdata GetRenderData()126 CRenderData* GetRenderData() { return m_RenderData; } 127 128 protected: 129 /// Factored out so subclasses don't need to repeat this if they want to add additional getters for bounds-related methods 130 /// (since they'll have to make sure to recalc the bounds if necessary before they return it). RecalculateBoundsIfNecessary()131 void RecalculateBoundsIfNecessary() 132 { 133 if (!m_BoundsValid) { 134 CalcBounds(); 135 m_BoundsValid = true; 136 } 137 } 138 139 protected: 140 /// World-space bounds of this object 141 CBoundingBoxAligned m_WorldBounds; 142 // local->world space transform 143 CMatrix3D m_Transform; 144 // world->local space transform 145 CMatrix3D m_InvTransform; 146 // object renderdata 147 CRenderData* m_RenderData; 148 149 /** 150 * Remembers whether any bounds need to be recalculated. Subclasses that add any data that depends on the bounds should 151 * take care to consider the validity of the bounds and recalculate their data when necessary -- overriding @ref CalcBounds 152 * to do so would be a good idea, since it's already set up to be called by @ref RecalculateBoundsIfNecessary whenever the 153 * bounds are marked as invalid. The latter should then be called before returning any bounds or bounds-derived data through 154 * a public interface (see the implementation of @ref GetWorldBounds for an example). 155 * 156 * @see CalcBounds 157 * @see InvalidateBounds 158 * @see RecalculateBoundsIfNecessary 159 */ 160 bool m_BoundsValid; 161 }; 162 163 #endif 164