To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / CollidoscopeApp / src / ParticleController.cpp @ 4:ab6db404403a

History | View | Annotate | Download (4.37 KB)

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