1 /*-------------------------------------------------------------------------------------
2 Copyright (c) 2006 John Judnich
3 
4 This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
5 Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
6 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
7 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
8 3. This notice may not be removed or altered from any source distribution.
9 -------------------------------------------------------------------------------------*/
10 #ifndef __BatchedGeometry_H__
11 #define __BatchedGeometry_H__
12 
13 #include <OgrePrerequisites.h>
14 #include <OgreMovableObject.h>
15 #include <OgreSceneNode.h>
16 #include <OgreMaterialManager.h>
17 
18 namespace Forests
19 {
20    //--------------------------------------------------------------------------
21    /// A "lightweight" version of Ogre::StaticGeometry, which gives you a little
22    /// more control over the batch materials, etc.
23    class BatchedGeometry : public Ogre::MovableObject
24    {
25    public:
26       //--------------------------------------------------------------------------
27       /// Visible chunk of geometry.
28       class SubBatch : public Ogre::Renderable
29       {
30       protected:
31          // A structure defining the desired position/orientation/scale of a batched mesh. The
32          // SubMesh is not specified since that can be determined by which MeshQueue this belongs to.
33          struct QueuedMesh
34          {
35             QueuedMesh(Ogre::SubMesh* sm, const Ogre::Vector3 &pos, const Ogre::Quaternion &ori,
36                const Ogre::Vector3 &scl, const Ogre::ColourValue &clr, void *userData_ = 0) :
subMeshQueuedMesh37             subMesh     (sm),
38                position    (pos),
39                orientation (ori),
40                scale       (scl),
41                color       (clr),
42                userData    (userData_)
43             {
44                // empty
45             }
46 
47             Ogre::SubMesh*    subMesh;
48             Ogre::Vector3     position;
49             Ogre::Quaternion  orientation;
50             Ogre::Vector3     scale;
51             Ogre::ColourValue color;
52             void*             userData;
53          };
54 
55          /// Queue of meshes for build batch of geometry
56          typedef std::vector<QueuedMesh> TMeshQueue;
57 
58 
59          // Function section
60 
61       public:
62          /// Constructor
63          SubBatch(BatchedGeometry *parent, Ogre::SubEntity *ent);
64          /// Destructor
65          ~SubBatch();
66 
67          ///
68          void addSubEntity(Ogre::SubEntity *ent, const Ogre::Vector3 &position,
69             const Ogre::Quaternion &orientation, const Ogre::Vector3 &scale,
70             const Ogre::ColourValue &color = Ogre::ColourValue::White, void* userData = NULL);
71 
72          /// Build (assemble a vertex/index buffers) geometry for rendering
73          virtual void build();
74          ///
75          void clear();
76 
77          ///
78          void addSelfToRenderQueue(Ogre::RenderQueueGroup *rqg);
79          ///
80          void getRenderOperation(Ogre::RenderOperation& op);
81          ///
82          Ogre::Real getSquaredViewDepth(const Ogre::Camera* cam) const;
83          ///
84          const Ogre::LightList& getLights(void) const;
85 
86          ///
setMaterial(Ogre::MaterialPtr & mat)87          void setMaterial(Ogre::MaterialPtr &mat)                 { m_ptrMaterial = mat; }
88          void setMaterialName(const Ogre::String &mat, const Ogre::String &rg =
89             Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
90          {
91 			 m_ptrMaterial = Ogre::MaterialManager::getSingleton().getByName(mat, rg).staticCast<Ogre::Material>();
92          }
93 
94          /// Get material name. Be careful, resource group name missing
getMaterialName()95          const Ogre::String& getMaterialName() const              { return m_ptrMaterial->getName(); }
getTechnique()96          Ogre::Technique *getTechnique() const                    { return m_pBestTechnique; }
getMaterial(void)97          const Ogre::MaterialPtr& getMaterial(void) const         { return m_ptrMaterial; }
getWorldTransforms(Ogre::Matrix4 * xform)98          void getWorldTransforms(Ogre::Matrix4* xform) const      { *xform = m_pParentGeom->_getParentNodeFullTransform(); }
getWorldOrientation(void)99          const Ogre::Quaternion& getWorldOrientation(void) const  { return m_pParentGeom->m_pSceneNode->_getDerivedOrientation(); }
getWorldPosition(void)100          const Ogre::Vector3& getWorldPosition(void) const        { return m_pParentGeom->m_pSceneNode->_getDerivedPosition(); }
castsShadows(void)101          bool castsShadows(void) const                            { return m_pParentGeom->getCastShadows(); }
102 
103          // internal fuctions
104       private:
105          /// Build vertex of QueuedMesh if it have identity orientation
106          static void _buildIdentiryOrientation(const QueuedMesh &queuedMesh, const Ogre::Vector3 &parentGeomCenter,
107             const std::vector<Ogre::VertexDeclaration::VertexElementList> &vertexBufferElements, std::vector<Ogre::uchar*> &vertexBuffers,
108             Ogre::VertexData *dst);
109          /// Build vertex of QueuedMesh if it have some orientation
110          static void _buildFullTransform(const QueuedMesh &queuedMesh, const Ogre::Vector3 &parentGeomCenter,
111             const std::vector<Ogre::VertexDeclaration::VertexElementList> &vertexBufferElements, std::vector<Ogre::uchar*> &vertexBuffers,
112             Ogre::VertexData *dst);
113 
114 
115          // Data section class SubBatch
116 
117       public:
118          Ogre::VertexData* m_pVertexData;          ///<
119          Ogre::IndexData*  m_pIndexData;           ///<
120 
121       protected:
122          bool              m_Built;                ///<
123          bool              m_RequireVertexColors;  ///<
124          Ogre::SubMesh*    m_pSubMesh;             ///< Ogre::SubMesh for Index/Vertex buffers manipulation
125          BatchedGeometry*  m_pParentGeom;          ///<
126          Ogre::MaterialPtr m_ptrMaterial;          ///<
127          TMeshQueue        m_queueMesh;            ///< The list of meshes to be added to this batch
128 
129       private:
130          Ogre::Technique*  m_pBestTechnique;       ///< Technique recalculated every frame
131 
132       }; // end class SubBatch
133       //-----------------------------------------------------------------------
134 
135       /// Stores a list of GeomBatch'es, using a format string (generated with getGeometryFormatString()) as the key value
136       typedef std::map<Ogre::String, SubBatch*>    TSubBatchMap;
137       typedef Ogre::MapIterator<TSubBatchMap>      TSubBatchIterator;
138       typedef Ogre::ConstMapIterator<TSubBatchMap> TConstSubBatchIterator;
139 
140    public:
141 
142       /// Constructor
143       BatchedGeometry(Ogre::SceneManager *mgr, Ogre::SceneNode *rootSceneNode);
144       ~BatchedGeometry();
145 
getSubBatchIterator()146       TConstSubBatchIterator getSubBatchIterator() const    { return TConstSubBatchIterator(m_mapSubBatch); }
getSubBatchIterator()147       TSubBatchIterator getSubBatchIterator()               { return TSubBatchIterator(m_mapSubBatch); }
148 
149       virtual void addEntity(Ogre::Entity *ent, const Ogre::Vector3 &position,
150          const Ogre::Quaternion &orientation = Ogre::Quaternion::IDENTITY,
151          const Ogre::Vector3 &scale = Ogre::Vector3::UNIT_SCALE,
152          const Ogre::ColourValue &color = Ogre::ColourValue::White);
153 
154       void build();
155       void clear();
156 
157       Ogre::Vector3 _convertToLocal(const Ogre::Vector3 &globalVec) const;
158 
getBoundingBox(void)159       const Ogre::AxisAlignedBox &getBoundingBox(void) const   { return m_boundsAAB; }
getBoundingRadius(void)160       Ogre::Real getBoundingRadius(void) const                 { return m_fRadius; }
161 
162    private:
163       bool isVisible();
164       const Ogre::String& getMovableType(void) const;
visitRenderables(Ogre::Renderable::Visitor * visitor,bool debugRenderables)165       void visitRenderables(Ogre::Renderable::Visitor* visitor, bool debugRenderables) { /* empty */ }
166       void _notifyCurrentCamera(Ogre::Camera *cam);
167       void _updateRenderQueue(Ogre::RenderQueue *queue);
168 
169    protected:
170       static Ogre::String getFormatString(Ogre::SubEntity *ent);
171       static void extractVertexDataFromShared(const Ogre::MeshPtr &mesh);
172 
173 
174       // Data section of BatchedGeometry class
175    protected:
176       bool                    m_Built;
177       bool                    m_BoundsUndefined;
178       Ogre::Vector3           m_vecCenter;
179       Ogre::AxisAlignedBox    m_boundsAAB;
180       TSubBatchMap            m_mapSubBatch;
181       /// Internal matrix for remap vertex type to vertex size instead call VertexElement::getTypeSize
182       static const size_t     s_vertexType2Size[Ogre::VET_COLOUR_ABGR + 1];
183 
184    private:
185       bool                    m_bWithinFarDistance;
186       Ogre::Real              m_fRadius;
187       Ogre::Real              m_fMinDistanceSquared;
188       Ogre::SceneManager*     m_pSceneMgr;
189       Ogre::SceneNode*        m_pSceneNode;
190       Ogre::SceneNode*        m_pParentSceneNode;
191    };
192 
193 }
194 
195 #endif
196