1
0
Nicolas Winkler 5 лет назад
Родитель
Сommit
1c97912cb5

+ 2 - 1
libalmond/include/MandelVideoGenerator.h

@@ -50,7 +50,8 @@ private:
     void callCallbacks(const MandelVideoProgressInfo& evi);
     Bitmap<RGBColor> overlay(const Bitmap<RGBColor>& outer,
                              const Bitmap<RGBColor>& inner,
-                             double scale);
+                             long bw, long bh,
+                             double scale, double oversizeFactor);
 };
 
 #endif // MANDELVIDEOGENERATOR_H

+ 63 - 20
libalmond/src/MandelVideoGenerator.cpp

@@ -19,10 +19,7 @@ void MandelVideoGenerator::generate(void)
 {
     mnd::MandelContext ctxt = mnd::initializeContext();
     mnd::MandelGenerator& gen = ctxt.getDefaultGenerator();
-    mnd::MandelInfo mi;
-    mi.bWidth = evi.width * 2;
-    mi.bHeight = evi.height * 2;
-    mi.maxIter = evi.maxIterations;
+
 
     VideoStream vs(evi.width, evi.height, evi.path, evi.bitrate, evi.fps, evi.preset.c_str());
 
@@ -31,20 +28,38 @@ void MandelVideoGenerator::generate(void)
     mnd::Real w = evi.start.width;
     mnd::Real h = evi.start.height;
 
-    mnd::Real bigW = 10000000000000000.0;
+    mnd::Real bigW = mnd::Real("1e+300");
     double bigFac = 1.0;
     Bitmap<RGBColor> big;
     Bitmap<RGBColor> small;
 
     int64_t frameCounter = 0;
+
+    const float oversizeFactor = 2;
+    const float sqrFactor = sqrt(oversizeFactor);
+    //const mnd::Real invsqrt2 = mnd::Real(1.0) / mnd::sqrt(mnd::Real(2));
+
+    mnd::MandelInfo mi;
+    mi.bWidth = evi.width * oversizeFactor;
+    mi.bHeight = evi.height * oversizeFactor;
+    mi.maxIter = evi.maxIterations;
+
+
     while(w > evi.end.width || h > evi.end.height) {
-        mi.view = mnd::MandelViewport{ x - w/2, y - h/2, w, h };
 
-        if (bigW > 2 * w) {
-            Bitmap<float> raw{ evi.width * 2, evi.height * 2 };
-            gen.generate(mi, raw.pixels.get());
+        if (bigW > sqrt(oversizeFactor) * w) {
+            mi.view = mnd::MandelViewport{ x - w/2, y - h/2, w, h };
+            //Bitmap<float> raw{ evi.width * oversizeFactor, evi.height * oversizeFactor };
+            Bitmap<float> rawSmall{ evi.width * oversizeFactor, evi.height * oversizeFactor };
+            //gen.generate(mi, raw.pixels.get());
+            mi.view.zoomCenter(1.0f / sqrt(oversizeFactor));
+            gen.generate(mi, rawSmall.pixels.get());
             //auto before = std::chrono::high_resolution_clock::now();
-            big = raw.map<RGBColor>([&mi, this] (float i) {
+            /*big = raw.map<RGBColor>([&mi, this] (float i) {
+                return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : evi.gradient.get(i);
+            });*/
+            big = std::move(small);
+            small = raw.map<RGBColor>([&mi, this] (float i) {
                 return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : evi.gradient.get(i);
             });
             /*mi.view.zoomCenter(0.5);
@@ -56,7 +71,7 @@ void MandelVideoGenerator::generate(void)
             bigFac = 1.0;
         }
 
-        vs.addFrame(overlay(big, small, bigFac));
+        vs.addFrame(overlay(big, small, evi.width, evi.height, bigFac, sqrt(oversizeFactor)));
         frameCounter++;
         MandelVideoProgressInfo mvpi{ frameCounter };
         callCallbacks(mvpi);
@@ -75,6 +90,21 @@ void MandelVideoGenerator::callCallbacks(const MandelVideoProgressInfo& evi)
     }
 }
 
+inline RGBColor lerpColors(const RGBColor& a, const RGBColor& b, double lerp)
+{
+    auto mklin = [] (double x) {
+        return x;
+    };
+    auto unlin = [] (double x) {
+        return x;
+    };
+
+    return RGBColor{
+        a.r * lerp + b.r * (1 - lerp),
+        a.g * lerp + b.g * (1 - lerp),
+        a.b * lerp + b.b * (1 - lerp)
+    };
+}
 
 inline RGBColor biliniear(const Bitmap<RGBColor>& img, double x, double y)
 {
@@ -134,23 +164,36 @@ inline RGBColor nearest(const Bitmap<RGBColor>& img, double x, double y)
 
 
 Bitmap<RGBColor> MandelVideoGenerator::overlay(const Bitmap<RGBColor>& outer,
-                         const Bitmap<RGBColor>& inner, double scale)
+                         const Bitmap<RGBColor>& inner, long bw, long bh,
+                         double scale, double oversizeFactor)
 {
     printf("%lf\n", scale);
-    Bitmap<RGBColor> ret{ outer.width / 2, outer.height / 2 };
-    double newW = outer.width * scale * 2;
-    double newH = outer.height * scale * 2;
-    double newX = outer.width * (1 - scale) / 2;
-    double newY = outer.height * (1 - scale) / 2;
+    Bitmap<RGBColor> ret{ bw, bh };
+
+    double outerLeft = outer.width * (1 - scale) / 2;
+    double outerTop = outer.height * (1 - scale) / 2;
+    double outerWidth = outer.width * scale;
+    double outerHeight = outer.height * scale;
+
+    double innerLeft = outer.width * (1 - scale * oversizeFactor) / 2;
+    double innerTop = outer.height * (1 - scale * oversizeFactor) / 2;
+    double innerWidth = outer.width * scale * oversizeFactor;
+    double innerHeight = outer.height * scale * oversizeFactor;
 
     auto before = std::chrono::high_resolution_clock::now();
 #pragma omp parallel for schedule(static, 1)
     for (int i = 0; i < ret.height; i++) {
         for (int j = 0; j < ret.width; j++) {
-            double newJ = newX + j * newW / outer.width;
-            double newI = newY + i * newH / outer.height;
+            double newJ = outerLeft + outerWidth * j / ret.width;
+            double newI = outerTop + outerHeight * i / ret.height;
             RGBColor a = biliniear(outer, newJ, newI);
-            ret.get(j, i) = a;
+
+            double innJ = innerLeft + innerWidth * j / ret.width;
+            double innI = innerTop + innerHeight * i / ret.height;
+            RGBColor b = biliniear(inner, innJ, innI);
+            double lerpVal = ::log(1.0 / scale) / ::log(oversizeFactor) / 2;
+            RGBColor lerped = lerpColors(a, b, lerpVal);
+            ret.get(j, i) = b;
         }
     }
     auto after = std::chrono::high_resolution_clock::now();

+ 2 - 0
libmandel/include/MandelUtil.h

@@ -39,6 +39,7 @@ struct mnd::MandelViewport
      * \brief zoom in around the center by a factor specified
      */
     void zoomCenter(float scale);
+    void zoomCenter(const Real& scale);
 
     /*!
      * \brief zoom in around a specific point
@@ -46,6 +47,7 @@ struct mnd::MandelViewport
      * \param y value between 0.0f and 1.0f
      */
     void zoom(float scale, float x, float y);
+    void zoom(const Real& scale, const Real& x, const Real& y);
 
     /*!
      * \brief returns a viewport where the whole mandelbrot set can be observed

+ 7 - 0
libmandel/include/Types.h

@@ -39,6 +39,7 @@ namespace mnd
             boost::multiprecision::et_off>;*/
 #   endif
     inline Float128 abs(const Float128& x) { return boost::multiprecision::abs(x); }
+    inline Float128 sqrt(const Float128& x) { return boost::multiprecision::sqrt(x); }
     inline Float128 floor(const Float128& x) { return boost::multiprecision::floor(x); }
     inline Float128 log(const Float128& x) { return boost::multiprecision::log(x); }
     inline Float128 log2(const Float128& x) { return boost::multiprecision::log2(x); }
@@ -51,6 +52,7 @@ namespace mnd
 
     //using Float256 = long double;
     inline Float256 abs(const Float256& x) { return boost::multiprecision::abs(x); }
+    inline Float256 sqrt(const Float256& x) { return boost::multiprecision::sqrt(x); }
     inline Float256 floor(const Float256& x) { return boost::multiprecision::floor(x); }
     inline Float256 log(const Float256& x) { return boost::multiprecision::log(x); }
     inline Float256 log2(const Float256& x) { return boost::multiprecision::log2(x); }
@@ -62,6 +64,7 @@ namespace mnd
             boost::multiprecision::et_off>;
 
     inline Float512 abs(const Float512& x) { return boost::multiprecision::abs(x); }
+    inline Float512 sqrt(const Float512& x) { return boost::multiprecision::sqrt(x); }
     inline Float512 floor(const Float512& x) { return boost::multiprecision::floor(x); }
     inline Float512 log(const Float512& x) { return boost::multiprecision::log(x); }
     inline Float512 log2(const Float512& x) { return boost::multiprecision::log2(x); }
@@ -83,6 +86,7 @@ namespace mnd
     using QuadDouble = qd_real;
 
     inline DoubleDouble abs(const DoubleDouble& x) { return ::abs(x); }
+    inline DoubleDouble sqrt(const DoubleDouble& x) { return ::sqrt(x); }
     inline DoubleDouble floor(const DoubleDouble& x) { return ::floor(x); }
     inline DoubleDouble log(const DoubleDouble& x) { return ::log(x); }
     inline DoubleDouble log2(const DoubleDouble& x) { return ::log(x) / ::log(DoubleDouble(2.0)); }
@@ -90,6 +94,7 @@ namespace mnd
 
 
     inline QuadDouble abs(const QuadDouble& x) { return ::abs(x); }
+    inline QuadDouble sqrt(const QuadDouble& x) { return ::sqrt(x); }
     inline QuadDouble floor(const QuadDouble& x) { return ::floor(x); }
     inline QuadDouble log(const QuadDouble& x) { return ::log(x); }
     inline QuadDouble log2(const QuadDouble& x) { return ::log(x) / ::log(QuadDouble(2.0)); }
@@ -97,6 +102,8 @@ namespace mnd
 
     inline double abs(double x) { return ::abs(x); }
     inline float abs(float x) { return ::abs(x); }
+    inline double sqrt(double x) { return ::sqrt(x); }
+    inline float sqrt(float x) { return ::sqrtf(x); }
     inline double floor(double x) { return ::floor(x); }
     inline float floor(float x) { return ::floorf(x); }
     inline double log(double x) { return ::log(x); }

+ 20 - 0
libmandel/src/MandelUtil.cpp

@@ -37,6 +37,16 @@ void MandelViewport::zoomCenter(float scale)
 }
 
 
+void MandelViewport::zoomCenter(const mnd::Real& scale)
+{
+    /*x += width * (1 - scale) / 2;
+    y += height * (1 - scale) / 2;
+    width *= scale;
+    height *= scale;*/
+    zoom(scale, mnd::Real(0.5), mnd::Real(0.5));
+}
+
+
 void MandelViewport::zoom(float scale, float xz, float yz)
 {
     mnd::Real scaleR = 1.0f - scale;
@@ -47,6 +57,16 @@ void MandelViewport::zoom(float scale, float xz, float yz)
 }
 
 
+void MandelViewport::zoom(const mnd::Real& scale, const mnd::Real& xz, const mnd::Real& yz)
+{
+    mnd::Real scaleR = 1.0f - scale;
+    this->x += width * scaleR * mnd::Real(xz);
+    this->y += height * scaleR * mnd::Real(yz);
+    width *= scale;
+    height *= scale;
+}
+
+
 MandelViewport MandelViewport::standardView(void)
 {
     return MandelViewport{

+ 1 - 1
mandelvid/src/main.cpp

@@ -27,7 +27,7 @@ int main() {
     evi.zoomSpeed = 1.3;
     evi.path = "video.avi";
     evi.bitrate = 1500;
-    evi.preset = "slow";
+    evi.preset = "veryfast";
 
     evi.start.adjustAspectRatio(evi.width, evi.height);