WIP on new canvas system
This commit is contained in:
parent
8099361cc9
commit
cf58bea1b7
28 changed files with 700 additions and 99 deletions
|
@ -1,48 +1,69 @@
|
|||
#include "WidgetPreviewCanvas.h"
|
||||
|
||||
#include "tools.h"
|
||||
#include "Canvas.h"
|
||||
#include "CanvasPreview.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
WidgetPreviewCanvas::WidgetPreviewCanvas(QWidget *parent) :
|
||||
QWidget(parent), canvas(NULL)
|
||||
{
|
||||
pixbuf = new QImage();
|
||||
inited = false;
|
||||
|
||||
startTimer(1000);
|
||||
}
|
||||
|
||||
WidgetPreviewCanvas::~WidgetPreviewCanvas()
|
||||
{
|
||||
delete pixbuf;
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::setCanvas(const Canvas *canvas)
|
||||
{
|
||||
this->canvas = canvas;
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.drawImage(0, 0, *pixbuf);
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::canvasResized(int width, int height)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::canvasCleared(const Color &col)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::canvasPainted(int x, int y, const Color &col)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::timerEvent(QTimerEvent *)
|
||||
{
|
||||
// Refresh the view
|
||||
CanvasPreview *preview = canvas->getPreview();
|
||||
if (canvas)
|
||||
{
|
||||
int width = preview->getWidth();
|
||||
int height = preview->getHeight();
|
||||
|
||||
if (QSize(width, height) != this->size())
|
||||
{
|
||||
setMaximumSize(width, height);
|
||||
setMinimumSize(width, height);
|
||||
resize(width, height);
|
||||
|
||||
delete pixbuf;
|
||||
pixbuf = new QImage(width, height, QImage::Format_ARGB32);
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::canvasCleared(const Color &col)
|
||||
{
|
||||
pixbuf->fill(colorToQColor(col));
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::canvasPainted(int x, int y, const Color &col)
|
||||
{
|
||||
pixbuf->setPixel(x, pixbuf->height() - 1 - y, colorToQColor(col).rgb());
|
||||
}
|
||||
|
||||
void WidgetPreviewCanvas::timerEvent(QTimerEvent *)
|
||||
{
|
||||
if (canvas)
|
||||
{
|
||||
if (!inited)
|
||||
{
|
||||
canvas->getPreview()->initLive(this);
|
||||
inited = true;
|
||||
}
|
||||
|
||||
canvas->getPreview()->updateLive(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,15 @@ class WidgetPreviewCanvas : public QWidget, public CanvasLiveClient
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit WidgetPreviewCanvas(QWidget *parent = 0);
|
||||
virtual ~WidgetPreviewCanvas();
|
||||
|
||||
/*!
|
||||
* \brief Set the canvas to watch and display, null to stop watching.
|
||||
*/
|
||||
void setCanvas(const Canvas *canvas);
|
||||
|
||||
virtual void paintEvent(QPaintEvent* event);
|
||||
|
||||
protected:
|
||||
virtual void canvasResized(int width, int height);
|
||||
virtual void canvasCleared(const Color &col);
|
||||
|
@ -30,7 +33,9 @@ protected:
|
|||
virtual void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
QImage* pixbuf;
|
||||
const Canvas *canvas;
|
||||
bool inited;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "dialogexplorer.h"
|
||||
#include "DesktopScenery.h"
|
||||
#include "BasePreview.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
#include "CameraDefinition.h"
|
||||
#include "tools.h"
|
||||
|
||||
|
@ -246,7 +246,8 @@ void FreeFormHelper::processExploreClicked()
|
|||
|
||||
void FreeFormHelper::processRenderClicked()
|
||||
{
|
||||
SoftwareRenderer renderer(DesktopScenery::getCurrent());
|
||||
SoftwareCanvasRenderer renderer;
|
||||
renderer.setScenery(DesktopScenery::getCurrent());
|
||||
|
||||
emit needAlterRenderer(&renderer);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ static void _renderUpdate(double progress)
|
|||
class RenderThread:public QThread
|
||||
{
|
||||
public:
|
||||
RenderThread(DialogRender* dialog, SoftwareRenderer* renderer, RenderArea::RenderParams params):QThread()
|
||||
RenderThread(DialogRender* dialog, SoftwareCanvasRenderer* renderer, RenderArea::RenderParams params):QThread()
|
||||
{
|
||||
_dialog = dialog;
|
||||
_renderer = renderer;
|
||||
|
@ -59,12 +59,13 @@ public:
|
|||
}
|
||||
void run()
|
||||
{
|
||||
_renderer->render();
|
||||
_renderer->start(_params);
|
||||
_dialog->tellRenderEnded();
|
||||
}
|
||||
private:
|
||||
DialogRender* _dialog;
|
||||
SoftwareRenderer* _renderer;
|
||||
SoftwareCanvasRenderer* _renderer;
|
||||
RenderArea::RenderParams _params;
|
||||
};
|
||||
|
||||
|
@ -86,14 +87,14 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
DialogRender::DialogRender(QWidget *parent, SoftwareRenderer* renderer):
|
||||
DialogRender::DialogRender(QWidget *parent, SoftwareCanvasRenderer* renderer):
|
||||
QDialog(parent, Qt::WindowTitleHint | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint)
|
||||
{
|
||||
pixbuf_lock = new QMutex();
|
||||
pixbuf = new QImage(1, 1, QImage::Format_ARGB32);
|
||||
_current_dialog = this;
|
||||
_render_thread = NULL;
|
||||
_renderer = renderer;
|
||||
canvas_renderer = renderer;
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Paysages 3D - Render"));
|
||||
|
@ -105,7 +106,6 @@ DialogRender::DialogRender(QWidget *parent, SoftwareRenderer* renderer):
|
|||
_scroll->setWidget(area);
|
||||
layout()->addWidget(_scroll);
|
||||
|
||||
canvas_renderer = new SoftwareCanvasRenderer();
|
||||
canvas_preview = new WidgetPreviewCanvas(this);
|
||||
canvas_preview->setCanvas(canvas_renderer->getCanvas());
|
||||
layout()->addWidget(canvas_preview);
|
||||
|
@ -159,7 +159,7 @@ DialogRender::~DialogRender()
|
|||
{
|
||||
if (_render_thread)
|
||||
{
|
||||
_renderer->interrupt();
|
||||
canvas_renderer->interrupt();
|
||||
_render_thread->wait();
|
||||
|
||||
delete _render_thread;
|
||||
|
@ -190,9 +190,9 @@ void DialogRender::startRender(RenderArea::RenderParams params)
|
|||
canvas_renderer->setSize(params.width, params.height, params.antialias);
|
||||
|
||||
applyRenderSize(params.width, params.height);
|
||||
_renderer->setPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate);
|
||||
canvas_renderer->setPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate);
|
||||
|
||||
_render_thread = new RenderThread(this, _renderer, params);
|
||||
_render_thread = new RenderThread(this, canvas_renderer, params);
|
||||
_render_thread->start();
|
||||
|
||||
exec();
|
||||
|
@ -218,7 +218,7 @@ void DialogRender::saveRender()
|
|||
filepath = filepath.append(".png");
|
||||
}
|
||||
std::string filepathstr = filepath.toStdString();
|
||||
if (_renderer->render_area->saveToFile((char*)filepathstr.c_str()))
|
||||
if (canvas_renderer->render_area->saveToFile((char*)filepathstr.c_str()))
|
||||
{
|
||||
QMessageBox::information(this, "Message", QString(tr("The picture %1 has been saved.")).arg(filepath));
|
||||
}
|
||||
|
@ -232,13 +232,13 @@ void DialogRender::saveRender()
|
|||
void DialogRender::toneMappingChanged()
|
||||
{
|
||||
ColorProfile profile((ColorProfile::ToneMappingOperator)_tonemapping_control->currentIndex(), ((double)_exposure_control->value()) * 0.01);
|
||||
_renderer->render_area->setToneMapping(profile);
|
||||
canvas_renderer->render_area->setToneMapping(profile);
|
||||
}
|
||||
|
||||
void DialogRender::loadLastRender()
|
||||
{
|
||||
applyRenderSize(_renderer->render_width, _renderer->render_height);
|
||||
_renderer->setPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate);
|
||||
applyRenderSize(canvas_renderer->render_width, canvas_renderer->render_height);
|
||||
canvas_renderer->setPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate);
|
||||
renderEnded();
|
||||
toneMappingChanged();
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ class DialogRender : public QDialog
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DialogRender(QWidget *parent, SoftwareRenderer* renderer);
|
||||
explicit DialogRender(QWidget *parent, SoftwareCanvasRenderer* renderer);
|
||||
~DialogRender();
|
||||
|
||||
void tellRenderSize(int width, int height);
|
||||
|
@ -56,7 +56,6 @@ private:
|
|||
QPushButton* _save_button;
|
||||
QThread* _render_thread;
|
||||
QLabel* _timer;
|
||||
SoftwareRenderer* _renderer;
|
||||
QProgressBar* _progress;
|
||||
time_t _started;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "tools.h"
|
||||
#include "DesktopScenery.h"
|
||||
#include "PackStream.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
#include "BasePreview.h"
|
||||
#include "CloudsDefinition.h"
|
||||
#include "CameraDefinition.h"
|
||||
|
@ -103,7 +103,8 @@ void FormRender::startQuickRender()
|
|||
{
|
||||
delete _renderer;
|
||||
}
|
||||
_renderer = new SoftwareRenderer(DesktopScenery::getCurrent());
|
||||
_renderer = new SoftwareCanvasRenderer();
|
||||
_renderer->setScenery(DesktopScenery::getCurrent());
|
||||
_renderer_inited = true;
|
||||
|
||||
DialogRender* dialog = new DialogRender(this, _renderer);
|
||||
|
@ -119,7 +120,8 @@ void FormRender::startRender()
|
|||
{
|
||||
delete _renderer;
|
||||
}
|
||||
_renderer = new SoftwareRenderer(DesktopScenery::getCurrent());
|
||||
_renderer = new SoftwareCanvasRenderer();
|
||||
_renderer->setScenery(DesktopScenery::getCurrent());
|
||||
_renderer_inited = true;
|
||||
|
||||
DialogRender* dialog = new DialogRender(this, _renderer);
|
||||
|
|
|
@ -31,7 +31,7 @@ protected slots:
|
|||
private:
|
||||
RenderArea::RenderParams _params;
|
||||
CameraDefinition* _camera;
|
||||
SoftwareRenderer* _renderer;
|
||||
SoftwareCanvasRenderer* _renderer;
|
||||
bool _renderer_inited;
|
||||
BasePreview* _preview_landscape;
|
||||
Base2dPreviewRenderer* _preview_landscape_renderer;
|
||||
|
|
|
@ -13,7 +13,7 @@ Canvas::Canvas()
|
|||
height = 1;
|
||||
portions.push_back(new CanvasPortion());
|
||||
|
||||
preview = new CanvasPreview();
|
||||
preview = new CanvasPreview;
|
||||
}
|
||||
|
||||
Canvas::~Canvas()
|
||||
|
@ -27,8 +27,8 @@ Canvas::~Canvas()
|
|||
|
||||
void Canvas::setSize(int width, int height)
|
||||
{
|
||||
horizontal_portion_count = 1 + width / 400;
|
||||
vertical_portion_count = 1 + height / 400;
|
||||
horizontal_portion_count = 1 + (width - 1) / 400;
|
||||
vertical_portion_count = 1 + (height - 1) / 400;
|
||||
|
||||
int portion_width = width / horizontal_portion_count;
|
||||
int portion_height = height / vertical_portion_count;
|
||||
|
@ -47,7 +47,7 @@ void Canvas::setSize(int width, int height)
|
|||
done_width = 0;
|
||||
for (int x = 0; x < horizontal_portion_count; x++)
|
||||
{
|
||||
CanvasPortion *portion = new CanvasPortion();
|
||||
CanvasPortion *portion = new CanvasPortion(preview);
|
||||
|
||||
portion->setSize((x == horizontal_portion_count - 1) ? width - done_width : portion_width,
|
||||
(y == vertical_portion_count - 1) ? height - done_height : portion_height);
|
||||
|
|
|
@ -7,5 +7,10 @@ CanvasFragment::CanvasFragment()
|
|||
CanvasFragment::CanvasFragment(double z, const Vector3 &location, int client, bool opaque):
|
||||
z(z), location(location), client(client), opaque(opaque)
|
||||
{
|
||||
color = COLOR_BLACK;
|
||||
color = COLOR_WHITE;
|
||||
}
|
||||
|
||||
void CanvasFragment::setColor(const Color &col)
|
||||
{
|
||||
color = col;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
CanvasFragment();
|
||||
CanvasFragment(double z, const Vector3 &location, int client=0, bool opaque=true);
|
||||
|
||||
void setColor(const Color &col);
|
||||
|
||||
inline bool getOpaque() const {return opaque;}
|
||||
inline double getZ() const {return z;}
|
||||
inline const Vector3 &getLocation() const {return location;}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
CanvasPixel::CanvasPixel()
|
||||
{
|
||||
count = 0;
|
||||
composite = COLOR_BLACK;
|
||||
}
|
||||
|
||||
const CanvasFragment *CanvasPixel::getFrontFragment() const
|
||||
|
@ -85,4 +86,16 @@ void CanvasPixel::pushFragment(const CanvasFragment &fragment)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateComposite();
|
||||
}
|
||||
|
||||
void CanvasPixel::updateComposite()
|
||||
{
|
||||
Color result(0.0, 0.0, 0.0, 1.0);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result.mask(fragments[i].getColor());
|
||||
}
|
||||
composite = result;
|
||||
}
|
||||
|
|
|
@ -21,14 +21,17 @@ public:
|
|||
CanvasPixel();
|
||||
|
||||
inline int getFragmentCount() const {return count;}
|
||||
inline const Color &getComposite() const {return composite;}
|
||||
const CanvasFragment *getFrontFragment() const;
|
||||
|
||||
void reset();
|
||||
void pushFragment(const CanvasFragment &fragment);
|
||||
void updateComposite();
|
||||
|
||||
private:
|
||||
int count;
|
||||
CanvasFragment fragments[MAX_FRAGMENT_COUNT];
|
||||
Color composite;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
#include <cassert>
|
||||
|
||||
#include "CanvasPixel.h"
|
||||
#include "CanvasPreview.h"
|
||||
|
||||
#define CHECK_COORDINATES() assert(x >= 0); \
|
||||
assert(x < width); \
|
||||
assert(y >= 0); \
|
||||
assert(y < height)
|
||||
|
||||
CanvasPortion::CanvasPortion()
|
||||
CanvasPortion::CanvasPortion(CanvasPreview* preview):
|
||||
preview(preview)
|
||||
{
|
||||
width = 1;
|
||||
height = 1;
|
||||
|
@ -58,5 +60,12 @@ void CanvasPortion::pushFragment(int x, int y, const CanvasFragment &fragment)
|
|||
CHECK_COORDINATES();
|
||||
|
||||
CanvasPixel &pixel = pixels[y * width + x];
|
||||
Color old_color = pixel.getComposite();
|
||||
|
||||
pixel.pushFragment(fragment);
|
||||
|
||||
if (preview)
|
||||
{
|
||||
preview->pushPixel(x, y, old_color, pixel.getComposite());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace software {
|
|||
class SOFTWARESHARED_EXPORT CanvasPortion
|
||||
{
|
||||
public:
|
||||
CanvasPortion();
|
||||
CanvasPortion(CanvasPreview* preview=NULL);
|
||||
~CanvasPortion();
|
||||
|
||||
inline int getWidth() const {return width;}
|
||||
|
@ -36,6 +36,7 @@ private:
|
|||
int width;
|
||||
int height;
|
||||
CanvasPixel *pixels;
|
||||
CanvasPreview* preview;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,22 +1,137 @@
|
|||
#include "CanvasPreview.h"
|
||||
|
||||
#include "Color.h"
|
||||
#include "CanvasLiveClient.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
CanvasPreview::CanvasPreview()
|
||||
{
|
||||
width = 1;
|
||||
height = 1;
|
||||
pixels = new CanvasPreviewPixel[1];
|
||||
pixels = new Color[1];
|
||||
|
||||
dirty_left = 1;
|
||||
dirty_right = -1;
|
||||
dirty_down = 1;
|
||||
dirty_up = -1;
|
||||
|
||||
lock = new Mutex();
|
||||
}
|
||||
|
||||
CanvasPreview::~CanvasPreview()
|
||||
{
|
||||
delete [] pixels;
|
||||
delete lock;
|
||||
}
|
||||
|
||||
void CanvasPreview::setSize(int real_width, int real_height, int preview_width, int preview_height)
|
||||
{
|
||||
lock->acquire();
|
||||
|
||||
delete [] pixels;
|
||||
pixels = new CanvasPreviewPixel[preview_width * preview_height];
|
||||
pixels = new Color[preview_width * preview_height];
|
||||
|
||||
width = preview_width;
|
||||
height = preview_height;
|
||||
|
||||
dirty_left = width;
|
||||
dirty_right = -1;
|
||||
dirty_down = height;
|
||||
dirty_up = -1;
|
||||
|
||||
lock->release();
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void CanvasPreview::reset()
|
||||
{
|
||||
lock->acquire();
|
||||
|
||||
int n = width * height;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
pixels[i] = COLOR_BLACK;
|
||||
}
|
||||
|
||||
lock->release();
|
||||
}
|
||||
|
||||
void CanvasPreview::initLive(CanvasLiveClient *client)
|
||||
{
|
||||
client->canvasResized(width, height);
|
||||
client->canvasCleared(COLOR_BLACK);
|
||||
|
||||
setAllDirty();
|
||||
}
|
||||
|
||||
void CanvasPreview::updateLive(CanvasLiveClient *client)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
lock->acquire();
|
||||
|
||||
for (y = dirty_down; y <= dirty_up; y++)
|
||||
{
|
||||
for (x = dirty_left; x <= dirty_right; x++)
|
||||
{
|
||||
client->canvasPainted(x, y, pixels[y * width + x]);
|
||||
}
|
||||
}
|
||||
|
||||
dirty_left = width;
|
||||
dirty_right = -1;
|
||||
dirty_down = height;
|
||||
dirty_up = -1;
|
||||
|
||||
lock->release();
|
||||
}
|
||||
|
||||
void CanvasPreview::pushPixel(int real_x, int real_y, const Color &old_color, const Color &new_color)
|
||||
{
|
||||
lock->acquire();
|
||||
|
||||
// TODO Assert-check and transform coordinates
|
||||
int x = real_x;
|
||||
int y = real_y;
|
||||
double fact = 1.0;
|
||||
|
||||
Color* pixel = pixels + (real_y * width + real_x);
|
||||
pixel->r = pixel->r - old_color.r * fact + new_color.r * fact;
|
||||
pixel->g = pixel->g - old_color.g * fact + new_color.g * fact;
|
||||
pixel->b = pixel->b - old_color.b * fact + new_color.b * fact;
|
||||
|
||||
// Set pixel dirty
|
||||
if (x < dirty_left)
|
||||
{
|
||||
dirty_left = x;
|
||||
}
|
||||
if (x > dirty_right)
|
||||
{
|
||||
dirty_right = x;
|
||||
}
|
||||
if (y < dirty_down)
|
||||
{
|
||||
dirty_down = y;
|
||||
}
|
||||
if (y > dirty_up)
|
||||
{
|
||||
dirty_up = y;
|
||||
}
|
||||
|
||||
lock->release();
|
||||
}
|
||||
|
||||
void CanvasPreview::setAllDirty()
|
||||
{
|
||||
lock->acquire();
|
||||
|
||||
dirty_left = 0;
|
||||
dirty_right = width - 1;
|
||||
dirty_down = 0;
|
||||
dirty_up = height - 1;
|
||||
|
||||
lock->release();
|
||||
}
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
typedef struct {
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
} CanvasPreviewPixel;
|
||||
|
||||
/**
|
||||
* @brief Smaller preview of a Canvas rendering, that can be watched live.
|
||||
*/
|
||||
|
@ -27,15 +21,25 @@ public:
|
|||
void setSize(int real_width, int real_height, int preview_width, int preview_height);
|
||||
void reset();
|
||||
|
||||
void initLive(CanvasLiveClient &client);
|
||||
void updateLive(CanvasLiveClient &client);
|
||||
void initLive(CanvasLiveClient *client);
|
||||
void updateLive(CanvasLiveClient *client);
|
||||
|
||||
void pushPixel(int real_x, int real_y, Color old_color, Color new_color);
|
||||
void pushPixel(int real_x, int real_y, const Color &old_color, const Color &new_color);
|
||||
|
||||
protected:
|
||||
void setAllDirty();
|
||||
|
||||
private:
|
||||
CanvasPreviewPixel *pixels;
|
||||
Mutex *lock;
|
||||
|
||||
Color *pixels;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int dirty_left;
|
||||
int dirty_right;
|
||||
int dirty_down;
|
||||
int dirty_up;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,337 @@
|
|||
#include "Rasterizer.h"
|
||||
|
||||
Rasterizer::Rasterizer()
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "CameraDefinition.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasFragment.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
struct paysages::software::ScanPoint
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} pixel;
|
||||
struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} location;
|
||||
int client;
|
||||
};
|
||||
|
||||
struct paysages::software::RenderScanlines
|
||||
{
|
||||
ScanPoint* up;
|
||||
ScanPoint* down;
|
||||
int left;
|
||||
int right;
|
||||
};
|
||||
|
||||
Rasterizer::Rasterizer(SoftwareRenderer* renderer, int client_id):
|
||||
renderer(renderer), client_id(client_id)
|
||||
{
|
||||
}
|
||||
|
||||
Rasterizer::~Rasterizer()
|
||||
{
|
||||
}
|
||||
|
||||
void Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3)
|
||||
{
|
||||
ScanPoint point1, point2, point3;
|
||||
double limit_width = (double)(canvas->getWidth() - 1);
|
||||
double limit_height = (double)(canvas->getHeight() - 1);
|
||||
|
||||
/* Filter if outside screen */
|
||||
if (pixel1.z < 1.0 || pixel2.z < 1.0 || pixel3.z < 1.0 || (pixel1.x < 0.0 && pixel2.x < 0.0 && pixel3.x < 0.0) || (pixel1.y < 0.0 && pixel2.y < 0.0 && pixel3.y < 0.0) || (pixel1.x > limit_width && pixel2.x > limit_width && pixel3.x > limit_width) || (pixel1.y > limit_height && pixel2.y > limit_height && pixel3.y > limit_height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepare vertices */
|
||||
// FIXME Apply canvas portion offset
|
||||
point1.pixel.x = pixel1.x;
|
||||
point1.pixel.y = pixel1.y;
|
||||
point1.pixel.z = pixel1.z;
|
||||
point1.location.x = location1.x;
|
||||
point1.location.y = location1.y;
|
||||
point1.location.z = location1.z;
|
||||
point1.client = client_id;
|
||||
|
||||
point2.pixel.x = pixel2.x;
|
||||
point2.pixel.y = pixel2.y;
|
||||
point2.pixel.z = pixel2.z;
|
||||
point2.location.x = location2.x;
|
||||
point2.location.y = location2.y;
|
||||
point2.location.z = location2.z;
|
||||
point2.client = client_id;
|
||||
|
||||
point3.pixel.x = pixel3.x;
|
||||
point3.pixel.y = pixel3.y;
|
||||
point3.pixel.z = pixel3.z;
|
||||
point3.location.x = location3.x;
|
||||
point3.location.y = location3.y;
|
||||
point3.location.z = location3.z;
|
||||
point3.client = client_id;
|
||||
|
||||
/* Prepare scanlines */
|
||||
// TODO Don't create scanlines for each triangles (one by thread is more appropriate)
|
||||
RenderScanlines scanlines;
|
||||
int width = canvas->getWidth();
|
||||
scanlines.left = width;
|
||||
scanlines.right = -1;
|
||||
scanlines.up = new ScanPoint[width];
|
||||
scanlines.down = new ScanPoint[width];
|
||||
|
||||
/* Render edges in scanlines */
|
||||
pushScanLineEdge(canvas, &scanlines, &point1, &point2);
|
||||
pushScanLineEdge(canvas, &scanlines, &point2, &point3);
|
||||
pushScanLineEdge(canvas, &scanlines, &point3, &point1);
|
||||
|
||||
/* Commit scanlines to area */
|
||||
renderScanLines(canvas, &scanlines);
|
||||
|
||||
/* Free scalines */
|
||||
delete[] scanlines.up;
|
||||
delete[] scanlines.down;
|
||||
}
|
||||
|
||||
void Rasterizer::pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
|
||||
{
|
||||
Vector3 p1, p2, p3;
|
||||
|
||||
p1 = getRenderer()->projectPoint(v1);
|
||||
p2 = getRenderer()->projectPoint(v2);
|
||||
p3 = getRenderer()->projectPoint(v3);
|
||||
|
||||
pushProjectedTriangle(canvas, p1, p2, p3, v1, v2, v3);
|
||||
}
|
||||
|
||||
void Rasterizer::pushQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4)
|
||||
{
|
||||
pushTriangle(canvas, v2, v3, v1);
|
||||
pushTriangle(canvas, v4, v1, v3);
|
||||
}
|
||||
|
||||
void Rasterizer::pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3)
|
||||
{
|
||||
Vector3 p1, p2, p3;
|
||||
|
||||
p1 = getRenderer()->projectPoint(v1);
|
||||
p2 = getRenderer()->projectPoint(v2);
|
||||
p3 = getRenderer()->projectPoint(v3);
|
||||
|
||||
pushProjectedTriangle(canvas, p1, p2, p3, ov1, ov2, ov3);
|
||||
}
|
||||
|
||||
void Rasterizer::pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4)
|
||||
{
|
||||
pushDisplacedTriangle(canvas, v2, v3, v1, ov2, ov3, ov1);
|
||||
pushDisplacedTriangle(canvas, v4, v1, v3, ov4, ov1, ov3);
|
||||
}
|
||||
|
||||
void Rasterizer::rasterizeToCanvas(CanvasPortion *)
|
||||
{
|
||||
}
|
||||
|
||||
void Rasterizer::scanGetDiff(ScanPoint* v1, ScanPoint* v2, ScanPoint* result)
|
||||
{
|
||||
result->pixel.x = v2->pixel.x - v1->pixel.x;
|
||||
result->pixel.y = v2->pixel.y - v1->pixel.y;
|
||||
result->pixel.z = v2->pixel.z - v1->pixel.z;
|
||||
result->location.x = v2->location.x - v1->location.x;
|
||||
result->location.y = v2->location.y - v1->location.y;
|
||||
result->location.z = v2->location.z - v1->location.z;
|
||||
result->client = v1->client;
|
||||
}
|
||||
|
||||
void Rasterizer::scanInterpolate(CameraDefinition* camera, ScanPoint* v1, ScanPoint* diff, double value, ScanPoint* result)
|
||||
{
|
||||
Vector3 vec1(v1->pixel.x, v1->pixel.y, v1->pixel.z);
|
||||
Vector3 vecdiff(diff->pixel.x, diff->pixel.y, diff->pixel.z);
|
||||
double v1depth = camera->getRealDepth(vec1);
|
||||
double v2depth = camera->getRealDepth(vec1.add(vecdiff));
|
||||
double factor = ((1.0 - value) / v1depth + value / v2depth);
|
||||
|
||||
result->pixel.x = v1->pixel.x + diff->pixel.x * value;
|
||||
result->pixel.y = v1->pixel.y + diff->pixel.y * value;
|
||||
result->pixel.z = v1->pixel.z + diff->pixel.z * value;
|
||||
result->location.x = ((1.0 - value) * (v1->location.x / v1depth) + value * (v1->location.x + diff->location.x) / v2depth) / factor;
|
||||
result->location.y = ((1.0 - value) * (v1->location.y / v1depth) + value * (v1->location.y + diff->location.y) / v2depth) / factor;
|
||||
result->location.z = ((1.0 - value) * (v1->location.z / v1depth) + value * (v1->location.z + diff->location.z) / v2depth) / factor;
|
||||
result->client = v1->client;
|
||||
}
|
||||
|
||||
void Rasterizer::pushScanPoint(CanvasPortion* canvas, RenderScanlines* scanlines, ScanPoint* point)
|
||||
{
|
||||
point->x = (int)floor(point->pixel.x);
|
||||
point->y = (int)floor(point->pixel.y);
|
||||
|
||||
if (point->x < 0 || point->x >= canvas->getWidth())
|
||||
{
|
||||
// Point outside scanline range
|
||||
return;
|
||||
}
|
||||
else if (scanlines->right < 0)
|
||||
{
|
||||
// First point pushed
|
||||
scanlines->left = point->x;
|
||||
scanlines->right = point->x;
|
||||
scanlines->up[point->x] = *point;
|
||||
scanlines->down[point->x] = *point;
|
||||
}
|
||||
else if (point->x > scanlines->right)
|
||||
{
|
||||
// Grow scanlines to right
|
||||
for (int x = scanlines->right + 1; x < point->x; x++)
|
||||
{
|
||||
scanlines->up[x].y = -1;
|
||||
scanlines->down[x].y = canvas->getHeight();
|
||||
}
|
||||
scanlines->right = point->x;
|
||||
scanlines->up[point->x] = *point;
|
||||
scanlines->down[point->x] = *point;
|
||||
}
|
||||
else if (point->x < scanlines->left)
|
||||
{
|
||||
// Grow scanlines to left
|
||||
for (int x = point->x + 1; x < scanlines->left; x++)
|
||||
{
|
||||
scanlines->up[x].y = -1;
|
||||
scanlines->down[x].y = canvas->getHeight();
|
||||
}
|
||||
scanlines->left = point->x;
|
||||
scanlines->up[point->x] = *point;
|
||||
scanlines->down[point->x] = *point;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Expand existing scanline
|
||||
if (point->y > scanlines->up[point->x].y)
|
||||
{
|
||||
scanlines->up[point->x] = *point;
|
||||
}
|
||||
if (point->y < scanlines->down[point->x].y)
|
||||
{
|
||||
scanlines->down[point->x] = *point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rasterizer::pushScanLineEdge(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point1, ScanPoint *point2)
|
||||
{
|
||||
double dx, fx;
|
||||
ScanPoint diff, point;
|
||||
int startx = lround(point1->pixel.x);
|
||||
int endx = lround(point2->pixel.x);
|
||||
int curx;
|
||||
|
||||
if (endx < startx)
|
||||
{
|
||||
pushScanLineEdge(canvas, scanlines, point2, point1);
|
||||
}
|
||||
else if (endx < 0 || startx >= canvas->getWidth())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (startx == endx)
|
||||
{
|
||||
pushScanPoint(canvas, scanlines, point1);
|
||||
pushScanPoint(canvas, scanlines, point2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startx < 0)
|
||||
{
|
||||
startx = 0;
|
||||
}
|
||||
if (endx >= canvas->getWidth())
|
||||
{
|
||||
endx = canvas->getWidth() - 1;
|
||||
}
|
||||
|
||||
dx = point2->pixel.x - point1->pixel.x;
|
||||
scanGetDiff(point1, point2, &diff);
|
||||
for (curx = startx; curx <= endx; curx++)
|
||||
{
|
||||
fx = (double)curx + 0.5;
|
||||
if (fx < point1->pixel.x)
|
||||
{
|
||||
fx = point1->pixel.x;
|
||||
}
|
||||
else if (fx > point2->pixel.x)
|
||||
{
|
||||
fx = point2->pixel.x;
|
||||
}
|
||||
fx = fx - point1->pixel.x;
|
||||
scanInterpolate(renderer->render_camera, point1, &diff, fx / dx, &point);
|
||||
|
||||
/*point.pixel.x = (double)curx;*/
|
||||
|
||||
pushScanPoint(canvas, scanlines, &point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rasterizer::renderScanLines(CanvasPortion *canvas, RenderScanlines* scanlines)
|
||||
{
|
||||
int x, starty, endy, cury;
|
||||
ScanPoint diff;
|
||||
double dy, fy;
|
||||
ScanPoint up, down, current;
|
||||
|
||||
if (scanlines->right > 0)
|
||||
{
|
||||
for (x = scanlines->left; x <= scanlines->right; x++)
|
||||
{
|
||||
up = scanlines->up[x];
|
||||
down = scanlines->down[x];
|
||||
|
||||
starty = down.y;
|
||||
endy = up.y;
|
||||
|
||||
if (endy < 0 || starty >= canvas->getHeight())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (starty < 0)
|
||||
{
|
||||
starty = 0;
|
||||
}
|
||||
if (endy >= canvas->getHeight())
|
||||
{
|
||||
endy = canvas->getHeight() - 1;
|
||||
}
|
||||
|
||||
dy = up.pixel.y - down.pixel.y;
|
||||
scanGetDiff(&down, &up, &diff);
|
||||
|
||||
current.x = x;
|
||||
for (cury = starty; cury <= endy; cury++)
|
||||
{
|
||||
fy = (double)cury + 0.5;
|
||||
if (fy < down.pixel.y)
|
||||
{
|
||||
fy = down.pixel.y;
|
||||
}
|
||||
else if (fy > up.pixel.y)
|
||||
{
|
||||
fy = up.pixel.y;
|
||||
}
|
||||
fy = fy - down.pixel.y;
|
||||
|
||||
current.y = cury;
|
||||
scanInterpolate(renderer->render_camera, &down, &diff, fy / dy, ¤t);
|
||||
|
||||
CanvasFragment fragment(current.pixel.z, Vector3(current.location.x, current.location.y, current.location.z), current.client);
|
||||
fragment.setColor((cury == starty || cury == endy) ? COLOR_GREY : COLOR_WHITE);
|
||||
canvas->pushFragment(current.x, current.y, fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,40 @@
|
|||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
typedef struct ScanPoint ScanPoint;
|
||||
typedef struct RenderScanlines RenderScanlines;
|
||||
|
||||
/**
|
||||
* @brief Base abstract class for scenery pieces that can be rasterized to polygons.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT Rasterizer
|
||||
{
|
||||
public:
|
||||
Rasterizer();
|
||||
Rasterizer(SoftwareRenderer *renderer, int client_id);
|
||||
virtual ~Rasterizer();
|
||||
|
||||
inline SoftwareRenderer *getRenderer() const {return renderer;}
|
||||
|
||||
virtual void rasterize() = 0;
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
||||
|
||||
protected:
|
||||
void pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3);
|
||||
|
||||
void pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3);
|
||||
void pushQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4);
|
||||
void pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3);
|
||||
void pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4);
|
||||
|
||||
SoftwareRenderer *renderer;
|
||||
int client_id;
|
||||
|
||||
private:
|
||||
void scanGetDiff(ScanPoint *v1, ScanPoint *v2, ScanPoint *result);
|
||||
void scanInterpolate(CameraDefinition *camera, ScanPoint *v1, ScanPoint *diff, double value, ScanPoint *result);
|
||||
void pushScanPoint(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point);
|
||||
void pushScanLineEdge(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point1, ScanPoint *point2);
|
||||
void renderScanLines(CanvasPortion *canvas, RenderScanlines *scanlines);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
#include "AtmosphereRenderer.h"
|
||||
#include "AtmosphereResult.h"
|
||||
#include "CloudsRenderer.h"
|
||||
#include "Rasterizer.h"
|
||||
|
||||
#define SPHERE_SIZE 20000.0
|
||||
|
||||
SkyRasterizer::SkyRasterizer(SoftwareRenderer* renderer):
|
||||
renderer(renderer)
|
||||
SkyRasterizer::SkyRasterizer(SoftwareRenderer* renderer, int client_id):
|
||||
Rasterizer(renderer, client_id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -83,3 +84,58 @@ void SkyRasterizer::rasterize()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkyRasterizer::rasterizeToCanvas(CanvasPortion* canvas)
|
||||
{
|
||||
int res_i, res_j;
|
||||
int i, j;
|
||||
double step_i, step_j;
|
||||
double current_i, current_j;
|
||||
Vector3 vertex1, vertex2, vertex3, vertex4;
|
||||
Vector3 camera_location, direction;
|
||||
|
||||
res_i = renderer->render_quality * 40;
|
||||
res_j = renderer->render_quality * 20;
|
||||
step_i = M_PI * 2.0 / (double)res_i;
|
||||
step_j = M_PI / (double)res_j;
|
||||
|
||||
camera_location = renderer->getCameraLocation(VECTOR_ZERO);
|
||||
|
||||
for (j = 0; j < res_j; j++)
|
||||
{
|
||||
if (!renderer->addRenderProgress(0.0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current_j = (double)(j - res_j / 2) * step_j;
|
||||
|
||||
for (i = 0; i < res_i; i++)
|
||||
{
|
||||
current_i = (double)i * step_i;
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j);
|
||||
vertex1 = camera_location.add(direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j);
|
||||
vertex2 = camera_location.add(direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j + step_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j + step_j);
|
||||
vertex3 = camera_location.add(direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j + step_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j + step_j);
|
||||
vertex4 = camera_location.add(direction);
|
||||
|
||||
/* TODO Triangles at poles */
|
||||
pushQuad(canvas, vertex1, vertex4, vertex3, vertex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,10 @@ namespace software {
|
|||
class SOFTWARESHARED_EXPORT SkyRasterizer: public Rasterizer
|
||||
{
|
||||
public:
|
||||
SkyRasterizer(SoftwareRenderer* renderer);
|
||||
void rasterize();
|
||||
SkyRasterizer(SoftwareRenderer* renderer, int client_id);
|
||||
|
||||
private:
|
||||
SoftwareRenderer* renderer;
|
||||
virtual void rasterize();
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,18 +3,29 @@
|
|||
#include "Rasterizer.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "Canvas.h"
|
||||
#include "TerrainRasterizer.h"
|
||||
#include "WaterRasterizer.h"
|
||||
#include "SkyRasterizer.h"
|
||||
#include "CameraDefinition.h"
|
||||
|
||||
SoftwareCanvasRenderer::SoftwareCanvasRenderer()
|
||||
{
|
||||
started = false;
|
||||
renderer = new SoftwareRenderer();
|
||||
canvas = new Canvas();
|
||||
|
||||
rasterizers.push_back(new TerrainRasterizer(this, 0));
|
||||
rasterizers.push_back(new WaterRasterizer(this, 1));
|
||||
rasterizers.push_back(new SkyRasterizer(this, 2));
|
||||
}
|
||||
|
||||
SoftwareCanvasRenderer::~SoftwareCanvasRenderer()
|
||||
{
|
||||
delete renderer;
|
||||
delete canvas;
|
||||
|
||||
for (auto &rasterizer: rasterizers)
|
||||
{
|
||||
delete rasterizer;
|
||||
}
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::setSize(int width, int height, int samples)
|
||||
|
@ -31,17 +42,22 @@ void SoftwareCanvasRenderer::render()
|
|||
started = true;
|
||||
CanvasPortion *portion = canvas->at(0, 0);
|
||||
|
||||
render_camera->setRenderSize(canvas->getWidth(), canvas->getHeight());
|
||||
|
||||
rasterize(portion, true);
|
||||
postProcess(portion, true);
|
||||
}
|
||||
|
||||
const std::vector<Rasterizer *> &SoftwareCanvasRenderer::getRasterizers() const
|
||||
{
|
||||
return rasterizers;
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded)
|
||||
{
|
||||
std::vector<Rasterizer> rasterizers;
|
||||
renderer->getRasterizers(&rasterizers);
|
||||
|
||||
for (auto &rasterizer:rasterizers)
|
||||
for (auto &rasterizer:getRasterizers())
|
||||
{
|
||||
rasterizer->rasterizeToCanvas(portion);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "SoftwareRenderer.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
|
@ -14,11 +16,11 @@ namespace software {
|
|||
*
|
||||
* It tries to keep a canvas portion rasterized ahead of the post processing.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT SoftwareCanvasRenderer
|
||||
class SOFTWARESHARED_EXPORT SoftwareCanvasRenderer: public SoftwareRenderer
|
||||
{
|
||||
public:
|
||||
SoftwareCanvasRenderer();
|
||||
~SoftwareCanvasRenderer();
|
||||
virtual ~SoftwareCanvasRenderer();
|
||||
|
||||
inline const Canvas *getCanvas() const {return canvas;}
|
||||
|
||||
|
@ -34,6 +36,11 @@ public:
|
|||
*/
|
||||
void render();
|
||||
|
||||
/*!
|
||||
* \brief Get the list of objects that can be rasterized to polygons on a canvas.
|
||||
*/
|
||||
virtual const std::vector<Rasterizer*> &getRasterizers() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Rasterize the scenery into a canvas portion.
|
||||
|
@ -50,8 +57,8 @@ protected:
|
|||
void postProcess(CanvasPortion* portion, bool threaded=true);
|
||||
|
||||
private:
|
||||
SoftwareRenderer* renderer;
|
||||
Canvas* canvas;
|
||||
std::vector<Rasterizer*> rasterizers;
|
||||
bool started;
|
||||
};
|
||||
|
||||
|
|
|
@ -108,22 +108,15 @@ void SoftwareRenderer::prepare()
|
|||
//fluid_medium->registerMedium(water_renderer);
|
||||
}
|
||||
|
||||
void SoftwareRenderer::getRasterizers(std::vector<Rasterizer> *array)
|
||||
{
|
||||
array->push_back(TerrainRasterizer(this));
|
||||
array->push_back(WaterRasterizer(this));
|
||||
array->push_back(SkyRasterizer(this));
|
||||
}
|
||||
|
||||
void SoftwareRenderer::rasterize()
|
||||
{
|
||||
TerrainRasterizer terrain(this);
|
||||
terrain.renderSurface();
|
||||
TerrainRasterizer terrain(this, 0);
|
||||
terrain.rasterize();
|
||||
|
||||
WaterRasterizer water(this);
|
||||
water.renderSurface();
|
||||
WaterRasterizer water(this, 1);
|
||||
water.rasterize();
|
||||
|
||||
SkyRasterizer sky(this);
|
||||
SkyRasterizer sky(this, 2);
|
||||
sky.rasterize();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,11 +59,6 @@ public:
|
|||
*/
|
||||
virtual void prepare();
|
||||
|
||||
/*!
|
||||
* \brief Get the list of objects that can be rasterized to polygons on a canvas.
|
||||
*/
|
||||
virtual void getRasterizers(std::vector<Rasterizer> *array);
|
||||
|
||||
/*!
|
||||
* \brief Start the rasterization process.
|
||||
*/
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#include "Scenery.h"
|
||||
#include "ParallelQueue.h"
|
||||
|
||||
TerrainRasterizer::TerrainRasterizer(SoftwareRenderer* renderer):
|
||||
renderer(renderer)
|
||||
TerrainRasterizer::TerrainRasterizer(SoftwareRenderer* renderer, int client_id):
|
||||
Rasterizer(renderer, client_id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ int TerrainRasterizer::processChunk(TerrainChunkInfo* chunk, double progress)
|
|||
return !renderer->render_interrupt;
|
||||
}
|
||||
|
||||
void TerrainRasterizer::renderSurface()
|
||||
void TerrainRasterizer::rasterize()
|
||||
{
|
||||
queue = new ParallelQueue();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
} TerrainChunkInfo;
|
||||
|
||||
public:
|
||||
TerrainRasterizer(SoftwareRenderer* renderer);
|
||||
TerrainRasterizer(SoftwareRenderer* renderer, int client_id);
|
||||
|
||||
/**
|
||||
* Method called for each chunk tessellated by getTessellationInfo.
|
||||
|
@ -46,10 +46,9 @@ public:
|
|||
*
|
||||
* This will push the rasterized quads in the render area, waiting for post process.
|
||||
*/
|
||||
void renderSurface();
|
||||
virtual void rasterize();
|
||||
|
||||
private:
|
||||
SoftwareRenderer* renderer;
|
||||
ParallelQueue* queue;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "WaterRenderer.h"
|
||||
#include "ParallelQueue.h"
|
||||
|
||||
WaterRasterizer::WaterRasterizer(SoftwareRenderer* renderer):
|
||||
renderer(renderer)
|
||||
WaterRasterizer::WaterRasterizer(SoftwareRenderer* renderer, int client_id):
|
||||
Rasterizer(renderer, client_id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ static int _parallelJobCallback(ParallelQueue*, int, void* data, int stopping)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void WaterRasterizer::renderSurface()
|
||||
void WaterRasterizer::rasterize()
|
||||
{
|
||||
ParallelRasterInfo* info;
|
||||
ParallelQueue* queue;
|
||||
|
|
|
@ -11,12 +11,9 @@ namespace software {
|
|||
class WaterRasterizer: public Rasterizer
|
||||
{
|
||||
public:
|
||||
WaterRasterizer(SoftwareRenderer* renderer);
|
||||
WaterRasterizer(SoftwareRenderer* renderer, int client_id);
|
||||
|
||||
void renderSurface();
|
||||
|
||||
private:
|
||||
SoftwareRenderer* renderer;
|
||||
virtual void rasterize();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue