root/src/examples/flowingcanvas/canvascell.h @ 165:3786a4b70805

Revision 165:3786a4b70805, 7.2 KB (checked in by Andreas Schaefer <gentryx@…>, 15 months ago)

particles now spawn, move and die

Line 
1#ifndef _libgeodecomp_examples_flowingcanvas_canvascell_h_
2#define _libgeodecomp_examples_flowingcanvas_canvascell_h_
3
4#include <stdio.h>
5#include <libgeodecomp/misc/floatcoord.h>
6#include <libgeodecomp/misc/topologies.h>
7
8#ifndef __host__
9#define __host__
10#endif
11
12#ifndef __device__
13#define __device__
14#endif
15
16namespace LibGeoDecomp {
17
18class CanvasCell
19{
20    friend class CanvasWriter;
21public:
22    class Particle
23    {
24    public:
25        __host__ __device__
26        Particle(const float& pos0 = 0, const float& pos1 = 0, const float& _lifetime = 100) :
27            lifetime(_lifetime)
28        {
29            pos[0] = pos0;
30            pos[1] = pos1;
31            vel[0] = 0;
32            vel[1] = 0;
33        }
34
35        __host__ __device__
36        void update(const float& deltaT, const float& force0, const float& force1, const float& forceFactor, const float& friction)
37        {
38            vel[0] += deltaT * forceFactor * force0;
39            vel[1] += deltaT * forceFactor * force1;
40            vel[0] *= friction;
41            vel[1] *= friction;
42            pos[0] += deltaT * vel[0];
43            pos[1] += deltaT * vel[1];
44            --lifetime;
45        }
46
47        float pos[2];
48        float vel[2];
49        int lifetime;
50    };
51
52    static const int MAX_PARTICLES = 20;
53    static const int MAX_SPAWN_COUNTDOWN = 100;
54    typedef Topologies::Cube<2>::Topology Topology;
55    static const int TILE_WIDTH = 4;
56    static const int TILE_HEIGHT = 4;
57   
58    static inline unsigned nanoSteps()
59    {
60        return 2;
61    }
62
63    CanvasCell(
64        Coord<2> _pos = Coord<2>(), 
65        bool _forceSet = false,
66        FloatCoord<2> _forceFixed = FloatCoord<2>(),
67        int _spawnCountdown = 0) :
68        spawnCountdown(_spawnCountdown),
69        cameraLevel(0),
70        numParticles(0)
71    {
72        pos[0] = _pos.x();
73        pos[1] = _pos.y();
74        forceFixed[0] = _forceFixed.c[0];
75        forceFixed[1] = _forceFixed.c[1];
76        forceSet = _forceSet;
77    }
78
79    // fixme: faster conversion if moore-neighborhood is used (instead of von neumann)?
80    __host__ __device__
81    void update(const CanvasCell *up, const CanvasCell *same, const CanvasCell *down, const unsigned& nanoStep)
82    {
83        if (nanoStep == 1) {
84            // fixme: can we avoid this?
85            *this = *same;
86            moveParticles(up, same, down);
87            return;
88        }
89
90        updateForces(up, same, down, nanoStep);
91        spawnParticles();
92        updateParticles();
93    }
94
95    template<typename COORD_MAP>
96    void update(const COORD_MAP& hood, const unsigned& nanoStep)
97    {
98        update(&hood[Coord<2>(0, -1)], &hood[Coord<2>(0, 0)], &hood[Coord<2>(0, 1)], nanoStep);
99    }
100
101
102    __host__ __device__
103    void readCam(const unsigned char& r, const unsigned char& g, const unsigned char& b)
104    {
105        cameraPixel = (0xff << 24) + (r << 16) + (g <<  8) + (b <<  0);
106
107        int val = (int)r + (int)g + (int)b;
108        if (val < 500) {
109            cameraLevel = 1.0;
110        } else {
111            cameraLevel = max(0.0, cameraLevel - 0.05);
112        }
113    }
114
115    // fixme:
116private:
117    unsigned color[TILE_HEIGHT][TILE_WIDTH];
118    unsigned cameraPixel;
119    unsigned spawnCountdown;
120    float pos[2];
121    bool forceSet;
122
123    float cameraLevel;
124    float forceVario[2];
125    float forceFixed[2];
126    float forceTotal[2];
127    int numParticles;
128    Particle particles[MAX_PARTICLES]; 
129
130    /**
131     * Transition particles between neighboring cells
132     */
133    __host__ __device__
134    void moveParticles(const CanvasCell *up, const CanvasCell *same, const CanvasCell *down)
135    {
136        numParticles = 0;
137        for (int x = -1; x < 2; ++x) {
138            addParticles(up[x]);
139            addParticles(same[x]);
140            addParticles(down[x]);
141        }
142    }
143
144    __host__ __device__
145    void addParticles(const CanvasCell& cell)
146    {
147        for (int i = 0; i < cell.numParticles; ++i) {
148            const Particle& particle = cell.particles[i];
149            // fixme: refactor via "extract method" for readability
150            if ((((int)pos[0]) == ((int)particle.pos[0])) &&
151                (((int)pos[1]) == ((int)particle.pos[1])) &&
152                (particle.lifetime > 0)) {
153                if (numParticles < MAX_PARTICLES) {
154                    particles[numParticles] = particle;
155                    ++numParticles; 
156                } else {
157                    printf("uhoh\n");
158                }
159            }
160        }
161    }
162
163    __host__ __device__
164    void spawnParticles()
165    {
166        // fixme: render particles
167        // fixme: spawn particles
168        // fixme: move particles to other cells
169
170        if (spawnCountdown <= 0) {
171            spawnCountdown = MAX_SPAWN_COUNTDOWN;
172
173            if ((numParticles < 1) && ((int)pos[0] % 5 == 0) && ((int)pos[1] % 5 == 0)) {
174                particles[numParticles] = Particle(pos[0], pos[1]);
175                numParticles = 1;
176            }
177           
178        } else {
179            --spawnCountdown;
180        }
181    }
182
183    __host__ __device__
184    void updateParticles()
185    {
186       
187        for (int i = 0; i < numParticles; ++i) {
188            Particle& p = particles[i];
189            // fixme: parameters
190            p.update(0.5, forceTotal[0], forceTotal[1], 1.0, 0.9);
191        }
192    }
193
194    __host__ __device__
195    void updateForces(const CanvasCell *up, const CanvasCell *same, const CanvasCell *down, const unsigned& nanoStep)
196    {
197        const CanvasCell& oldSelf = *same;
198       
199        spawnCountdown = oldSelf.spawnCountdown;
200        pos[0] = oldSelf.pos[0];
201        pos[1] = oldSelf.pos[1];
202        cameraPixel = oldSelf.cameraPixel;
203        cameraLevel = oldSelf.cameraLevel;
204        numParticles = oldSelf.numParticles;
205        for (int i = 0; i < numParticles; ++i) {
206            particles[i] = oldSelf.particles[i];
207        } 
208
209        forceSet = oldSelf.forceSet;
210        if (forceSet) {
211            forceFixed[0] = oldSelf.forceFixed[0];
212            forceFixed[1] = oldSelf.forceFixed[1];
213        } else {
214            forceFixed[0] = (up[0].forceFixed[0] +
215                             same[-1].forceFixed[0] +
216                             same[1].forceFixed[0] +
217                             down[0].forceFixed[0]) * 0.25;
218            forceFixed[1] = (up[0].forceFixed[1] +
219                             same[-1].forceFixed[1] +
220                             same[1].forceFixed[1] +
221                             down[0].forceFixed[1]) * 0.25;
222        }
223
224        cameraLevel = (up[0].cameraLevel +
225                             same[-1].cameraLevel +
226                             same[1].cameraLevel +
227                             down[0].cameraLevel) * 0.25;
228       
229        float gradientX = same[1].cameraLevel - same[-1].cameraLevel;
230        float gradientY = down[0].cameraLevel - up[0].cameraLevel;
231        forceVario[0] = 0;
232        if ((gradientX > 0.011) || (gradientX < -0.011)) {
233            forceVario[0] = 0.01 / gradientX;
234        } else {
235            forceVario[0] = 0;
236        }
237
238        if ((gradientY > 0.011) || (gradientY < -0.011)) {
239            forceVario[1] = 0.01 / gradientY;
240        } else {
241            forceVario[1] = 0;
242        }
243
244        forceTotal[0] = 0.5 * (forceFixed[0] + forceVario[0]);
245        forceTotal[1] = 0.5 * (forceFixed[1] + forceVario[1]);
246    }
247
248    __host__ __device__
249    float max(const float& a, const float& b)
250    {
251        return a > b ? a : b;
252    }
253};
254
255}
256
257#endif
Note: See TracBrowser for help on using the browser.