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