paysages: Threaded previews.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@311 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-04-29 20:42:36 +00:00 committed by ThunderK
parent 5cd3c5b506
commit d4f2ff4e1d
3 changed files with 54 additions and 28 deletions

5
TODO
View file

@ -11,12 +11,17 @@ Technology Preview 2 :
- Improve curve editor. - Improve curve editor.
- Water and terrain LOD moves with the camera, fix it like in the wanderer. - Water and terrain LOD moves with the camera, fix it like in the wanderer.
- There should not have to be more preview threads than core. - There should not have to be more preview threads than core.
- Handle preview threads termination.
- Add preview threads pausing (for rendering).
- Add preview chunks priority (for visible previews).
- Interrupt preview chunk renderings that will be discarded at commit.
Technology Preview 3 : Technology Preview 3 :
- Restore render progress. - Restore render progress.
- Add antialiasing option (pay attention to memory usage). - Add antialiasing option (pay attention to memory usage).
- Add basic vegetation system (not sure). - Add basic vegetation system (not sure).
- Improve sky rendering (colors and light halo). - Improve sky rendering (colors and light halo).
- Add a progress indicator on previews.
Release Candidate : Release Candidate :
- Polish all features and UI. - Polish all features and UI.

View file

@ -6,15 +6,14 @@
#include <QTimer> #include <QTimer>
#include <QWheelEvent> #include <QWheelEvent>
/*************** PreviewChunk ***************/
class PreviewChunk class PreviewChunk
{ {
public: public:
PreviewChunk(BasePreview* preview, QImage* pixbuf, QMutex* lock, int xstart, int ystart, int xsize, int ysize) PreviewChunk(BasePreview* preview, int xstart, int ystart, int xsize, int ysize)
{ {
_preview = preview; _preview = preview;
_pixbuf = pixbuf;
_lock = lock;
_xstart = xstart; _xstart = xstart;
_ystart = ystart; _ystart = ystart;
_xsize = xsize; _xsize = xsize;
@ -36,26 +35,25 @@ public:
bool render() bool render()
{ {
bool changed = false; bool changed = false;
int revision;
if (_need_render) if (_need_render)
{ {
_need_render = false; _need_render = false;
_lock->lock(); QImage pixbuf = _preview->startChunkTransaction(_xstart, _ystart, _xsize, _ysize, &revision);
QImage tempbuffer = _pixbuf->copy(_xstart, _ystart, _xsize, _ysize);
_lock->unlock();
for (int x = 0; x < _xsize; x++) for (int x = 0; x < _xsize; x++)
{ {
for (int y = 0; y < _ysize; y++) for (int y = 0; y < _ysize; y++)
{ {
QRgb col = tempbuffer.pixel(x, y); QRgb col = pixbuf.pixel(x, y);
if (qAlpha(col) < 255) if (qAlpha(col) < 255)
{ {
QColor newcol = _preview->getPixelColor(_xstart + x, _ystart + y); QColor newcol = _preview->getPixelColor(_xstart + x, _ystart + y);
newcol.setAlpha(255); newcol.setAlpha(255);
tempbuffer.setPixel(x, y, newcol.rgb()); pixbuf.setPixel(x, y, newcol.rgb());
changed = true; changed = true;
} }
@ -64,16 +62,7 @@ public:
if (changed) if (changed)
{ {
_lock->lock(); _preview->commitChunkTransaction(&pixbuf, _xstart, _ystart, _xsize, _ysize, revision);
for (int x = 0; x < _xsize; x++)
{
for (int y = 0; y < _ysize; y++)
{
_pixbuf->setPixel(_xstart + x, _ystart + y, tempbuffer.pixel(x, y));
}
}
_lock->unlock();
_preview->tellContentChange();
} }
} }
@ -81,8 +70,6 @@ public:
} }
private: private:
BasePreview* _preview; BasePreview* _preview;
QImage* _pixbuf;
QMutex* _lock;
bool _need_render; bool _need_render;
int _xstart; int _xstart;
int _ystart; int _ystart;
@ -230,6 +217,7 @@ QWidget(parent)
this->pixbuf->fill(0x00000000); this->pixbuf->fill(0x00000000);
_width = width(); _width = width();
_height = height(); _height = height();
_revision = 0;
this->alive = true; this->alive = true;
@ -311,6 +299,29 @@ void BasePreview::redraw()
emit(redrawRequested()); emit(redrawRequested());
} }
QImage BasePreview::startChunkTransaction(int x, int y, int w, int h, int* revision)
{
*revision = _revision;
return pixbuf->copy(x, y, w, h);
}
void BasePreview::commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision)
{
if (revision == _revision)
{
lock_drawing->lock();
for (int ix = 0; ix < w; ix++)
{
for (int iy = 0; iy < h; iy++)
{
pixbuf->setPixel(x + ix, y + iy, chunk->pixel(ix, iy));
}
}
lock_drawing->unlock();
emit contentChange();
}
}
QColor BasePreview::getPixelColor(int x, int y) QColor BasePreview::getPixelColor(int x, int y)
{ {
return getColor((double) (x - _width / 2) * scaling + xoffset, (double) (y - _height / 2) * scaling + yoffset); return getColor((double) (x - _width / 2) * scaling + xoffset, (double) (y - _height / 2) * scaling + yoffset);
@ -328,7 +339,7 @@ void BasePreview::handleRedraw()
painter.setOpacity(0.99); painter.setOpacity(0.99);
painter.drawImage(0, 0, part); painter.drawImage(0, 0, part);
_drawing_manager->updateChunks(this); updateChunks();
lock_drawing->unlock(); lock_drawing->unlock();
} }
@ -353,7 +364,7 @@ void BasePreview::resizeEvent(QResizeEvent* event)
{ {
for (int y = 0; y < _height; y += 32) for (int y = 0; y < _height; y += 32)
{ {
_drawing_manager->addChunk(new PreviewChunk(this, pixbuf, lock_drawing, x, y, x + 32 > _width ? _width - x : 32, y + 32 > _height ? _height - y : 32)); _drawing_manager->addChunk(new PreviewChunk(this, x, y, x + 32 > _width ? _width - x : 32, y + 32 > _height ? _height - y : 32));
} }
} }
@ -380,6 +391,12 @@ void BasePreview::updateScaling()
} }
} }
void BasePreview::updateChunks()
{
_drawing_manager->updateChunks(this);
_revision++;
}
void BasePreview::mousePressEvent(QMouseEvent* event) void BasePreview::mousePressEvent(QMouseEvent* event)
{ {
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
@ -430,7 +447,7 @@ void BasePreview::mouseMoveEvent(QMouseEvent* event)
lock_drawing->lock(); lock_drawing->lock();
pixbuf->fill(0x00000000); pixbuf->fill(0x00000000);
_drawing_manager->updateChunks(this); updateChunks();
lock_drawing->unlock(); lock_drawing->unlock();
} }
else else
@ -468,7 +485,7 @@ void BasePreview::mouseMoveEvent(QMouseEvent* event)
pixbuf->fill(0x00000000); pixbuf->fill(0x00000000);
painter.drawImage(xstart + ndx, ystart + ndy, part); painter.drawImage(xstart + ndx, ystart + ndy, part);
_drawing_manager->updateChunks(this); updateChunks();
lock_drawing->unlock(); lock_drawing->unlock();
emit contentChange(); emit contentChange();
@ -546,7 +563,7 @@ void BasePreview::wheelEvent(QWheelEvent* event)
pixbuf->fill(0x00000000); pixbuf->fill(0x00000000);
painter.setOpacity(0.99); painter.setOpacity(0.99);
painter.drawImage(0, 0, part); painter.drawImage(0, 0, part);
_drawing_manager->updateChunks(this); updateChunks();
lock_drawing->unlock(); lock_drawing->unlock();
emit contentChange(); emit contentChange();
@ -559,7 +576,7 @@ void BasePreview::wheelEvent(QWheelEvent* event)
pixbuf->fill(0x00000000); pixbuf->fill(0x00000000);
painter.setOpacity(0.99); painter.setOpacity(0.99);
painter.drawImage((width - part.width()) / 2, (height - part.height()) / 2, part); painter.drawImage((width - part.width()) / 2, (height - part.height()) / 2, part);
_drawing_manager->updateChunks(this); updateChunks();
lock_drawing->unlock(); lock_drawing->unlock();
emit contentChange(); emit contentChange();

View file

@ -17,10 +17,11 @@ public:
static void initDrawers(); static void initDrawers();
static void stopDrawers(); static void stopDrawers();
void redraw(); void redraw();
inline void tellContentChange() {emit contentChange();} QImage startChunkTransaction(int x, int y, int w, int h, int* revision);
void commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision);
QColor getPixelColor(int x, int y); QColor getPixelColor(int x, int y);
@ -37,6 +38,7 @@ protected:
private: private:
void updateScaling(); void updateScaling();
void updateChunks();
void resizeEvent(QResizeEvent* event); void resizeEvent(QResizeEvent* event);
void paintEvent(QPaintEvent* event); void paintEvent(QPaintEvent* event);
@ -50,6 +52,8 @@ private:
int _width; int _width;
int _height; int _height;
int _revision;
int mousex; int mousex;
int mousey; int mousey;