From bfba3999b5cee49bd9a556f51170193849228a46 Mon Sep 17 00:00:00 2001 From: Edouard Dupin Date: Thu, 6 Sep 2012 02:50:38 +0200 Subject: [PATCH] add distance field calculation for the Image draw absraction system --- draw/Image.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ draw/Image.h | 79 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/draw/Image.cpp b/draw/Image.cpp index 3d40c2d..14b99d9 100644 --- a/draw/Image.cpp +++ b/draw/Image.cpp @@ -259,3 +259,98 @@ void draw::Image::Disc(Vector2D pos, float radius, float angleStart, floa } +void GenerateSDF( Grid &g ) +{ + // Pass 0 + Vector2D tmpPos; + for (tmpPos.y=1 ; tmpPos.y 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.x=g.m_size.x-2 ; tmpPos.x>0 ; tmpPos.x--) { + Vector2D p = g.Get(tmpPos); + g.Compare(p, tmpPos, 1, 0 ); + g.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 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.x=1 ; tmpPos.x p = g.Get(tmpPos); + g.Compare(p, tmpPos, -1, 0 ); + g.Set(tmpPos, p); + } + } +} + +// see : http://www.codersnotes.com/notes/signed-distance-fields + +void draw::Image::DistanceField(void) +{ + DistanceField(Vector2D(0,0), m_size); +} +void draw::Image::DistanceField(Vector2D pos, Vector2D size) +{ + Grid grid1(size); + Grid grid2(size); + grid1.SetOutsideVal(50); + grid2.SetOutsideVal(50); + + Vector2D tmpPos; + for(tmpPos.y=0 ; tmpPos.y elem1 = grid1.Get(tmpPos); + Vector2D elem2 = grid2.Get(tmpPos); + // Calculate the actual distance from the x/y + float dist1 = sqrt( (double)elem1.QuadDist() ); + float dist2 = sqrt( (double)elem2.QuadDist() ); + float dist = dist1 - dist2; + /* + if (tmpPos.y < 32) { + if (tmpPos.x < 32) { + DRAW_DEBUG( "generate Distance : " << dist1 << "," << dist2 << " ==> " << (dist*3 + 128)); + } else if (tmpPos.x == 32) { + DRAW_DEBUG( " ---" ); + } + } + */ + draw::Color tmpColor = Get(pos+tmpPos); + // Clamp and scale it, just for display purposes. + tmpColor.a = etk_avg(0, (dist*3 + 128), 255); + Set(pos+tmpPos, tmpColor); + } + } +} + diff --git a/draw/Image.h b/draw/Image.h index a5768d8..9cf0276 100644 --- a/draw/Image.h +++ b/draw/Image.h @@ -42,6 +42,79 @@ #include #include + + +class Grid +{ + public: + Vector2D m_size; + etk::Vector > m_data; + int32_t m_outsideVal; + Grid(Vector2D size) + { + m_size = size; + m_outsideVal = 20; + // basic element : + Vector2D tmpPoint(0,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 SetInide(Vector2D pos) + { + if( pos.x>=0 && pos.x=0 && pos.y pos) + { + if( pos.x>=0 && pos.x=0 && pos.y Get(Vector2D pos) + { + ; + if( pos.x>0 && pos.x0 && pos.y(0,0); + }; + + void Set(Vector2D pos, Vector2D val) + { + if( pos.x>0 && pos.x0 && pos.y &p, Vector2D pos, int32_t offsetx, int32_t offsety ) + { + pos.x += offsetx; + pos.y += offsety; + Vector2D other = Get(pos); + other.x += offsetx; + other.y += offsety; + + if (other.QuadDist() < p.QuadDist()) { + p = other; + } + }; +}; + + + namespace draw { @@ -162,6 +235,12 @@ namespace draw void Rectangle(Vector2D pos, Vector2D size); void Circle(Vector2D pos, float radius, float angleStart=0, float angleStop=2*M_PI); void Disc(Vector2D 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 pos, Vector2D size); + private: + + }; };