| 1 | #ifndef _libgeodecomp_examples_flowingcanvas_canvaswriter_h_ |
|---|
| 2 | #define _libgeodecomp_examples_flowingcanvas_canvaswriter_h_ |
|---|
| 3 | |
|---|
| 4 | #include <QImage> |
|---|
| 5 | #include <QPainter> |
|---|
| 6 | #include <libgeodecomp/io/writer.h> |
|---|
| 7 | #include <libgeodecomp/examples/flowingcanvas/canvascell.h> |
|---|
| 8 | |
|---|
| 9 | namespace LibGeoDecomp { |
|---|
| 10 | |
|---|
| 11 | class CanvasWriter : public QObject, public Writer<CanvasCell> |
|---|
| 12 | { |
|---|
| 13 | Q_OBJECT |
|---|
| 14 | |
|---|
| 15 | public: |
|---|
| 16 | class SelectForceFixed |
|---|
| 17 | { |
|---|
| 18 | public: |
|---|
| 19 | float operator()(const CanvasCell& cell, const int& index) const |
|---|
| 20 | { |
|---|
| 21 | return cell.forceFixed[index]; |
|---|
| 22 | } |
|---|
| 23 | }; |
|---|
| 24 | |
|---|
| 25 | class SelectForceVario |
|---|
| 26 | { |
|---|
| 27 | public: |
|---|
| 28 | float operator()(const CanvasCell& cell, const int& index) const |
|---|
| 29 | { |
|---|
| 30 | return cell.forceVario[index]; |
|---|
| 31 | } |
|---|
| 32 | }; |
|---|
| 33 | |
|---|
| 34 | class SelectForceTotal |
|---|
| 35 | { |
|---|
| 36 | public: |
|---|
| 37 | float operator()(const CanvasCell& cell, const int& index) const |
|---|
| 38 | { |
|---|
| 39 | return cell.forceTotal[index]; |
|---|
| 40 | } |
|---|
| 41 | }; |
|---|
| 42 | |
|---|
| 43 | class SelectCameraLevel |
|---|
| 44 | { |
|---|
| 45 | public: |
|---|
| 46 | unsigned operator()(const CanvasCell& cell) const |
|---|
| 47 | { |
|---|
| 48 | return (0xff << 24) + ((int)(cell.cameraLevel * 250) << 16); |
|---|
| 49 | } |
|---|
| 50 | }; |
|---|
| 51 | |
|---|
| 52 | class SelectCameraPixel |
|---|
| 53 | { |
|---|
| 54 | public: |
|---|
| 55 | unsigned operator()(const CanvasCell& cell) const |
|---|
| 56 | { |
|---|
| 57 | return cell.cameraPixel; |
|---|
| 58 | } |
|---|
| 59 | }; |
|---|
| 60 | |
|---|
| 61 | CanvasWriter(QImage **_outputFrame, |
|---|
| 62 | MonolithicSimulator<CanvasCell> *_sim) : |
|---|
| 63 | Writer<CanvasCell>("foo", _sim, 1), |
|---|
| 64 | outputFrame(_outputFrame), |
|---|
| 65 | particleMode(3), |
|---|
| 66 | cameraMode(1) |
|---|
| 67 | {} |
|---|
| 68 | |
|---|
| 69 | virtual void initialized() |
|---|
| 70 | {} |
|---|
| 71 | |
|---|
| 72 | virtual void stepFinished() |
|---|
| 73 | { |
|---|
| 74 | const typename Simulator<CanvasCell>::GridType *grid = sim->getGrid(); |
|---|
| 75 | |
|---|
| 76 | switch (particleMode) { |
|---|
| 77 | case 0: |
|---|
| 78 | drawForce(grid, SelectForceVario()); |
|---|
| 79 | break; |
|---|
| 80 | case 1: |
|---|
| 81 | drawForce(grid, SelectForceFixed()); |
|---|
| 82 | break; |
|---|
| 83 | case 2: |
|---|
| 84 | drawForce(grid, SelectForceTotal()); |
|---|
| 85 | break; |
|---|
| 86 | case 3: |
|---|
| 87 | drawParticles(grid); |
|---|
| 88 | break; |
|---|
| 89 | default: |
|---|
| 90 | break; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | switch (cameraMode) { |
|---|
| 94 | case 0: |
|---|
| 95 | drawAttribute(grid, SelectCameraPixel()); |
|---|
| 96 | break; |
|---|
| 97 | case 1: |
|---|
| 98 | drawAttribute(grid, SelectCameraLevel()); |
|---|
| 99 | break; |
|---|
| 100 | default: |
|---|
| 101 | break; |
|---|
| 102 | } |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | virtual void allDone() |
|---|
| 106 | { |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | public slots: |
|---|
| 110 | virtual void cycleViewModeParticle() |
|---|
| 111 | { |
|---|
| 112 | particleMode = (particleMode + 1) % 4; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | virtual void cycleViewModeCamera() |
|---|
| 116 | { |
|---|
| 117 | cameraMode = (cameraMode + 1) % 3; |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | private: |
|---|
| 121 | QImage **outputFrame; |
|---|
| 122 | int particleMode; |
|---|
| 123 | int cameraMode; |
|---|
| 124 | |
|---|
| 125 | template<typename SELECTOR> |
|---|
| 126 | void drawForce(const typename Simulator<CanvasCell>::GridType *grid, const SELECTOR& selector) |
|---|
| 127 | { |
|---|
| 128 | Coord<2> dim = sim->getInitializer()->gridDimensions(); |
|---|
| 129 | |
|---|
| 130 | int spacingX = 10; |
|---|
| 131 | int spacingY = 10; |
|---|
| 132 | float factorX = 1.0 * (*outputFrame)->width() / dim.x(); |
|---|
| 133 | float factorY = 1.0 * (*outputFrame)->height() / dim.y(); |
|---|
| 134 | |
|---|
| 135 | QPainter p(*outputFrame); |
|---|
| 136 | p.setBrush(QBrush(Qt::black)); |
|---|
| 137 | p.drawRect(0, 0, (*outputFrame)->width(), (*outputFrame)->height()); |
|---|
| 138 | p.setBrush(QBrush(Qt::white)); |
|---|
| 139 | p.setPen(QPen(Qt::white)); |
|---|
| 140 | |
|---|
| 141 | for (int y = 0; y < dim.y(); y += spacingY) { |
|---|
| 142 | for (int x = 0; x < dim.x(); x += spacingX) { |
|---|
| 143 | int startX = (x + 0.5) * factorX; |
|---|
| 144 | int startY = (y + 0.5) * factorY; |
|---|
| 145 | const CanvasCell& cell = grid->at(Coord<2>(x, y)); |
|---|
| 146 | float force0 = selector(cell, 0); |
|---|
| 147 | float force1 = selector(cell, 1); |
|---|
| 148 | int offsetX = force0 * spacingX * factorX * 0.8; |
|---|
| 149 | int offsetY = force1 * spacingY * factorY * 0.8; |
|---|
| 150 | int endX = startX + offsetX; |
|---|
| 151 | int endY = startY + offsetY; |
|---|
| 152 | p.drawLine(startX, startY, endX, endY); |
|---|
| 153 | QRectF rect(endX - spacingX * 0.1, endY - spacingY * 0.1, spacingX * 0.2, spacingY * 0.2); |
|---|
| 154 | p.drawEllipse(rect); |
|---|
| 155 | } |
|---|
| 156 | } |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | // fixme: erase background |
|---|
| 160 | // fixme: scale to image size |
|---|
| 161 | template<typename SELECTOR> |
|---|
| 162 | void drawAttribute(const typename Simulator<CanvasCell>::GridType *grid, const SELECTOR& selector) |
|---|
| 163 | { |
|---|
| 164 | Coord<2> dim = sim->getInitializer()->gridDimensions(); |
|---|
| 165 | |
|---|
| 166 | for (int y = 0; y < dim.y(); ++y) { |
|---|
| 167 | for (int x = 0; x < dim.x(); ++x) { |
|---|
| 168 | (*outputFrame)->setPixel(x, y, selector(grid->at(Coord<2>(x, y)))); |
|---|
| 169 | } |
|---|
| 170 | } |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | void drawParticles(const typename Simulator<CanvasCell>::GridType *grid) |
|---|
| 174 | { |
|---|
| 175 | Coord<2> dim = sim->getInitializer()->gridDimensions(); |
|---|
| 176 | float factorX = 1.0 * (*outputFrame)->width() / dim.x(); |
|---|
| 177 | float factorY = 1.0 * (*outputFrame)->height() / dim.y(); |
|---|
| 178 | |
|---|
| 179 | QPainter p(*outputFrame); |
|---|
| 180 | p.setBrush(QBrush(Qt::black)); |
|---|
| 181 | p.drawRect(0, 0, (*outputFrame)->width(), (*outputFrame)->height()); |
|---|
| 182 | p.setBrush(QBrush(Qt::white)); |
|---|
| 183 | p.setPen(QPen(Qt::white)); |
|---|
| 184 | |
|---|
| 185 | for (int y = 0; y < dim.y(); ++y) { |
|---|
| 186 | for (int x = 0; x < dim.x(); ++x) { |
|---|
| 187 | const CanvasCell& cell = grid->at(Coord<2>(x, y)); |
|---|
| 188 | for (int i = 0; i < cell.numParticles; ++i) { |
|---|
| 189 | const CanvasCell::Particle& particle = cell.particles[i]; |
|---|
| 190 | QPoint origin(particle.pos[0] * factorX, |
|---|
| 191 | particle.pos[1] * factorY); |
|---|
| 192 | QPoint direction(particle.vel[0] * 20, |
|---|
| 193 | particle.vel[1] * 20); |
|---|
| 194 | QPoint end = origin + direction; |
|---|
| 195 | QPoint offset(2, 2); |
|---|
| 196 | QSize size(4, 4); |
|---|
| 197 | QRectF rect(origin - offset, size); |
|---|
| 198 | p.drawEllipse(rect); |
|---|
| 199 | p.drawLine(origin, end); |
|---|
| 200 | } |
|---|
| 201 | } |
|---|
| 202 | } |
|---|
| 203 | } |
|---|
| 204 | }; |
|---|
| 205 | |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | #endif |
|---|