Skip to content

Conversation

@rudrabeniwal
Copy link
Collaborator

Results (Drive link)

Overview:

  • Animation Parameters and Mandelbrot parameters control:

    • Animation duration and frame rate
    • Initial and final zoom levels
    • Starting point and destination coordinates within the Mandelbrot set
    • Maximum iteration limit for determining set membership
  • Mandelbrot Set Calculation: calculateMandelbrot function that determines how many iterations it takes for a point to escape the set. This function:

    • Scales and translates pixel coordinates based on the current zoom level and focus point
    • Uses Cyfra's functional GSeq API to:
      • Generate the sequence starting with Z₀ = (0,0)
      • Apply the iteration formula Z_{n+1} = Z_n² + C
      • Terminate when |Z| >= 2 (proven escape threshold) or iteration limit reached
      • Count the number of iterations before escape
    def calculateMandelbrot(c: Vec2[Float32], globalTimePos: Float32): Int32 =
    // Calculate zoom factor based on animation time
    val zoom = BaseZoom + (TargetZoom - BaseZoom) * globalTimePos
    
    // Calculate focus point based on animation time
    val focusX = mix(InitialFocusX, MandelbrotCenterX, globalTimePos)
    val focusY = mix(InitialFocusY, MandelbrotCenterY, globalTimePos)
    
    // Scale coordinates based on zoom and focus
    val scaledC = vec2(
    (c.x - 0.3f) * 2.5f / zoom + focusX,
    (c.y - 0.5f) * 2.5f / zoom + focusY
    )
    
    // Calculate iteration count using Z = Z² + C
    GSeq
    .gen(vec2(0f, 0f), next = z => ((z.x * z.x) - (z.y * z.y), 2.0f * z.x * z.y) + scaledC)
    .limit(IterationLimit)
    .map(length)
    .takeWhile(_ < 2.0f)
    .count
  • Batch Processing: The animation is rendered in batches to efficiently manage memory:

    // Process in batches to manage memory
    for
    batchStart <- startFrame until totalFrames by BatchSize
    batchEnd = Math.min(batchStart + BatchSize, totalFrames)
    do
    // Batch rendering logic...

    For each batch:

    1. A temporary directory is created
    2. An animated function is defined for the specific time segment
    3. The function is rendered to PNG files using AnimatedFunctionRenderer
    4. Files are moved to the final output directory with sequential frame names
    5. Memory is explicitly freed with garbage collection between batches

Note

Calling System.gc() manually can cause unpredictable performance slowdowns. The JVM usually handles GC timing more efficiently on its own.

  • Animation Function: A GPU-compatible function using Cyfra's AnimatedFunction API:

    def createMandelbrotFunction(batchStartTime: Float32,
    batchDuration: Milliseconds,
    animationDurationMs: Float32): AnimatedFunction =
    // Define color mapping function
    def mandelbrotColor(uv: Vec2[Float32])(using instant: AnimationInstant): Vec4[Float32] = ...
    
    AnimatedFunction.fromCoord(mandelbrotColor, batchDuration)

    This creates a function that maps from:

    • 2D coordinates (uv) in the range [0,1]
    • Animation time
    • To RGBA color values
  • The implementation includes functionality to resume rendering if interrupted:

    def findLastRenderedFrame(directory: Path): Int = ...

    This allows long rendering jobs to be stopped and restarted without losing progress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant