WIP on new canvas system
This commit is contained in:
parent
43431aae87
commit
8099361cc9
16 changed files with 381 additions and 30 deletions
|
@ -1,6 +1,7 @@
|
|||
#include "WidgetPreviewCanvas.h"
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "CanvasPreview.h"
|
||||
|
||||
WidgetPreviewCanvas::WidgetPreviewCanvas(QWidget *parent) :
|
||||
QWidget(parent), canvas(NULL)
|
||||
|
@ -31,10 +32,11 @@ void WidgetPreviewCanvas::canvasPainted(int x, int y, const Color &col)
|
|||
void WidgetPreviewCanvas::timerEvent(QTimerEvent *)
|
||||
{
|
||||
// Refresh the view
|
||||
CanvasPreview *preview = canvas->getPreview();
|
||||
if (canvas)
|
||||
{
|
||||
int width = canvas->getPreviewWidth();
|
||||
int height = canvas->getPreviewHeight();
|
||||
int width = preview->getWidth();
|
||||
int height = preview->getHeight();
|
||||
|
||||
if (QSize(width, height) != this->size())
|
||||
{
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
#include "Canvas.h"
|
||||
|
||||
#include "CanvasPortion.h"
|
||||
#include <cassert>
|
||||
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasPreview.h"
|
||||
|
||||
Canvas::Canvas()
|
||||
{
|
||||
horizontal_portion_count = 1;
|
||||
vertical_portion_count = 1;
|
||||
width = 1;
|
||||
height = 1;
|
||||
preview_width = 1;
|
||||
preview_height = 1;
|
||||
portions.push_back(new CanvasPortion());
|
||||
|
||||
preview = new CanvasPreview();
|
||||
}
|
||||
|
||||
Canvas::~Canvas()
|
||||
|
@ -20,6 +22,7 @@ Canvas::~Canvas()
|
|||
{
|
||||
delete portion;
|
||||
}
|
||||
delete preview;
|
||||
}
|
||||
|
||||
void Canvas::setSize(int width, int height)
|
||||
|
@ -63,8 +66,9 @@ void Canvas::setSize(int width, int height)
|
|||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->preview_width = width;
|
||||
this->preview_height = height;
|
||||
|
||||
// TODO Smaller preview
|
||||
preview->setSize(width, height, width, height);
|
||||
}
|
||||
|
||||
CanvasPortion *Canvas::at(int x, int y) const
|
||||
|
|
|
@ -27,8 +27,7 @@ public:
|
|||
|
||||
inline int getWidth() const {return width;}
|
||||
inline int getHeight() const {return height;}
|
||||
inline int getPreviewWidth() const {return preview_width;}
|
||||
inline int getPreviewHeight() const {return preview_height;}
|
||||
inline CanvasPreview *getPreview() const {return preview;}
|
||||
|
||||
private:
|
||||
std::vector<CanvasPortion*> portions;
|
||||
|
@ -36,8 +35,8 @@ private:
|
|||
int vertical_portion_count;
|
||||
int width;
|
||||
int height;
|
||||
int preview_width;
|
||||
int preview_height;
|
||||
|
||||
CanvasPreview *preview;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,3 +3,9 @@
|
|||
CanvasFragment::CanvasFragment()
|
||||
{
|
||||
}
|
||||
|
||||
CanvasFragment::CanvasFragment(double z, const Vector3 &location, int client, bool opaque):
|
||||
z(z), location(location), client(client), opaque(opaque)
|
||||
{
|
||||
color = COLOR_BLACK;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "Color.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
|
@ -13,6 +16,20 @@ class SOFTWARESHARED_EXPORT CanvasFragment
|
|||
{
|
||||
public:
|
||||
CanvasFragment();
|
||||
CanvasFragment(double z, const Vector3 &location, int client=0, bool opaque=true);
|
||||
|
||||
inline bool getOpaque() const {return opaque;}
|
||||
inline double getZ() const {return z;}
|
||||
inline const Vector3 &getLocation() const {return location;}
|
||||
inline int getClient() const {return client;}
|
||||
inline const Color &getColor() const {return color;}
|
||||
|
||||
private:
|
||||
bool opaque;
|
||||
double z;
|
||||
Vector3 location;
|
||||
int client;
|
||||
Color color;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,88 @@
|
|||
#include "CanvasPixel.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
CanvasPixel::CanvasPixel()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
const CanvasFragment *CanvasPixel::getFrontFragment() const
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fragments + (count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasPixel::reset()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void CanvasPixel::pushFragment(const CanvasFragment &fragment)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
fragments[0] = fragment;
|
||||
count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fragments[0].getOpaque() and fragment.getZ() > fragments[0].getZ())
|
||||
{
|
||||
// behind opaque fragment, don't bother
|
||||
return;
|
||||
}
|
||||
|
||||
// find expected position
|
||||
int i = 0;
|
||||
while (i < count and fragment.getZ() < fragments[i].getZ())
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
if (fragment.getOpaque())
|
||||
{
|
||||
// Discard fragments masked by the incoming opaque one
|
||||
if (i < count)
|
||||
{
|
||||
memmove(fragments + 1, fragments + i, sizeof(CanvasFragment) * (count - i));
|
||||
count -= i;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 1;
|
||||
}
|
||||
fragments[0] = fragment;
|
||||
}
|
||||
else if (i < count)
|
||||
{
|
||||
// Need to make room for the incoming fragment
|
||||
if (count < MAX_FRAGMENT_COUNT)
|
||||
{
|
||||
memmove(fragments + i + 1, fragments + i, sizeof(CanvasFragment) * (count - i));
|
||||
fragments[i] = fragment;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count == MAX_FRAGMENT_COUNT)
|
||||
{
|
||||
// Replace nearest fragment
|
||||
fragments[count - 1] = fragment;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append
|
||||
fragments[count] = fragment;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "CanvasFragment.h"
|
||||
|
||||
const int MAX_FRAGMENT_COUNT = 7;
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
|
@ -15,6 +19,16 @@ class SOFTWARESHARED_EXPORT CanvasPixel
|
|||
{
|
||||
public:
|
||||
CanvasPixel();
|
||||
|
||||
inline int getFragmentCount() const {return count;}
|
||||
const CanvasFragment *getFrontFragment() const;
|
||||
|
||||
void reset();
|
||||
void pushFragment(const CanvasFragment &fragment);
|
||||
|
||||
private:
|
||||
int count;
|
||||
CanvasFragment fragments[MAX_FRAGMENT_COUNT];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,62 @@
|
|||
#include "CanvasPortion.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "CanvasPixel.h"
|
||||
|
||||
#define CHECK_COORDINATES() assert(x >= 0); \
|
||||
assert(x < width); \
|
||||
assert(y >= 0); \
|
||||
assert(y < height)
|
||||
|
||||
CanvasPortion::CanvasPortion()
|
||||
{
|
||||
width = 1;
|
||||
height = 1;
|
||||
pixels = new CanvasPixel[1];
|
||||
}
|
||||
|
||||
CanvasPortion::~CanvasPortion()
|
||||
{
|
||||
delete[] pixels;
|
||||
}
|
||||
|
||||
int CanvasPortion::getFragmentCount(int x, int y) const
|
||||
{
|
||||
CHECK_COORDINATES();
|
||||
|
||||
return pixels[y * width + x].getFragmentCount();
|
||||
}
|
||||
|
||||
const CanvasFragment *CanvasPortion::getFrontFragment(int x, int y) const
|
||||
{
|
||||
CHECK_COORDINATES();
|
||||
|
||||
return pixels[y * width + x].getFrontFragment();
|
||||
}
|
||||
|
||||
void CanvasPortion::clear()
|
||||
{
|
||||
int n = width * height;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
pixels[i].reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasPortion::setSize(int width, int height)
|
||||
{
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
// TODO Resize and clear pixels
|
||||
|
||||
delete[] pixels;
|
||||
pixels = new CanvasPixel[width * height];
|
||||
}
|
||||
|
||||
void CanvasPortion::pushFragment(int x, int y, const CanvasFragment &fragment)
|
||||
{
|
||||
CHECK_COORDINATES();
|
||||
|
||||
CanvasPixel &pixel = pixels[y * width + x];
|
||||
pixel.pushFragment(fragment);
|
||||
}
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
typedef struct {
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
} CanvasPreviewPixel;
|
||||
|
||||
/**
|
||||
* @brief Rectangular portion of a Canvas.
|
||||
*
|
||||
|
@ -21,20 +15,27 @@ class SOFTWARESHARED_EXPORT CanvasPortion
|
|||
{
|
||||
public:
|
||||
CanvasPortion();
|
||||
~CanvasPortion();
|
||||
|
||||
inline int getWidth() const {return width;}
|
||||
inline int getHeight() const {return height;}
|
||||
int getFragmentCount(int x, int y) const;
|
||||
const CanvasFragment *getFrontFragment(int x, int y) const;
|
||||
|
||||
void clear();
|
||||
void setSize(int width, int height);
|
||||
|
||||
/**
|
||||
* @brief Add a fragment to the pixel located at (x, y).
|
||||
*
|
||||
* Checking x and y coordinates to be in the canvas portion should be done before this call.
|
||||
*/
|
||||
void pushFragment(int x, int y, const CanvasFragment &fragment);
|
||||
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
std::vector<CanvasPixel> *pixels;
|
||||
|
||||
int preview_width;
|
||||
int preview_height;
|
||||
std::vector<CanvasPreviewPixel> *preview_pixels;
|
||||
CanvasPixel *pixels;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
22
src/render/software/CanvasPreview.cpp
Normal file
22
src/render/software/CanvasPreview.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "CanvasPreview.h"
|
||||
|
||||
CanvasPreview::CanvasPreview()
|
||||
{
|
||||
width = 1;
|
||||
height = 1;
|
||||
pixels = new CanvasPreviewPixel[1];
|
||||
}
|
||||
|
||||
CanvasPreview::~CanvasPreview()
|
||||
{
|
||||
delete [] pixels;
|
||||
}
|
||||
|
||||
void CanvasPreview::setSize(int real_width, int real_height, int preview_width, int preview_height)
|
||||
{
|
||||
delete [] pixels;
|
||||
pixels = new CanvasPreviewPixel[preview_width * preview_height];
|
||||
|
||||
width = preview_width;
|
||||
height = preview_height;
|
||||
}
|
44
src/render/software/CanvasPreview.h
Normal file
44
src/render/software/CanvasPreview.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef CANVASPREVIEW_H
|
||||
#define CANVASPREVIEW_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
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.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT CanvasPreview
|
||||
{
|
||||
public:
|
||||
CanvasPreview();
|
||||
~CanvasPreview();
|
||||
|
||||
inline int getWidth() const {return width;}
|
||||
inline int getHeight() const {return height;}
|
||||
|
||||
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 pushPixel(int real_x, int real_y, Color old_color, Color new_color);
|
||||
|
||||
private:
|
||||
CanvasPreviewPixel *pixels;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CANVASPREVIEW_H
|
|
@ -44,7 +44,8 @@ SOURCES += SoftwareRenderer.cpp \
|
|||
CanvasFragment.cpp \
|
||||
SoftwareCanvasRenderer.cpp \
|
||||
Rasterizer.cpp \
|
||||
CanvasLiveClient.cpp
|
||||
CanvasLiveClient.cpp \
|
||||
CanvasPreview.cpp
|
||||
|
||||
HEADERS += SoftwareRenderer.h\
|
||||
software_global.h \
|
||||
|
@ -78,7 +79,8 @@ HEADERS += SoftwareRenderer.h\
|
|||
CanvasFragment.h \
|
||||
SoftwareCanvasRenderer.h \
|
||||
Rasterizer.h \
|
||||
CanvasLiveClient.h
|
||||
CanvasLiveClient.h \
|
||||
CanvasPreview.h
|
||||
|
||||
unix:!symbian {
|
||||
maemo5 {
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace software {
|
|||
class CanvasPixel;
|
||||
class CanvasFragment;
|
||||
class CanvasLiveClient;
|
||||
class CanvasPreview;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
104
src/tests/CanvasPortion_Test.cpp
Normal file
104
src/tests/CanvasPortion_Test.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
#include "BaseTestCase.h"
|
||||
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasFragment.h"
|
||||
|
||||
TEST(CanvasPortion, setSize)
|
||||
{
|
||||
CanvasPortion portion;
|
||||
|
||||
portion.setSize(150, 30);
|
||||
|
||||
EXPECT_EQ(150, portion.getWidth());
|
||||
EXPECT_EQ(30, portion.getHeight());
|
||||
}
|
||||
|
||||
TEST(CanvasPortion, pushFragment)
|
||||
{
|
||||
CanvasPortion portion;
|
||||
CanvasFragment pushed;
|
||||
const CanvasFragment *got;
|
||||
int count;
|
||||
|
||||
portion.setSize(50, 50);
|
||||
portion.pushFragment(10, 15, pushed);
|
||||
|
||||
count = portion.getFragmentCount(10, 14);
|
||||
ASSERT_EQ(0, count);
|
||||
got = portion.getFrontFragment(10, 14);
|
||||
ASSERT_FALSE(got);
|
||||
|
||||
count = portion.getFragmentCount(10, 15);
|
||||
ASSERT_EQ(1, count);
|
||||
got = portion.getFrontFragment(10, 15);
|
||||
ASSERT_TRUE(got);
|
||||
}
|
||||
|
||||
TEST(CanvasPortion, pushFragment_opaque)
|
||||
{
|
||||
CanvasPortion portion;
|
||||
CanvasFragment pushed;
|
||||
|
||||
portion.setSize(10, 10);
|
||||
|
||||
pushed = CanvasFragment(2.0, VECTOR_ZERO, 0);
|
||||
portion.pushFragment(2, 2, pushed);
|
||||
|
||||
ASSERT_EQ(1, portion.getFragmentCount(2, 2));
|
||||
EXPECT_DOUBLE_EQ(2.0, portion.getFrontFragment(2, 2)->getZ());
|
||||
|
||||
pushed = CanvasFragment(4.0, VECTOR_ZERO, 0);
|
||||
portion.pushFragment(2, 2, pushed);
|
||||
|
||||
ASSERT_EQ(1, portion.getFragmentCount(2, 2));
|
||||
EXPECT_DOUBLE_EQ(2.0, portion.getFrontFragment(2, 2)->getZ());
|
||||
|
||||
pushed = CanvasFragment(1.0, VECTOR_ZERO, 0);
|
||||
portion.pushFragment(2, 2, pushed);
|
||||
|
||||
ASSERT_EQ(1, portion.getFragmentCount(2, 2));
|
||||
EXPECT_DOUBLE_EQ(1.0, portion.getFrontFragment(2, 2)->getZ());
|
||||
}
|
||||
|
||||
TEST(CanvasPortion, pushFragment_transparent)
|
||||
{
|
||||
CanvasPortion portion;
|
||||
CanvasFragment pushed;
|
||||
|
||||
portion.setSize(10, 10);
|
||||
|
||||
pushed = CanvasFragment(4.0, VECTOR_ZERO, 0, false);
|
||||
portion.pushFragment(2, 2, pushed);
|
||||
|
||||
ASSERT_EQ(1, portion.getFragmentCount(2, 2));
|
||||
EXPECT_DOUBLE_EQ(4.0, portion.getFrontFragment(2, 2)->getZ());
|
||||
|
||||
pushed = CanvasFragment(3.0, VECTOR_ZERO, 0, true);
|
||||
portion.pushFragment(2, 2, pushed);
|
||||
|
||||
ASSERT_EQ(1, portion.getFragmentCount(2, 2));
|
||||
EXPECT_DOUBLE_EQ(3.0, portion.getFrontFragment(2, 2)->getZ());
|
||||
|
||||
pushed = CanvasFragment(2.0, VECTOR_ZERO, 0, false);
|
||||
portion.pushFragment(2, 2, pushed);
|
||||
|
||||
ASSERT_EQ(2, portion.getFragmentCount(2, 2));
|
||||
EXPECT_DOUBLE_EQ(2.0, portion.getFrontFragment(2, 2)->getZ());
|
||||
}
|
||||
|
||||
TEST(CanvasPortion, clear)
|
||||
{
|
||||
CanvasPortion portion;
|
||||
CanvasFragment fragment;
|
||||
|
||||
portion.setSize(10, 10);
|
||||
portion.pushFragment(5, 5, fragment);
|
||||
|
||||
EXPECT_EQ(0, portion.getFragmentCount(4, 5));
|
||||
EXPECT_EQ(1, portion.getFragmentCount(5, 5));
|
||||
|
||||
portion.clear();
|
||||
|
||||
EXPECT_EQ(0, portion.getFragmentCount(4, 5));
|
||||
EXPECT_EQ(0, portion.getFragmentCount(5, 5));
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "Canvas.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasPreview.h"
|
||||
|
||||
static void checkPortion(Canvas &canvas, int x, int y, int width, int height)
|
||||
{
|
||||
|
@ -21,8 +22,8 @@ TEST(Canvas, SizingAndCutting)
|
|||
canvas.setSize(200, 100);
|
||||
EXPECT_EQ(200, canvas.getWidth());
|
||||
EXPECT_EQ(100, canvas.getHeight());
|
||||
EXPECT_EQ(200, canvas.getPreviewWidth());
|
||||
EXPECT_EQ(100, canvas.getPreviewHeight());
|
||||
EXPECT_EQ(200, canvas.getPreview()->getWidth());
|
||||
EXPECT_EQ(100, canvas.getPreview()->getHeight());
|
||||
ASSERT_EQ(1, canvas.getHorizontalPortionCount());
|
||||
ASSERT_EQ(1, canvas.getVerticalPortionCount());
|
||||
checkPortion(canvas, 0, 0, 200, 100);
|
||||
|
@ -30,8 +31,8 @@ TEST(Canvas, SizingAndCutting)
|
|||
canvas.setSize(600, 501);
|
||||
EXPECT_EQ(600, canvas.getWidth());
|
||||
EXPECT_EQ(501, canvas.getHeight());
|
||||
EXPECT_EQ(600, canvas.getPreviewWidth());
|
||||
EXPECT_EQ(501, canvas.getPreviewHeight());
|
||||
EXPECT_EQ(600, canvas.getPreview()->getWidth());
|
||||
EXPECT_EQ(501, canvas.getPreview()->getHeight());
|
||||
ASSERT_EQ(2, canvas.getHorizontalPortionCount());
|
||||
ASSERT_EQ(2, canvas.getVerticalPortionCount());
|
||||
checkPortion(canvas, 0, 0, 300, 250);
|
||||
|
|
|
@ -20,7 +20,8 @@ SOURCES += main.cpp \
|
|||
FluidMediumManager_Test.cpp \
|
||||
VertexArray_Test.cpp \
|
||||
FractalNoise_Test.cpp \
|
||||
Canvas_Test.cpp
|
||||
Canvas_Test.cpp \
|
||||
CanvasPortion_Test.cpp
|
||||
|
||||
HEADERS += \
|
||||
BaseTestCase.h
|
||||
|
|
Loading…
Reference in a new issue