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 // Original author: Tels <http://bloodgate.com>, released as public domain
29 #include "OgreRingEmitter.h"
30 #include "OgreParticle.h"
31 #include "OgreException.h"
32 #include "OgreStringConverter.h"
33 
34 
35 /* Implements an Emitter whose emitting points all lie inside a ring.
36 */
37 
38 namespace Ogre {
39 
40     RingEmitter::CmdInnerX RingEmitter::msCmdInnerX;
41     RingEmitter::CmdInnerY RingEmitter::msCmdInnerY;
42 
43     //-----------------------------------------------------------------------
RingEmitter(ParticleSystem * psys)44     RingEmitter::RingEmitter(ParticleSystem* psys)
45         : AreaEmitter(psys)
46     {
47         if (initDefaults("Ring"))
48         {
49             // Add custom parameters
50             ParamDictionary* pDict = getParamDictionary();
51 
52             pDict->addParameter(ParameterDef("inner_width", "Parametric value describing the proportion of the "
53                 "shape which is hollow.", PT_REAL), &msCmdInnerX);
54             pDict->addParameter(ParameterDef("inner_height", "Parametric value describing the proportion of the "
55                 "shape which is hollow.", PT_REAL), &msCmdInnerY);
56         }
57         // default is half empty
58         setInnerSize(0.5,0.5);
59     }
60     //-----------------------------------------------------------------------
_initParticle(Particle * pParticle)61     void RingEmitter::_initParticle(Particle* pParticle)
62     {
63         Real a, b, x, y, z;
64 
65         // Call superclass
66         AreaEmitter::_initParticle(pParticle);
67         // create a random angle from 0 .. PI*2
68         Radian alpha ( Math::RangeRandom(0,Math::TWO_PI) );
69 
70         // create two random radius values that are bigger than the inner size
71         a = Math::RangeRandom(mInnerSizex,1.0);
72         b = Math::RangeRandom(mInnerSizey,1.0);
73 
74         // with a and b we have defined a random ellipse inside the inner
75         // ellipse and the outer circle (radius 1.0)
76         // with alpha, and a and b we select a random point on this ellipse
77         // and calculate it's coordinates
78         x = a * Math::Sin(alpha);
79         y = b * Math::Cos(alpha);
80         // the height is simple -1 to 1
81         z = Math::SymmetricRandom();
82 
83         // scale the found point to the ring's size and move it
84         // relatively to the center of the emitter point
85 
86         pParticle->position = mPosition +
87          + x * mXRange + y * mYRange + z * mZRange;
88 
89         // Generate complex data by reference
90         genEmissionColour(pParticle->colour);
91         genEmissionDirection( pParticle->position, pParticle->direction );
92         genEmissionVelocity(pParticle->direction);
93 
94         // Generate simpler data
95         pParticle->timeToLive = pParticle->totalTimeToLive = genEmissionTTL();
96 
97     }
98     //-----------------------------------------------------------------------
setInnerSize(Real x,Real y)99     void RingEmitter::setInnerSize(Real x, Real y)
100     {
101         // TODO: should really throw some exception
102         if ((x > 0) && (x < 1.0) &&
103             (y > 0) && (y < 1.0))
104             {
105             mInnerSizex = x;
106             mInnerSizey = y;
107             }
108     }
109     //-----------------------------------------------------------------------
setInnerSizeX(Real x)110     void RingEmitter::setInnerSizeX(Real x)
111     {
112         assert(x > 0 && x < 1.0);
113 
114         mInnerSizex = x;
115     }
116     //-----------------------------------------------------------------------
setInnerSizeY(Real y)117     void RingEmitter::setInnerSizeY(Real y)
118     {
119         assert(y > 0 && y < 1.0);
120 
121         mInnerSizey = y;
122     }
123     //-----------------------------------------------------------------------
getInnerSizeX(void) const124     Real RingEmitter::getInnerSizeX(void) const
125     {
126         return mInnerSizex;
127     }
128     //-----------------------------------------------------------------------
getInnerSizeY(void) const129     Real RingEmitter::getInnerSizeY(void) const
130     {
131         return mInnerSizey;
132     }
133     //-----------------------------------------------------------------------
134     //-----------------------------------------------------------------------
135     // Command objects
136     //-----------------------------------------------------------------------
137     //-----------------------------------------------------------------------
doGet(const void * target) const138     String RingEmitter::CmdInnerX::doGet(const void* target) const
139     {
140         return StringConverter::toString(
141             static_cast<const RingEmitter*>(target)->getInnerSizeX() );
142     }
doSet(void * target,const String & val)143     void RingEmitter::CmdInnerX::doSet(void* target, const String& val)
144     {
145         static_cast<RingEmitter*>(target)->setInnerSizeX(StringConverter::parseReal(val));
146     }
147     //-----------------------------------------------------------------------
doGet(const void * target) const148     String RingEmitter::CmdInnerY::doGet(const void* target) const
149     {
150         return StringConverter::toString(
151             static_cast<const RingEmitter*>(target)->getInnerSizeY() );
152     }
doSet(void * target,const String & val)153     void RingEmitter::CmdInnerY::doSet(void* target, const String& val)
154     {
155         static_cast<RingEmitter*>(target)->setInnerSizeY(StringConverter::parseReal(val));
156     }
157 
158 }
159 
160 
161