Update the distance image genereration

This commit is contained in:
Edouard DUPIN 2012-09-14 17:20:42 +02:00
parent b3f1a97a28
commit 4c16ddcbd7
2 changed files with 172 additions and 49 deletions

View File

@ -258,40 +258,41 @@ void draw::Image::Disc(Vector2D<float> pos, float radius, float angleStart, floa
{
}
#ifdef BASIC_GRADIENT
void GenerateSDF( Grid &g )
void Grid::GenerateSDF()
{
// Pass 0
Vector2D<int32_t> tmpPos;
for (tmpPos.y=1 ; tmpPos.y<g.m_size.y-1 ; tmpPos.y++) {
for (tmpPos.x=1 ; tmpPos.x<g.m_size.x-1 ; tmpPos.x++) {
Vector2D<int32_t> p = g.Get(tmpPos);
g.Compare(p, tmpPos, -1, 0 );
g.Compare(p, tmpPos, 0, -1 );
g.Compare(p, tmpPos, -1, -1 );
g.Compare(p, tmpPos, 1, -1 );
g.Set(tmpPos, p);
for (tmpPos.y=1 ; tmpPos.y<m_size.y-1 ; tmpPos.y++) {
for (tmpPos.x=1 ; tmpPos.x<m_size.x-1 ; tmpPos.x++) {
Vector2D<int32_t> p = Get(tmpPos);
Compare(p, tmpPos, -1, 0 );
Compare(p, tmpPos, 0, -1 );
Compare(p, tmpPos, -1, -1 );
Compare(p, tmpPos, 1, -1 );
Set(tmpPos, p);
}
for (tmpPos.x=g.m_size.x-2 ; tmpPos.x>0 ; tmpPos.x--) {
Vector2D<int32_t> p = g.Get(tmpPos);
g.Compare(p, tmpPos, 1, 0 );
g.Set(tmpPos, p );
for (tmpPos.x=m_size.x-2 ; tmpPos.x>0 ; tmpPos.x--) {
Vector2D<int32_t> p = Get(tmpPos);
Compare(p, tmpPos, 1, 0 );
Set(tmpPos, p );
}
}
// Pass 1
for (tmpPos.y=g.m_size.y-2 ; tmpPos.y>0 ; tmpPos.y--) {
for (tmpPos.x=g.m_size.x-2 ; tmpPos.x>0 ; tmpPos.x--) {
Vector2D<int32_t> p = g.Get(tmpPos);
g.Compare(p, tmpPos, 1, 0 );
g.Compare(p, tmpPos, 0, 1 );
g.Compare(p, tmpPos, -1, 1 );
g.Compare(p, tmpPos, 1, 1 );
g.Set(tmpPos, p);
for (tmpPos.y=m_size.y-2 ; tmpPos.y>0 ; tmpPos.y--) {
for (tmpPos.x=m_size.x-2 ; tmpPos.x>1 ; tmpPos.x--) {
Vector2D<int32_t> p = Get(tmpPos);
Compare(p, tmpPos, 1, 0 );
Compare(p, tmpPos, 0, 1 );
Compare(p, tmpPos, -1, 1 );
Compare(p, tmpPos, 1, 1 );
Set(tmpPos, p);
}
for (tmpPos.x=1 ; tmpPos.x<g.m_size.x-1 ; tmpPos.x++) {
Vector2D<int32_t> p = g.Get(tmpPos);
g.Compare(p, tmpPos, -1, 0 );
g.Set(tmpPos, p);
for (tmpPos.x=1 ; tmpPos.x<m_size.x-1 ; tmpPos.x++) {
Vector2D<int32_t> p = Get(tmpPos);
Compare(p, tmpPos, -1, 0 );
Set(tmpPos, p);
}
}
}
@ -302,8 +303,69 @@ void draw::Image::DistanceField(void)
{
DistanceField(Vector2D<int32_t>(0,0), m_size);
}
void draw::Image::DistanceField(Vector2D<int32_t> pos, Vector2D<int32_t> size)
#endif
#define META_DIST (8)
void draw::Image::DistanceField(Vector2D<int32_t> pos, Vector2D<int32_t> size, int32_t upscaler, int32_t startPos)
{
#ifndef BASIC_GRADIENT
float maxVal = 1/(1000.0*sqrt(META_DIST*META_DIST+META_DIST*META_DIST));
Vector2D<int32_t> tmpPos;
// generate distance system ... matrix ...
Grid grid2(Vector2D<int32_t>(META_DIST*2,META_DIST*2));
for(tmpPos.y=0 ; tmpPos.y<META_DIST*2 ; tmpPos.y++ ) {
for(tmpPos.x=0 ; tmpPos.x<META_DIST*2 ; tmpPos.x++ ) {
int32_t val = 1000.0*sqrt((tmpPos.x-META_DIST)*(tmpPos.x-META_DIST) + (tmpPos.y-META_DIST)*(tmpPos.y-META_DIST));
grid2.Set(tmpPos, val);
}
}
Grid grid1(size);
grid1.SetErrorVal(0);
for(tmpPos.y=0 ; tmpPos.y<size.y ; tmpPos.y++ ) {
for(tmpPos.x=0 ; tmpPos.x<size.x ; tmpPos.x++ ) {
draw::Color tmpColor = Get(pos+tmpPos);
// Points inside get marked with a x/y of zero.
// Points outside get marked with an infinitely large distance.
if (tmpColor.a<=0x7F) {
grid1.SetInide(tmpPos);
} else {
grid1.SetOutside(tmpPos);
}
}
}
for(tmpPos.y=startPos ; tmpPos.y<size.y ; tmpPos.y+=upscaler ) {
for(tmpPos.x=startPos ; tmpPos.x<size.x ; tmpPos.x+=upscaler ) {
int32_t insideOrOutsideCurrentPixel = grid1.Get(tmpPos);
// when out no distance find ...
grid1.SetErrorVal(insideOrOutsideCurrentPixel);
Vector2D<int32_t> tmpPos2;
int32_t newDist = 50000000;
for(tmpPos2.y=-META_DIST ; tmpPos2.y<META_DIST ; tmpPos2.y++ ) {
for(tmpPos2.x=-META_DIST ; tmpPos2.x<META_DIST ; tmpPos2.x++ ) {
// we have an opposite factor ...
if (insideOrOutsideCurrentPixel != grid1.Get(tmpPos+tmpPos2)) {
// get new distance
int32_t tmpDist = grid2.Get(tmpPos2 + Vector2D<int32_t>(META_DIST,META_DIST));
if (newDist > tmpDist) {
newDist = tmpDist;
}
}
}
}
// set the finded distance :
draw::Color tmpColor = Get(pos+tmpPos);
float tmpValue = ((1.0-((float)newDist * maxVal)) * 0.5) * 128.0;
if (tmpColor.a<=0x7F) {
tmpColor.a = etk_avg(0, tmpValue, 255);
} else {
tmpColor.a = etk_avg(0, 255-tmpValue, 255);
}
Set(pos+tmpPos, tmpColor);
}
}
#else
Grid grid1(size);
Grid grid2(size);
grid1.SetOutsideVal(500000);
@ -326,13 +388,12 @@ void draw::Image::DistanceField(Vector2D<int32_t> pos, Vector2D<int32_t> size)
}
}
}
// Generate the SDF:
GenerateSDF( grid1 );
GenerateSDF( grid2 );
grid1.GenerateSDF();
grid2.GenerateSDF();
for(tmpPos.y=0 ; tmpPos.y<size.y ; tmpPos.y++ ) {
for(tmpPos.x=0 ; tmpPos.x<size.x ; tmpPos.x++ ) {
for(tmpPos.y=startPos ; tmpPos.y<size.y ; tmpPos.y+=upscaler ) {
for(tmpPos.x=startPos ; tmpPos.x<size.x ; tmpPos.x+=upscaler ) {
Vector2D<int32_t> elem1 = grid1.Get(tmpPos);
Vector2D<int32_t> elem2 = grid2.Get(tmpPos);
// Calculate the actual distance from the x/y
@ -354,5 +415,6 @@ void draw::Image::DistanceField(Vector2D<int32_t> pos, Vector2D<int32_t> size)
Set(pos+tmpPos, tmpColor);
}
}
#endif
}

View File

@ -42,8 +42,70 @@
#include <agg/agg_color_rgba.h>
#include <agg/agg_pixfmt_rgba.h>
#define BASIC_GRADIENT
#ifndef BASIC_GRADIENT
class Grid
{
public:
Vector2D<int32_t> m_size;
etk::Vector<int32_t > m_data;
int32_t m_outsideVal;
int32_t m_errorVal;
Grid(Vector2D<int32_t> size)
{
m_size = size;
m_outsideVal = 20;
m_errorVal = 0;
// basic element :
int32_t tmpPoint = 0;
// preallocate data with a basic bg elements :
m_data.ReSize(m_size.x*m_size.y, tmpPoint);
};
~Grid(void) { };
void SetOutsideVal(int32_t newVal)
{
m_outsideVal = newVal;
}
void SetErrorVal(int32_t newVal)
{
m_errorVal = newVal;
}
void SetInide(Vector2D<int32_t> pos)
{
if( pos.x>=0 && pos.x<m_size.x
&& pos.y>=0 && pos.y<m_size.y) {
m_data[pos.x+pos.y*m_size.x]=0;
}
};
void SetOutside(Vector2D<int32_t> pos)
{
if( pos.x>=0 && pos.x<m_size.x
&& pos.y>=0 && pos.y<m_size.y) {
m_data[pos.x+pos.y*m_size.x]=m_outsideVal;
}
};
int32_t Get(Vector2D<int32_t> pos)
{
;
if( pos.x>0 && pos.x<m_size.x
&& pos.y>0 && pos.y<m_size.y) {
return m_data[pos.x+pos.y*m_size.x];
}
return m_errorVal;
};
void Set(Vector2D<int32_t> pos, int32_t val)
{
if( pos.x>0 && pos.x<m_size.x
&& pos.y>0 && pos.y<m_size.y) {
m_data[pos.x+pos.y*m_size.x] = val;
}
};
};
#else
class Grid
{
public:
@ -72,37 +134,36 @@ class Grid
}
void SetInide(Vector2D<int32_t> pos)
{
if( pos.x>=0 && pos.x<m_size.x
&& pos.y>=0 && pos.y<m_size.y) {
//if( pos.x>=0 && pos.x<m_size.x
// && pos.y>=0 && pos.y<m_size.y) {
m_data[pos.x+pos.y*m_size.x].x=0;
m_data[pos.x+pos.y*m_size.x].y=0;
}
//}
};
void SetOutside(Vector2D<int32_t> pos)
{
if( pos.x>=0 && pos.x<m_size.x
&& pos.y>=0 && pos.y<m_size.y) {
//if( pos.x>=0 && pos.x<m_size.x
// && pos.y>=0 && pos.y<m_size.y) {
m_data[pos.x+pos.y*m_size.x].x=m_outsideVal;
m_data[pos.x+pos.y*m_size.x].y=m_outsideVal;
}
//}
};
Vector2D<int32_t> Get(Vector2D<int32_t> pos)
{
;
if( pos.x>0 && pos.x<m_size.x
&& pos.y>0 && pos.y<m_size.y) {
//if( pos.x>0 && pos.x<m_size.x
// && pos.y>0 && pos.y<m_size.y) {
return m_data[pos.x+pos.y*m_size.x];
}
return Vector2D<int32_t>(m_errorVal,m_errorVal);
//}
//return Vector2D<int32_t>(m_errorVal,m_errorVal);
};
void Set(Vector2D<int32_t> pos, Vector2D<int32_t> val)
{
if( pos.x>0 && pos.x<m_size.x
&& pos.y>0 && pos.y<m_size.y) {
//if( pos.x>0 && pos.x<m_size.x
// && pos.y>0 && pos.y<m_size.y) {
m_data[pos.x+pos.y*m_size.x] = val;
}
//}
};
void Compare(Vector2D<int32_t> &p, Vector2D<int32_t> pos, int32_t offsetx, int32_t offsety )
@ -112,13 +173,13 @@ class Grid
Vector2D<int32_t> other = Get(pos);
other.x += offsetx;
other.y += offsety;
if (other.QuadDist() < p.QuadDist()) {
p = other;
}
};
void GenerateSDF(void);
};
#endif
namespace draw
@ -243,7 +304,7 @@ namespace draw
void Disc(Vector2D<float> pos, float radius, float angleStart=0, float angleStop=2*M_PI);
// generate the distant field from the alpha value of the Image
void DistanceField(void);
void DistanceField(Vector2D<int32_t> pos, Vector2D<int32_t> size);
void DistanceField(Vector2D<int32_t> pos, Vector2D<int32_t> size, int32_t upscaler=1, int32_t startPos=0);
void SaveFile(const char * file) {};
private: