1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 29 // Thanks to Vincent Cantin (karmaGfa) for the original implementation of this 30 // class, although it has now been mostly rewritten 31 32 #ifndef _BillboardChain_H__ 33 #define _BillboardChain_H__ 34 35 #include "OgrePrerequisites.h" 36 37 #include "OgreMovableObject.h" 38 #include "OgreRenderable.h" 39 #include "OgreResourceGroupManager.h" 40 #include "OgreHeaderPrefix.h" 41 42 namespace Ogre { 43 44 /** \addtogroup Core 45 * @{ 46 */ 47 /** \addtogroup Effects 48 * @{ 49 */ 50 51 /** Allows the rendering of a chain of connected billboards. 52 @remarks 53 A billboard chain operates much like a traditional billboard, i.e. its 54 segments always face the camera; the difference being that instead of 55 a set of disconnected quads, the elements in this class are connected 56 together in a chain which must always stay in a continuous strip. This 57 kind of effect is useful for creating effects such as trails, beams, 58 lightning effects, etc. 59 @par 60 A single instance of this class can actually render multiple separate 61 chain segments in a single render operation, provided they all use the 62 same material. To clarify the terminology: a 'segment' is a separate 63 sub-part of the chain with its own start and end (called the 'head' 64 and the 'tail'). An 'element' is a single position / colour / texcoord 65 entry in a segment. You can add items to the head of a chain, and 66 remove them from the tail, very efficiently. Each segment has a max 67 size, and if adding an element to the segment would exceed this size, 68 the tail element is automatically removed and re-used as the new item 69 on the head. 70 @par 71 This class has no auto-updating features to do things like alter the 72 colour of the elements or to automatically add / remove elements over 73 time - you have to do all this yourself as a user of the class. 74 Subclasses can however be used to provide this kind of behaviour 75 automatically. @see RibbonTrail 76 */ 77 class _OgreExport BillboardChain : public MovableObject, public Renderable 78 { 79 80 public: 81 82 /** Contains the data of an element of the BillboardChain. 83 */ 84 class _OgreExport Element 85 { 86 87 public: 88 89 Element(); 90 91 Element(const Vector3 &position, 92 Real width, 93 Real texCoord, 94 const ColourValue &colour, 95 const Quaternion &orientation); 96 97 Vector3 position; 98 Real width; 99 /// U or V texture coord depending on options 100 Real texCoord; 101 ColourValue colour; 102 103 /// Only used when mFaceCamera == false 104 Quaternion orientation; 105 }; 106 typedef vector<Element>::type ElementList; 107 108 /** Constructor (don't use directly, use factory) 109 @param name The name to give this object 110 @param maxElements The maximum number of elements per chain 111 @param numberOfChains The number of separate chain segments contained in this object 112 @param useTextureCoords If true, use texture coordinates from the chain elements 113 @param useColours If true, use vertex colours from the chain elements 114 @param dynamic If true, buffers are created with the intention of being updated 115 */ 116 BillboardChain(const String& name, size_t maxElements = 20, size_t numberOfChains = 1, 117 bool useTextureCoords = true, bool useColours = true, bool dynamic = true); 118 /// Destructor 119 virtual ~BillboardChain(); 120 121 /** Set the maximum number of chain elements per chain 122 */ 123 virtual void setMaxChainElements(size_t maxElements); 124 /** Get the maximum number of chain elements per chain 125 */ getMaxChainElements(void)126 virtual size_t getMaxChainElements(void) const { return mMaxElementsPerChain; } 127 /** Set the number of chain segments (this class can render multiple chains 128 at once using the same material). 129 */ 130 virtual void setNumberOfChains(size_t numChains); 131 /** Get the number of chain segments (this class can render multiple chains 132 at once using the same material). 133 */ getNumberOfChains(void)134 virtual size_t getNumberOfChains(void) const { return mChainCount; } 135 136 /** Sets whether texture coordinate information should be included in the 137 final buffers generated. 138 @note You must use either texture coordinates or vertex colour since the 139 vertices have no normals and without one of these there is no source of 140 colour for the vertices. 141 */ 142 virtual void setUseTextureCoords(bool use); 143 /** Gets whether texture coordinate information should be included in the 144 final buffers generated. 145 */ getUseTextureCoords(void)146 virtual bool getUseTextureCoords(void) const { return mUseTexCoords; } 147 148 /** The direction in which texture coordinates from elements of the 149 chain are used. 150 */ 151 enum TexCoordDirection 152 { 153 /// Tex coord in elements is treated as the 'u' texture coordinate 154 TCD_U, 155 /// Tex coord in elements is treated as the 'v' texture coordinate 156 TCD_V 157 }; 158 /** Sets the direction in which texture coords specified on each element 159 are deemed to run along the length of the chain. 160 @param dir The direction, default is TCD_U. 161 */ 162 virtual void setTextureCoordDirection(TexCoordDirection dir); 163 /** Gets the direction in which texture coords specified on each element 164 are deemed to run. 165 */ getTextureCoordDirection(void)166 virtual TexCoordDirection getTextureCoordDirection(void) { return mTexCoordDir; } 167 168 /** Set the range of the texture coordinates generated across the width of 169 the chain elements. 170 @param start Start coordinate, default 0.0 171 @param end End coordinate, default 1.0 172 */ 173 virtual void setOtherTextureCoordRange(Real start, Real end); 174 /** Get the range of the texture coordinates generated across the width of 175 the chain elements. 176 */ getOtherTextureCoordRange(void)177 virtual const Real* getOtherTextureCoordRange(void) const { return mOtherTexCoordRange; } 178 179 /** Sets whether vertex colour information should be included in the 180 final buffers generated. 181 @note You must use either texture coordinates or vertex colour since the 182 vertices have no normals and without one of these there is no source of 183 colour for the vertices. 184 */ 185 virtual void setUseVertexColours(bool use); 186 /** Gets whether vertex colour information should be included in the 187 final buffers generated. 188 */ getUseVertexColours(void)189 virtual bool getUseVertexColours(void) const { return mUseVertexColour; } 190 191 /** Sets whether or not the buffers created for this object are suitable 192 for dynamic alteration. 193 */ 194 virtual void setDynamic(bool dyn); 195 196 /** Gets whether or not the buffers created for this object are suitable 197 for dynamic alteration. 198 */ getDynamic(void)199 virtual bool getDynamic(void) const { return mDynamic; } 200 201 /** Add an element to the 'head' of a chain. 202 @remarks 203 If this causes the number of elements to exceed the maximum elements 204 per chain, the last element in the chain (the 'tail') will be removed 205 to allow the additional element to be added. 206 @param chainIndex The index of the chain 207 @param billboardChainElement The details to add 208 */ 209 virtual void addChainElement(size_t chainIndex, 210 const Element& billboardChainElement); 211 /** Remove an element from the 'tail' of a chain. 212 @param chainIndex The index of the chain 213 */ 214 virtual void removeChainElement(size_t chainIndex); 215 /** Update the details of an existing chain element. 216 @param chainIndex The index of the chain 217 @param elementIndex The element index within the chain, measured from 218 the 'head' of the chain 219 @param billboardChainElement The details to set 220 */ 221 virtual void updateChainElement(size_t chainIndex, size_t elementIndex, 222 const Element& billboardChainElement); 223 /** Get the detail of a chain element. 224 @param chainIndex The index of the chain 225 @param elementIndex The element index within the chain, measured from 226 the 'head' of the chain 227 */ 228 virtual const Element& getChainElement(size_t chainIndex, size_t elementIndex) const; 229 230 /** Returns the number of chain elements. */ 231 virtual size_t getNumChainElements(size_t chainIndex) const; 232 233 /** Remove all elements of a given chain (but leave the chain intact). */ 234 virtual void clearChain(size_t chainIndex); 235 /** Remove all elements from all chains (but leave the chains themselves intact). */ 236 virtual void clearAllChains(void); 237 238 /** Sets whether the billboard should always be facing the camera or a custom direction 239 set by each point element. 240 @remarks 241 Billboards facing the camera are useful for smoke trails, light beams, etc by 242 simulating a cylinder. However, because of this property, wide trails can cause 243 several artefacts unless the head is properly covered. 244 Therefore, non-camera-facing billboards are much more convenient for leaving big 245 trails of movement from thin objects, for example a sword swing as seen in many 246 fighting games. 247 @param faceCamera True to be always facing the camera (Default value: True) 248 @param normalVector Only used when faceCamera == false. Must be a non-zero vector. 249 This vector is the "point of reference" for each point orientation. For example, 250 if normalVector is Vector3::UNIT_Z, and the point's orientation is an identity 251 matrix, the segment corresponding to that point will be facing towards UNIT_Z 252 This vector is internally normalized. 253 */ 254 void setFaceCamera( bool faceCamera, const Vector3 &normalVector=Vector3::UNIT_X ); 255 256 /// Get the material name in use getMaterialName(void)257 virtual const String& getMaterialName(void) const { return mMaterialName; } 258 /// Set the material name to use for rendering 259 virtual void setMaterialName( const String& name, const String& groupName = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME ); 260 261 262 // Overridden members follow 263 Real getSquaredViewDepth(const Camera* cam) const; 264 Real getBoundingRadius(void) const; 265 const AxisAlignedBox& getBoundingBox(void) const; 266 const MaterialPtr& getMaterial(void) const; 267 const String& getMovableType(void) const; 268 void _updateRenderQueue(RenderQueue *); 269 void getRenderOperation(RenderOperation &); 270 virtual bool preRender(SceneManager* sm, RenderSystem* rsys); 271 void getWorldTransforms(Matrix4 *) const; 272 const LightList& getLights(void) const; 273 /// @copydoc MovableObject::visitRenderables 274 void visitRenderables(Renderable::Visitor* visitor, 275 bool debugRenderables = false); 276 277 278 279 protected: 280 281 /// Maximum length of each chain 282 size_t mMaxElementsPerChain; 283 /// Number of chains 284 size_t mChainCount; 285 /// Use texture coords? 286 bool mUseTexCoords; 287 /// Use vertex colour? 288 bool mUseVertexColour; 289 /// Dynamic use? 290 bool mDynamic; 291 /// Vertex data 292 VertexData* mVertexData; 293 /// Index data (to allow multiple unconnected chains) 294 IndexData* mIndexData; 295 /// Is the vertex declaration dirty? 296 bool mVertexDeclDirty; 297 /// Do the buffers need recreating? 298 bool mBuffersNeedRecreating; 299 /// Do the bounds need redefining? 300 mutable bool mBoundsDirty; 301 /// Is the index buffer dirty? 302 bool mIndexContentDirty; 303 /// Is the vertex buffer dirty? 304 bool mVertexContentDirty; 305 /// AABB 306 mutable AxisAlignedBox mAABB; 307 /// Bounding radius 308 mutable Real mRadius; 309 /// Material 310 String mMaterialName; 311 MaterialPtr mMaterial; 312 /// Texture coord direction 313 TexCoordDirection mTexCoordDir; 314 /// Other texture coord range 315 Real mOtherTexCoordRange[2]; 316 /// Camera last used to build the vertex buffer 317 Camera *mVertexCameraUsed; 318 /// When true, the billboards always face the camera 319 bool mFaceCamera; 320 /// Used when mFaceCamera == false; determines the billboard's "normal". i.e. 321 /// when the orientation is identity, the billboard is perpendicular to this 322 /// vector 323 Vector3 mNormalBase; 324 325 326 /// The list holding the chain elements 327 ElementList mChainElementList; 328 329 /** Simple struct defining a chain segment by referencing a subset of 330 the preallocated buffer (which will be mMaxElementsPerChain * mChainCount 331 long), by it's chain index, and a head and tail value which describe 332 the current chain. The buffer subset wraps at mMaxElementsPerChain 333 so that head and tail can move freely. head and tail are inclusive, 334 when the chain is empty head and tail are filled with high-values. 335 */ 336 struct ChainSegment 337 { 338 /// The start of this chains subset of the buffer 339 size_t start; 340 /// The 'head' of the chain, relative to start 341 size_t head; 342 /// The 'tail' of the chain, relative to start 343 size_t tail; 344 }; 345 typedef vector<ChainSegment>::type ChainSegmentList; 346 ChainSegmentList mChainSegmentList; 347 348 /// Setup the STL collections 349 virtual void setupChainContainers(void); 350 /// Setup vertex declaration 351 virtual void setupVertexDeclaration(void); 352 /// Setup buffers 353 virtual void setupBuffers(void); 354 /// Update the contents of the vertex buffer 355 virtual void updateVertexBuffer(Camera* cam); 356 /// Update the contents of the index buffer 357 virtual void updateIndexBuffer(void); 358 virtual void updateBoundingBox(void) const; 359 360 /// Chain segment has no elements 361 static const size_t SEGMENT_EMPTY; 362 }; 363 364 365 /** Factory object for creating BillboardChain instances */ 366 class _OgreExport BillboardChainFactory : public MovableObjectFactory 367 { 368 protected: 369 MovableObject* createInstanceImpl( const String& name, const NameValuePairList* params); 370 public: BillboardChainFactory()371 BillboardChainFactory() {} ~BillboardChainFactory()372 ~BillboardChainFactory() {} 373 374 static String FACTORY_TYPE_NAME; 375 376 const String& getType(void) const; 377 void destroyInstance( MovableObject* obj); 378 379 }; 380 381 /** @} */ 382 /** @} */ 383 384 } // namespace 385 386 #include "OgreHeaderSuffix.h" 387 388 #endif 389 390 391