f@0
|
1 #include "ParticleController.h"
|
f@0
|
2 #include "cinder/Rand.h"
|
f@0
|
3
|
f@0
|
4 #include <type_traits>
|
f@0
|
5
|
f@0
|
6 using namespace ci;
|
f@0
|
7 using std::list;
|
f@0
|
8
|
f@0
|
9 ParticleController::ParticleController() :
|
f@0
|
10 mNumParticles( 0 )
|
f@0
|
11
|
f@0
|
12 {
|
f@0
|
13 mParticles.assign( kMaxParticles, Particle() );
|
f@0
|
14 mParticlePositions.assign( kMaxParticles, vec2( -1, -1 ) );
|
f@0
|
15
|
f@0
|
16 mParticleVbo = gl::Vbo::create( GL_ARRAY_BUFFER, mParticlePositions, GL_DYNAMIC_DRAW );
|
f@0
|
17
|
f@0
|
18 geom::BufferLayout particleLayout;
|
f@0
|
19 particleLayout.append( geom::Attrib::POSITION, 2, sizeof( vec2 ), 0 );
|
f@0
|
20
|
f@0
|
21 auto mesh = gl::VboMesh::create( mParticlePositions.size(), GL_POINTS, { { particleLayout, mParticleVbo } } );
|
f@0
|
22
|
f@0
|
23 #if ! defined( CINDER_GL_ES )
|
f@0
|
24 auto glsl = gl::GlslProg::create( gl::GlslProg::Format()
|
f@0
|
25 .vertex( CI_GLSL( 150,
|
f@0
|
26 uniform mat4 ciModelViewProjection;
|
f@0
|
27 in vec4 ciPosition;
|
f@0
|
28
|
f@0
|
29 void main( void ) {
|
f@0
|
30 gl_Position = ciModelViewProjection * ciPosition;
|
f@0
|
31 gl_PointSize = 1.0;
|
f@0
|
32 }
|
f@0
|
33 ) )
|
f@0
|
34 .fragment( CI_GLSL( 150,
|
f@0
|
35 out vec4 oColor;
|
f@0
|
36
|
f@0
|
37 void main( void ) {
|
f@0
|
38 oColor = vec4( 1.0f, 1.0f, 1.0f, 1.0f );
|
f@0
|
39 }
|
f@0
|
40 ) )
|
f@0
|
41 );
|
f@0
|
42
|
f@0
|
43 mParticleBatch = gl::Batch::create( mesh, glsl );
|
f@0
|
44
|
f@0
|
45 #else
|
f@0
|
46 auto glsl = gl::GlslProg::create( gl::GlslProg::Format()
|
f@0
|
47 .vertex( CI_GLSL( 100,
|
f@0
|
48 uniform mat4 ciModelViewProjection;
|
f@0
|
49 attribute vec4 ciPosition;
|
f@0
|
50
|
f@0
|
51 void main( void ) {
|
f@0
|
52 gl_Position = ciModelViewProjection * ciPosition;
|
f@0
|
53 gl_PointSize = 1.0;
|
f@0
|
54 }
|
f@0
|
55 ) )
|
f@0
|
56 .fragment( CI_GLSL( 100,
|
f@0
|
57 precision highp float;
|
f@0
|
58
|
f@0
|
59 void main( void ) {
|
f@0
|
60 gl_FragColor = vec4( 1, 1, 1, 1 );
|
f@0
|
61 }
|
f@0
|
62 ) )
|
f@0
|
63 );
|
f@0
|
64
|
f@0
|
65 mParticleBatch = gl::Batch::create( mesh, glsl );
|
f@0
|
66 #endif
|
f@0
|
67
|
f@0
|
68
|
f@0
|
69 }
|
f@0
|
70
|
f@0
|
71 void ParticleController::updateParticles()
|
f@0
|
72 {
|
f@0
|
73 for ( size_t i = 0; i < mNumParticles; i++ ){
|
f@0
|
74
|
f@0
|
75 Particle &particle = mParticles[i];
|
f@0
|
76 vec2 &pos = mParticlePositions[i];
|
f@0
|
77
|
f@0
|
78 particle.mAge++;
|
f@0
|
79
|
f@0
|
80
|
f@0
|
81 if ( (!particle.mFlyOver && particle.mAge > particle.mLifespan)
|
f@0
|
82 || (particle.mFlyOver && particle.mAge >= 300) ){
|
f@0
|
83 // dispose particle
|
f@0
|
84 mParticles[i] = mParticles[mNumParticles - 1];
|
f@0
|
85 mParticlePositions[i] = mParticlePositions[mNumParticles - 1];
|
f@0
|
86 mParticlePositions[mNumParticles - 1].x = -1.0f;
|
f@0
|
87 mParticlePositions[mNumParticles - 1].y = -1.0f;
|
f@0
|
88 mNumParticles--;
|
f@0
|
89 continue;
|
f@0
|
90 }
|
f@0
|
91
|
f@0
|
92 pos += particle.mVel;
|
f@0
|
93 if ( ci::distance( pos, particle.mCloudCenter ) > particle.mCloudSize && !particle.mFlyOver ){
|
f@0
|
94 particle.mVel = rotate<float>( particle.mVel, 5 );
|
f@0
|
95 }
|
f@0
|
96 }
|
f@0
|
97
|
f@0
|
98 void *gpuMem = mParticleVbo->mapReplace();
|
f@0
|
99 memcpy( gpuMem, mParticlePositions.data(), mParticlePositions.size() * sizeof( vec2 ) );
|
f@0
|
100 mParticleVbo->unmap();
|
f@0
|
101 }
|
f@0
|
102
|
f@0
|
103 void ParticleController::addParticles(int amount, const vec2 &initialLocation, const float cloudSize)
|
f@0
|
104 {
|
f@0
|
105 int reduction = ci::lmap<int>(mNumParticles, 0, kMaxParticles, 0, kMaxParticleAdd);
|
f@0
|
106 amount -= reduction;
|
f@0
|
107
|
f@0
|
108 if ( mNumParticles + amount > kMaxParticles ){
|
f@0
|
109 //return;
|
f@0
|
110 amount = kMaxParticles - mNumParticles;
|
f@0
|
111 }
|
f@0
|
112
|
f@0
|
113 if( amount <= 0 )
|
f@0
|
114 return;
|
f@0
|
115
|
f@0
|
116 for( size_t i = 0; i < amount; i++ ){
|
f@0
|
117 // init new particle
|
f@0
|
118 Particle &particle = mParticles[mNumParticles + i];
|
f@0
|
119 vec2 &pos = mParticlePositions[mNumParticles + i];
|
f@0
|
120
|
f@0
|
121 pos = initialLocation + Rand::randVec2() * 5.0f; // find a location nearby the initial location
|
f@0
|
122 particle.mCloudCenter = pos;
|
f@0
|
123 particle.mVel = Rand::randVec2() * Rand::randFloat( 1.0f, 5.0f );
|
f@0
|
124 particle.mCloudSize = cloudSize;
|
f@0
|
125 particle.mAge = 0;
|
f@0
|
126 particle.mLifespan = Rand::randInt( 30, 60 );
|
f@0
|
127 particle.mFlyOver = (Rand::randInt( 500 ) == 0);
|
f@0
|
128
|
f@0
|
129 }
|
f@0
|
130
|
f@0
|
131 mNumParticles += amount ;
|
f@0
|
132
|
f@0
|
133 }
|
f@0
|
134
|
f@0
|
135
|
f@0
|
136
|