Coverage Report

Created: 2025-10-10 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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