/src/ogre/OgreMain/src/OgreBillboardParticleRenderer.cpp
Line | Count | Source |
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-2014 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 | | #include "OgreStableHeaders.h" |
29 | | |
30 | | #include "OgreBillboardParticleRenderer.h" |
31 | | #include "OgreParticle.h" |
32 | | #include "OgreBillboard.h" |
33 | | |
34 | | namespace Ogre { |
35 | | static String rendererTypeName = "billboard"; |
36 | | |
37 | | /** Command object for billboard type (see ParamCommand).*/ |
38 | | class _OgrePrivate CmdBillboardType : public ParamCommand |
39 | | { |
40 | | public: |
41 | | String doGet(const void* target) const override; |
42 | | void doSet(void* target, const String& val) override; |
43 | | }; |
44 | | /** Command object for billboard origin (see ParamCommand).*/ |
45 | | class _OgrePrivate CmdBillboardOrigin : public ParamCommand |
46 | | { |
47 | | public: |
48 | | String doGet(const void* target) const override; |
49 | | void doSet(void* target, const String& val) override; |
50 | | }; |
51 | | /** Command object for billboard rotation type (see ParamCommand).*/ |
52 | | class _OgrePrivate CmdBillboardRotationType : public ParamCommand |
53 | | { |
54 | | public: |
55 | | String doGet(const void* target) const override; |
56 | | void doSet(void* target, const String& val) override; |
57 | | }; |
58 | | /** Command object for common direction (see ParamCommand).*/ |
59 | | class _OgrePrivate CmdCommonDirection : public ParamCommand |
60 | | { |
61 | | public: |
62 | | String doGet(const void* target) const override; |
63 | | void doSet(void* target, const String& val) override; |
64 | | }; |
65 | | /** Command object for common up-vector (see ParamCommand).*/ |
66 | | class _OgrePrivate CmdCommonUpVector : public ParamCommand |
67 | | { |
68 | | public: |
69 | | String doGet(const void* target) const override; |
70 | | void doSet(void* target, const String& val) override; |
71 | | }; |
72 | | /** Command object for point rendering (see ParamCommand).*/ |
73 | | class _OgrePrivate CmdPointRendering : public ParamCommand |
74 | | { |
75 | | public: |
76 | | String doGet(const void* target) const override; |
77 | | void doSet(void* target, const String& val) override; |
78 | | }; |
79 | | /** Command object for accurate facing(see ParamCommand).*/ |
80 | | class _OgrePrivate CmdAccurateFacing : public ParamCommand |
81 | | { |
82 | | public: |
83 | | String doGet(const void* target) const override; |
84 | | void doSet(void* target, const String& val) override; |
85 | | }; |
86 | | static CmdBillboardType msBillboardTypeCmd; |
87 | | static CmdBillboardOrigin msBillboardOriginCmd; |
88 | | static CmdBillboardRotationType msBillboardRotationTypeCmd; |
89 | | static CmdCommonDirection msCommonDirectionCmd; |
90 | | static CmdCommonUpVector msCommonUpVectorCmd; |
91 | | static CmdPointRendering msPointRenderingCmd; |
92 | | static CmdAccurateFacing msAccurateFacingCmd; |
93 | | |
94 | | static class CmdStacksAndSlices : public ParamCommand |
95 | | { |
96 | | public: |
97 | | String doGet(const void* target) const override |
98 | 0 | { |
99 | 0 | return StringConverter::toString( |
100 | 0 | static_cast<const BillboardParticleRenderer*>(target)->getTextureStacksAndSlices()); |
101 | 0 | } |
102 | | void doSet(void* target, const String& val) override |
103 | 0 | { |
104 | 0 | Vector2 tmp = StringConverter::parseVector2(val); |
105 | 0 | static_cast<BillboardParticleRenderer*>(target)->setTextureStacksAndSlices(tmp.x, tmp.y); |
106 | 0 | } |
107 | | } msStacksAndSlicesCmd; |
108 | | |
109 | | //----------------------------------------------------------------------- |
110 | 0 | BillboardParticleRenderer::BillboardParticleRenderer() : mStacksSlices(1, 1) |
111 | 0 | { |
112 | 0 | if (createParamDictionary("BillboardParticleRenderer")) |
113 | 0 | { |
114 | 0 | ParamDictionary* dict = getParamDictionary(); |
115 | 0 | dict->addParameter(ParameterDef("billboard_type", |
116 | 0 | "The type of billboard to use. 'point' means a simulated spherical particle, " |
117 | 0 | "'oriented_common' means all particles in the set are oriented around common_direction, " |
118 | 0 | "'oriented_self' means particles are oriented around their own direction, " |
119 | 0 | "'perpendicular_common' means all particles are perpendicular to common_direction, " |
120 | 0 | "and 'perpendicular_self' means particles are perpendicular to their own direction.", |
121 | 0 | PT_STRING), |
122 | 0 | &msBillboardTypeCmd); |
123 | |
|
124 | 0 | dict->addParameter(ParameterDef("billboard_origin", |
125 | 0 | "This setting controls the fine tuning of where a billboard appears in relation to it's position. " |
126 | 0 | "Possible value are: 'top_left', 'top_center', 'top_right', 'center_left', 'center', 'center_right', " |
127 | 0 | "'bottom_left', 'bottom_center' and 'bottom_right'. Default value is 'center'.", |
128 | 0 | PT_STRING), |
129 | 0 | &msBillboardOriginCmd); |
130 | |
|
131 | 0 | dict->addParameter(ParameterDef("billboard_rotation_type", |
132 | 0 | "This setting controls the billboard rotation type. " |
133 | 0 | "'vertex' means rotate the billboard's vertices around their facing direction." |
134 | 0 | "'texcoord' means rotate the billboard's texture coordinates. Default value is 'texcoord'.", |
135 | 0 | PT_STRING), |
136 | 0 | &msBillboardRotationTypeCmd); |
137 | |
|
138 | 0 | dict->addParameter(ParameterDef("common_direction", |
139 | 0 | "Only useful when billboard_type is oriented_common or perpendicular_common. " |
140 | 0 | "When billboard_type is oriented_common, this parameter sets the common orientation for " |
141 | 0 | "all particles in the set (e.g. raindrops may all be oriented downwards). " |
142 | 0 | "When billboard_type is perpendicular_common, this parameter sets the perpendicular vector for " |
143 | 0 | "all particles in the set (e.g. an aureola around the player and parallel to the ground).", |
144 | 0 | PT_VECTOR3), |
145 | 0 | &msCommonDirectionCmd); |
146 | |
|
147 | 0 | dict->addParameter(ParameterDef("common_up_vector", |
148 | 0 | "Only useful when billboard_type is perpendicular_self or perpendicular_common. This " |
149 | 0 | "parameter sets the common up-vector for all particles in the set (e.g. an aureola around " |
150 | 0 | "the player and parallel to the ground).", |
151 | 0 | PT_VECTOR3), |
152 | 0 | &msCommonUpVectorCmd); |
153 | 0 | dict->addParameter(ParameterDef("point_rendering", |
154 | 0 | "Set whether or not particles will use point rendering " |
155 | 0 | "rather than manually generated quads. This allows for faster " |
156 | 0 | "rendering of point-oriented particles although introduces some " |
157 | 0 | "limitations too such as requiring a common particle size." |
158 | 0 | "Possible values are 'true' or 'false'.", |
159 | 0 | PT_BOOL), |
160 | 0 | &msPointRenderingCmd); |
161 | 0 | dict->addParameter(ParameterDef("accurate_facing", |
162 | 0 | "Set whether or not particles will be oriented to the camera " |
163 | 0 | "based on the relative position to the camera rather than just " |
164 | 0 | "the camera direction. This is more accurate but less optimal. " |
165 | 0 | "Cannot be combined with point rendering.", |
166 | 0 | PT_BOOL), |
167 | 0 | &msAccurateFacingCmd); |
168 | |
|
169 | 0 | dict->addParameter(ParameterDef("texture_sheet_size", "", |
170 | 0 | PT_UNSIGNED_INT), |
171 | 0 | &msStacksAndSlicesCmd); |
172 | 0 | } |
173 | | |
174 | | // Create billboard set |
175 | 0 | mBillboardSet = OGRE_NEW BillboardSet("", 0, true); |
176 | | // World-relative axes |
177 | 0 | mBillboardSet->setBillboardsInWorldSpace(true); |
178 | 0 | } |
179 | | //----------------------------------------------------------------------- |
180 | | BillboardParticleRenderer::~BillboardParticleRenderer() |
181 | 0 | { |
182 | | // mBillboardSet is never actually attached to a node, we just passthrough |
183 | | // based on the particle system's attachment. So manually notify that it's |
184 | | // no longer attached. |
185 | 0 | mBillboardSet->_notifyAttached(0); |
186 | 0 | OGRE_DELETE mBillboardSet; |
187 | 0 | } |
188 | | //----------------------------------------------------------------------- |
189 | | const String& BillboardParticleRenderer::getType(void) const |
190 | 0 | { |
191 | 0 | return rendererTypeName; |
192 | 0 | } |
193 | | //----------------------------------------------------------------------- |
194 | | void BillboardParticleRenderer::_updateRenderQueue(RenderQueue* queue, |
195 | | std::vector<Particle*>& currentParticles, bool cullIndividually) |
196 | 0 | { |
197 | 0 | OgreProfile("BillboardParticleRenderer"); |
198 | 0 | mBillboardSet->setCullIndividually(cullIndividually); |
199 | | |
200 | | // Update billboard set geometry |
201 | 0 | mBillboardSet->beginBillboards(currentParticles.size()); |
202 | 0 | Billboard bb; |
203 | |
|
204 | 0 | for (Particle* p : currentParticles) |
205 | 0 | { |
206 | 0 | bb.mPosition = p->mPosition; |
207 | |
|
208 | 0 | if (mBillboardSet->getBillboardType() == BBT_ORIENTED_SELF || |
209 | 0 | mBillboardSet->getBillboardType() == BBT_PERPENDICULAR_SELF) |
210 | 0 | { |
211 | | // Normalise direction vector |
212 | 0 | bb.mDirection = p->mDirection; |
213 | 0 | bb.mDirection.normalise(); |
214 | 0 | } |
215 | 0 | bb.mColour = p->mColour; |
216 | 0 | bb.mRotation = p->mRotation; |
217 | 0 | bb.mTexcoordIndex = p->mTexcoordIndex; |
218 | 0 | bb.mOwnDimensions = p->mWidth != mBillboardSet->getDefaultWidth() || |
219 | 0 | p->mHeight != mBillboardSet->getDefaultHeight(); |
220 | 0 | if (bb.mOwnDimensions) |
221 | 0 | { |
222 | 0 | bb.mWidth = p->mWidth; |
223 | 0 | bb.mHeight = p->mHeight; |
224 | 0 | } |
225 | 0 | mBillboardSet->injectBillboard(bb); |
226 | 0 | } |
227 | |
|
228 | 0 | mBillboardSet->endBillboards(); |
229 | | |
230 | | // Update the queue |
231 | 0 | mBillboardSet->_updateRenderQueue(queue); |
232 | 0 | } |
233 | | |
234 | | void BillboardParticleRenderer::_notifyBoundingBox(const AxisAlignedBox& aabb) |
235 | 0 | { |
236 | 0 | mBillboardSet->setBounds(aabb, Math::boundingRadiusFromAABB(aabb)); |
237 | 0 | } |
238 | | //----------------------------------------------------------------------- |
239 | | //----------------------------------------------------------------------- |
240 | | //----------------------------------------------------------------------- |
241 | | const String& BillboardParticleRendererFactory::getType() const |
242 | 0 | { |
243 | 0 | return rendererTypeName; |
244 | 0 | } |
245 | | //----------------------------------------------------------------------- |
246 | | ParticleSystemRenderer* BillboardParticleRendererFactory::createInstance( |
247 | | const String& name ) |
248 | 0 | { |
249 | 0 | return OGRE_NEW BillboardParticleRenderer(); |
250 | 0 | } |
251 | | //----------------------------------------------------------------------- |
252 | | //----------------------------------------------------------------------- |
253 | | String CmdBillboardType::doGet(const void* target) const |
254 | 0 | { |
255 | 0 | BillboardType t = static_cast<const BillboardParticleRenderer*>(target)->getBillboardType(); |
256 | 0 | switch(t) |
257 | 0 | { |
258 | 0 | case BBT_POINT: |
259 | 0 | return "point"; |
260 | 0 | break; |
261 | 0 | case BBT_ORIENTED_COMMON: |
262 | 0 | return "oriented_common"; |
263 | 0 | break; |
264 | 0 | case BBT_ORIENTED_SELF: |
265 | 0 | return "oriented_self"; |
266 | 0 | break; |
267 | 0 | case BBT_PERPENDICULAR_COMMON: |
268 | 0 | return "perpendicular_common"; |
269 | 0 | case BBT_PERPENDICULAR_SELF: |
270 | 0 | return "perpendicular_self"; |
271 | 0 | } |
272 | | // Compiler nicety |
273 | 0 | return ""; |
274 | 0 | } |
275 | | void CmdBillboardType::doSet(void* target, const String& val) |
276 | 0 | { |
277 | 0 | BillboardType t; |
278 | 0 | if (val == "point") |
279 | 0 | { |
280 | 0 | t = BBT_POINT; |
281 | 0 | } |
282 | 0 | else if (val == "oriented_common") |
283 | 0 | { |
284 | 0 | t = BBT_ORIENTED_COMMON; |
285 | 0 | } |
286 | 0 | else if (val == "oriented_self") |
287 | 0 | { |
288 | 0 | t = BBT_ORIENTED_SELF; |
289 | 0 | } |
290 | 0 | else if (val == "perpendicular_common") |
291 | 0 | { |
292 | 0 | t = BBT_PERPENDICULAR_COMMON; |
293 | 0 | } |
294 | 0 | else if (val == "perpendicular_self") |
295 | 0 | { |
296 | 0 | t = BBT_PERPENDICULAR_SELF; |
297 | 0 | } |
298 | 0 | else |
299 | 0 | { |
300 | 0 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
301 | 0 | "Invalid billboard_type '" + val + "'", |
302 | 0 | "ParticleSystem::CmdBillboardType::doSet"); |
303 | 0 | } |
304 | | |
305 | 0 | static_cast<BillboardParticleRenderer*>(target)->setBillboardType(t); |
306 | 0 | } |
307 | | //----------------------------------------------------------------------- |
308 | | String CmdBillboardOrigin::doGet(const void* target) const |
309 | 0 | { |
310 | 0 | BillboardOrigin o = static_cast<const BillboardParticleRenderer*>(target)->getBillboardOrigin(); |
311 | 0 | switch (o) |
312 | 0 | { |
313 | 0 | case BBO_TOP_LEFT: |
314 | 0 | return "top_left"; |
315 | 0 | case BBO_TOP_CENTER: |
316 | 0 | return "top_center"; |
317 | 0 | case BBO_TOP_RIGHT: |
318 | 0 | return "top_right"; |
319 | 0 | case BBO_CENTER_LEFT: |
320 | 0 | return "center_left"; |
321 | 0 | case BBO_CENTER: |
322 | 0 | return "center"; |
323 | 0 | case BBO_CENTER_RIGHT: |
324 | 0 | return "center_right"; |
325 | 0 | case BBO_BOTTOM_LEFT: |
326 | 0 | return "bottom_left"; |
327 | 0 | case BBO_BOTTOM_CENTER: |
328 | 0 | return "bottom_center"; |
329 | 0 | case BBO_BOTTOM_RIGHT: |
330 | 0 | return "bottom_right"; |
331 | 0 | } |
332 | | // Compiler nicety |
333 | 0 | return BLANKSTRING; |
334 | 0 | } |
335 | | void CmdBillboardOrigin::doSet(void* target, const String& val) |
336 | 0 | { |
337 | 0 | BillboardOrigin o; |
338 | 0 | if (val == "top_left") |
339 | 0 | o = BBO_TOP_LEFT; |
340 | 0 | else if (val =="top_center") |
341 | 0 | o = BBO_TOP_CENTER; |
342 | 0 | else if (val =="top_right") |
343 | 0 | o = BBO_TOP_RIGHT; |
344 | 0 | else if (val =="center_left") |
345 | 0 | o = BBO_CENTER_LEFT; |
346 | 0 | else if (val =="center") |
347 | 0 | o = BBO_CENTER; |
348 | 0 | else if (val =="center_right") |
349 | 0 | o = BBO_CENTER_RIGHT; |
350 | 0 | else if (val =="bottom_left") |
351 | 0 | o = BBO_BOTTOM_LEFT; |
352 | 0 | else if (val =="bottom_center") |
353 | 0 | o = BBO_BOTTOM_CENTER; |
354 | 0 | else if (val =="bottom_right") |
355 | 0 | o = BBO_BOTTOM_RIGHT; |
356 | 0 | else |
357 | 0 | { |
358 | 0 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
359 | 0 | "Invalid billboard_origin '" + val + "'", |
360 | 0 | "ParticleSystem::CmdBillboardOrigin::doSet"); |
361 | 0 | } |
362 | | |
363 | 0 | static_cast<BillboardParticleRenderer*>(target)->setBillboardOrigin(o); |
364 | 0 | } |
365 | | //----------------------------------------------------------------------- |
366 | | String CmdBillboardRotationType::doGet(const void* target) const |
367 | 0 | { |
368 | 0 | BillboardRotationType r = static_cast<const BillboardParticleRenderer*>(target)->getBillboardRotationType(); |
369 | 0 | switch(r) |
370 | 0 | { |
371 | 0 | case BBR_VERTEX: |
372 | 0 | return "vertex"; |
373 | 0 | case BBR_TEXCOORD: |
374 | 0 | return "texcoord"; |
375 | 0 | } |
376 | | // Compiler nicety |
377 | 0 | return BLANKSTRING; |
378 | 0 | } |
379 | | void CmdBillboardRotationType::doSet(void* target, const String& val) |
380 | 0 | { |
381 | 0 | BillboardRotationType r; |
382 | 0 | if (val == "vertex") |
383 | 0 | r = BBR_VERTEX; |
384 | 0 | else if (val == "texcoord") |
385 | 0 | r = BBR_TEXCOORD; |
386 | 0 | else |
387 | 0 | { |
388 | 0 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
389 | 0 | "Invalid billboard_rotation_type '" + val + "'", |
390 | 0 | "ParticleSystem::CmdBillboardRotationType::doSet"); |
391 | 0 | } |
392 | | |
393 | 0 | static_cast<BillboardParticleRenderer*>(target)->setBillboardRotationType(r); |
394 | 0 | } |
395 | | //----------------------------------------------------------------------- |
396 | | String CmdCommonDirection::doGet(const void* target) const |
397 | 0 | { |
398 | 0 | return StringConverter::toString( |
399 | 0 | static_cast<const BillboardParticleRenderer*>(target)->getCommonDirection() ); |
400 | 0 | } |
401 | | void CmdCommonDirection::doSet(void* target, const String& val) |
402 | 0 | { |
403 | 0 | static_cast<BillboardParticleRenderer*>(target)->setCommonDirection( |
404 | 0 | StringConverter::parseVector3(val)); |
405 | 0 | } |
406 | | //----------------------------------------------------------------------- |
407 | | String CmdCommonUpVector::doGet(const void* target) const |
408 | 0 | { |
409 | 0 | return StringConverter::toString( |
410 | 0 | static_cast<const BillboardParticleRenderer*>(target)->getCommonUpVector() ); |
411 | 0 | } |
412 | | void CmdCommonUpVector::doSet(void* target, const String& val) |
413 | 0 | { |
414 | 0 | static_cast<BillboardParticleRenderer*>(target)->setCommonUpVector( |
415 | 0 | StringConverter::parseVector3(val)); |
416 | 0 | } |
417 | | //----------------------------------------------------------------------- |
418 | | String CmdPointRendering::doGet(const void* target) const |
419 | 0 | { |
420 | 0 | return StringConverter::toString( |
421 | 0 | static_cast<const BillboardParticleRenderer*>(target)->isPointRenderingEnabled() ); |
422 | 0 | } |
423 | | void CmdPointRendering::doSet(void* target, const String& val) |
424 | 0 | { |
425 | 0 | static_cast<BillboardParticleRenderer*>(target)->setPointRenderingEnabled( |
426 | 0 | StringConverter::parseBool(val)); |
427 | 0 | } |
428 | | //----------------------------------------------------------------------- |
429 | | String CmdAccurateFacing::doGet(const void* target) const |
430 | 0 | { |
431 | 0 | return StringConverter::toString( |
432 | 0 | static_cast<const BillboardParticleRenderer*>(target)->getUseAccurateFacing() ); |
433 | 0 | } |
434 | | void CmdAccurateFacing::doSet(void* target, const String& val) |
435 | 0 | { |
436 | 0 | static_cast<BillboardParticleRenderer*>(target)->setUseAccurateFacing( |
437 | 0 | StringConverter::parseBool(val)); |
438 | 0 | } |
439 | | |
440 | | } |
441 | | |
442 | | |