root/src/examples/flowingcanvas/canvascell.h @ 167:4a9556a866ac

Revision 167:4a9556a866ac, 7.3 KB (checked in by Andreas Schaefer <gentryx@…>, 14 months ago)

presentable version

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 = 10;
53    static const int MAX_SPAWN_COUNTDOWN = 60;
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 8;
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 == (nanoSteps() - 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
92        if (nanoStep == (nanoSteps() - 2)) {
93            spawnParticles();
94            updateParticles();
95        }
96    }
97
98    template<typename COORD_MAP>
99    void update(const COORD_MAP& hood, const unsigned& nanoStep)
100    {
101        update(&hood[Coord<2>(0, -1)], &hood[Coord<2>(0, 0)], &hood[Coord<2>(0, 1)], nanoStep);
102    }
103
104
105    __host__ __device__
106    void readCam(const unsigned char& r, const unsigned char& g, const unsigned char& b)
107    {
108        cameraPixel = (0xff << 24) + (r << 16) + (g <<  8) + (b <<  0);
109
110        int val = (int)r + (int)g + (int)b;
111        if (val < 250) {
112            cameraLevel = 1.0;
113        } else {
114            cameraLevel = max(0.0, cameraLevel - 0.05);
115        }
116    }
117
118    // fixme:
119private:
120    unsigned color[TILE_HEIGHT][TILE_WIDTH];
121    unsigned cameraPixel;
122    unsigned spawnCountdown;
123    float pos[2];
124    bool forceSet;
125
126    float cameraLevel;
127    float forceVario[2];
128    float forceFixed[2];
129    float forceTotal[2];
130    int numParticles;
131    Particle particles[MAX_PARTICLES]; 
132
133    /**
134     * Transition particles between neighboring cells
135     */
136    __host__ __device__
137    void moveParticles(const CanvasCell *up, const CanvasCell *same, const CanvasCell *down)
138    {
139        numParticles = 0;
140        for (int x = -1; x < 2; ++x) {
141            addParticles(up[x]);
142            addParticles(same[x]);
143            addParticles(down[x]);
144        }
145    }
146
147    __host__ __device__
148    void addParticles(const CanvasCell& cell)
149    {
150        for (int i = 0; i < cell.numParticles; ++i) {
151            const Particle& particle = cell.particles[i];
152            // fixme: refactor via "extract method" for readability
153            if ((((int)pos[0]) == ((int)particle.pos[0])) &&
154                (((int)pos[1]) == ((int)particle.pos[1])) &&
155                (particle.lifetime > 0)) {
156                if (numParticles < MAX_PARTICLES) {
157                    particles[numParticles] = particle;
158                    ++numParticles; 
159                } else {
160                    printf("uhoh\n");
161                }
162            }
163        }
164    }
165
166    __host__ __device__
167    void spawnParticles()
168    {
169        // fixme: render particles
170        // fixme: spawn particles
171        // fixme: move particles to other cells
172
173        if (spawnCountdown <= 0) {
174            spawnCountdown = MAX_SPAWN_COUNTDOWN;
175
176            if ((numParticles < 1) && ((int)pos[0] % 5 == 0) && ((int)pos[1] % 5 == 0)) {
177                particles[numParticles] = Particle(pos[0], pos[1]);
178                numParticles = 1;
179            }
180           
181        } else {
182            --spawnCountdown;
183        }
184    }
185
186    __host__ __device__
187    void updateParticles()
188    {
189       
190        for (int i = 0; i < numParticles; ++i) {
191            Particle& p = particles[i];
192            // fixme: parameters
193            p.update(0.5, forceTotal[0], forceTotal[1], 1.0, 0.9);
194        }
195    }
196
197    __host__ __device__
198    void updateForces(const CanvasCell *up, const CanvasCell *same, const CanvasCell *down, const unsigned& nanoStep)
199    {
200        const CanvasCell& oldSelf = *same;
201       
202        spawnCountdown = oldSelf.spawnCountdown;
203        pos[0] = oldSelf.pos[0];
204        pos[1] = oldSelf.pos[1];
205        cameraPixel = oldSelf.cameraPixel;
206        cameraLevel = oldSelf.cameraLevel;
207        numParticles = oldSelf.numParticles;
208        for (int i = 0; i < numParticles; ++i) {
209            particles[i] = oldSelf.particles[i];
210        } 
211
212        forceSet = oldSelf.forceSet;
213        if (forceSet) {
214            forceFixed[0] = oldSelf.forceFixed[0];
215            forceFixed[1] = oldSelf.forceFixed[1];
216        } else {
217            forceFixed[0] = (up[0].forceFixed[0] +
218                             same[-1].forceFixed[0] +
219                             same[1].forceFixed[0] +
220                             down[0].forceFixed[0]) * 0.25;
221            forceFixed[1] = (up[0].forceFixed[1] +
222                             same[-1].forceFixed[1] +
223                             same[1].forceFixed[1] +
224                             down[0].forceFixed[1]) * 0.25;
225        }
226
227        cameraLevel = (up[0].cameraLevel +
228                             same[-1].cameraLevel +
229                             same[1].cameraLevel +
230                             down[0].cameraLevel) * 0.25;
231       
232        float gradientX = same[1].cameraLevel - same[-1].cameraLevel;
233        float gradientY = down[0].cameraLevel - up[0].cameraLevel;
234        forceVario[0] = 0;
235        if ((gradientX > 0.011) || (gradientX < -0.011)) {
236            forceVario[0] = 0.01 / gradientX;
237        } else {
238            forceVario[0] = 0;
239        }
240
241        if ((gradientY > 0.011) || (gradientY < -0.011)) {
242            forceVario[1] = 0.01 / gradientY;
243        } else {
244            forceVario[1] = 0;
245        }
246
247        forceTotal[0] = 0.5 * (forceFixed[0] + forceVario[0]);
248        forceTotal[1] = 0.5 * (forceFixed[1] + forceVario[1]);
249    }
250
251    __host__ __device__
252    float max(const float& a, const float& b)
253    {
254        return a > b ? a : b;
255    }
256};
257
258}
259
260#endif
Note: See TracBrowser for help on using the browser.