Browse Source

Updated API of approximateSDF

Chlumsky 1 year ago
parent
commit
3af96cda22
2 changed files with 15 additions and 21 deletions
  1. 13 18
      core/approximate-sdf.cpp
  2. 2 3
      core/approximate-sdf.h

+ 13 - 18
core/approximate-sdf.cpp

@@ -9,7 +9,7 @@
 
 
 namespace msdfgen {
 namespace msdfgen {
 
 
-void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double outerRange, double innerRange) {
+void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const SDFTransformation &transformation) {
     struct Entry {
     struct Entry {
         float absDist;
         float absDist;
         int bitmapX, bitmapY;
         int bitmapX, bitmapY;
@@ -31,8 +31,9 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
     for (float *p = output.pixels, *end = output.pixels+output.width*output.height; p < end; ++p)
     for (float *p = output.pixels, *end = output.pixels+output.width*output.height; p < end; ++p)
         *p = -ESTSDF_MAX_DIST;
         *p = -ESTSDF_MAX_DIST;
 
 
-    Vector2 invScale = projection.unprojectVector(Vector2(1));
-    float dLimit = float(max(outerRange, innerRange));
+    Vector2 invScale = transformation.unprojectVector(Vector2(1));
+    DistanceMapping invDistanceMapping = transformation.distanceMapping.inverse();
+    float dLimit = float(max(fabs(invDistanceMapping(0)), fabs(invDistanceMapping(1))));
     std::priority_queue<Entry> queue;
     std::priority_queue<Entry> queue;
     double x[3], y[3];
     double x[3], y[3];
     int dx[3], dy[3];
     int dx[3], dy[3];
@@ -40,13 +41,13 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
     // Horizontal scanlines
     // Horizontal scanlines
     for (int bitmapY = 0; bitmapY < output.height; ++bitmapY) {
     for (int bitmapY = 0; bitmapY < output.height; ++bitmapY) {
         float *row = firstRow+bitmapY*stride;
         float *row = firstRow+bitmapY*stride;
-        double y = projection.unprojectY(bitmapY+.5);
+        double y = transformation.unprojectY(bitmapY+.5);
         entry.bitmapY = bitmapY;
         entry.bitmapY = bitmapY;
         for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
         for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
             for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
             for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                 int n = (*edge)->horizontalScanlineIntersections(x, dy, y);
                 int n = (*edge)->horizontalScanlineIntersections(x, dy, y);
                 for (int i = 0; i < n; ++i) {
                 for (int i = 0; i < n; ++i) {
-                    double bitmapX = projection.projectX(x[i]);
+                    double bitmapX = transformation.projectX(x[i]);
                     double bitmapX0 = floor(bitmapX-.5)+.5;
                     double bitmapX0 = floor(bitmapX-.5)+.5;
                     double bitmapX1 = bitmapX0+1;
                     double bitmapX1 = bitmapX0+1;
                     if (bitmapX1 > 0 && bitmapX0 < output.width) {
                     if (bitmapX1 > 0 && bitmapX0 < output.width) {
@@ -109,13 +110,13 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
 
 
     // Vertical scanlines
     // Vertical scanlines
     for (int bitmapX = 0; bitmapX < output.width; ++bitmapX) {
     for (int bitmapX = 0; bitmapX < output.width; ++bitmapX) {
-        double x = projection.unprojectX(bitmapX+.5);
+        double x = transformation.unprojectX(bitmapX+.5);
         entry.bitmapX = bitmapX;
         entry.bitmapX = bitmapX;
         for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
         for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
             for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
             for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                 int n = (*edge)->verticalScanlineIntersections(y, dx, x);
                 int n = (*edge)->verticalScanlineIntersections(y, dx, x);
                 for (int i = 0; i < n; ++i) {
                 for (int i = 0; i < n; ++i) {
-                    double bitmapY = projection.projectY(y[i]);
+                    double bitmapY = transformation.projectY(y[i]);
                     double bitmapY0 = floor(bitmapY-.5)+.5;
                     double bitmapY0 = floor(bitmapY-.5)+.5;
                     double bitmapY1 = bitmapY0+1;
                     double bitmapY1 = bitmapY0+1;
                     if (bitmapY0 > 0 && bitmapY1 < output.height) {
                     if (bitmapY0 > 0 && bitmapY1 < output.height) {
@@ -165,7 +166,7 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
         if (newEntry.bitmapX >= 0) {
         if (newEntry.bitmapX >= 0) {
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
-                Point2 shapeCoord = projection.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
+                Point2 shapeCoord = transformation.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 sd = float(sign(sd))*newEntry.absDist;
                 sd = float(sign(sd))*newEntry.absDist;
                 if (newEntry.absDist < dLimit)
                 if (newEntry.absDist < dLimit)
@@ -176,7 +177,7 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
         if (newEntry.bitmapX < output.width) {
         if (newEntry.bitmapX < output.width) {
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
-                Point2 shapeCoord = projection.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
+                Point2 shapeCoord = transformation.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 sd = float(sign(sd))*newEntry.absDist;
                 sd = float(sign(sd))*newEntry.absDist;
                 if (newEntry.absDist < dLimit)
                 if (newEntry.absDist < dLimit)
@@ -188,7 +189,7 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
         if (newEntry.bitmapY >= 0) {
         if (newEntry.bitmapY >= 0) {
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
-                Point2 shapeCoord = projection.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
+                Point2 shapeCoord = transformation.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 sd = float(sign(sd))*newEntry.absDist;
                 sd = float(sign(sd))*newEntry.absDist;
                 if (newEntry.absDist < dLimit)
                 if (newEntry.absDist < dLimit)
@@ -199,7 +200,7 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
         if (newEntry.bitmapY < output.height) {
         if (newEntry.bitmapY < output.height) {
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             float &sd = ESTSDF_PIXEL_AT(newEntry.bitmapX, newEntry.bitmapY);
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
             if (fabsf(sd) == ESTSDF_MAX_DIST) {
-                Point2 shapeCoord = projection.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
+                Point2 shapeCoord = transformation.unproject(Point2(newEntry.bitmapX+.5, newEntry.bitmapY+.5));
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 newEntry.absDist = float((shapeCoord-entry.nearPoint).length());
                 sd = float(sign(sd))*newEntry.absDist;
                 sd = float(sign(sd))*newEntry.absDist;
                 if (newEntry.absDist < dLimit)
                 if (newEntry.absDist < dLimit)
@@ -208,14 +209,8 @@ void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const
         }
         }
     }
     }
 
 
-    float rangeFactor = 1.f/float(outerRange+innerRange);
-    float zeroBias = rangeFactor*float(outerRange);
     for (float *p = output.pixels, *end = output.pixels+output.width*output.height; p < end; ++p)
     for (float *p = output.pixels, *end = output.pixels+output.width*output.height; p < end; ++p)
-        *p = rangeFactor**p+zeroBias;
-}
-
-void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range) {
-    approximateSDF(output, shape, projection, .5*range, .5*range);
+        *p = transformation.distanceMapping(*p);
 }
 }
 
 
 }
 }

+ 2 - 3
core/approximate-sdf.h

@@ -1,14 +1,13 @@
 
 
 #pragma once
 #pragma once
 
 
-#include "Projection.h"
+#include "SDFTransformation.h"
 #include "Shape.h"
 #include "Shape.h"
 #include "BitmapRef.hpp"
 #include "BitmapRef.hpp"
 
 
 namespace msdfgen {
 namespace msdfgen {
 
 
 // Fast SDF approximation (out of range values not computed)
 // Fast SDF approximation (out of range values not computed)
-void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double outerRange, double innerRange);
-void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range);
+void approximateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const SDFTransformation &transformation);
 
 
 }
 }