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