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 @ 5:75b744078d66

History | View | Annotate | Download (5.13 KB)

1 5:75b744078d66 f
/*
2

3
 Copyright (C) 2015  Fiore Martin
4
 Copyright (C) 2016  Queen Mary University of London
5
 Author: Fiore Martin
6

7
 This file is part of Collidoscope.
8

9
 Collidoscope is free software: you can redistribute it and/or modify
10
 it under the terms of the GNU General Public License as published by
11
 the Free Software Foundation, either version 3 of the License, or
12
 (at your option) any later version.
13

14
 This program is distributed in the hope that it will be useful,
15
 but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 GNU General Public License for more details.
18

19
 You should have received a copy of the GNU General Public License
20
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
21

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