mirror of
https://github.com/bspeice/speice.io
synced 2025-03-11 17:21:29 -04:00
90 lines
3.6 KiB
Plaintext
90 lines
3.6 KiB
Plaintext
---
|
|
slug: 2025/03/playing-with-fire-camera
|
|
title: "Playing with fire: The camera"
|
|
date: 2025-03-07 12:00:00
|
|
authors: [bspeice]
|
|
tags: []
|
|
---
|
|
|
|
Something that bugged me while writing the first three articles on fractal flames were the constraints on
|
|
output images. At the time, I had worked out how to render fractal flames by studying
|
|
the source code of [Apophysis](https://sourceforge.net/projects/apophysis/)
|
|
and [flam3](https://github.com/scottdraves/flam3). That was just enough to define a basic camera for displaying
|
|
in a browser.
|
|
|
|
Having spent more time with fractal flames and computer graphics, it's time to implement
|
|
some missing features.
|
|
|
|
<!-- truncate -->
|
|
|
|
## Restrictions
|
|
|
|
To review, the restrictions we've had so far:
|
|
|
|
> ...we need to convert from fractal flame coordinates to pixel coordinates.
|
|
> To simplify things, we'll assume that we're _plotting a square image_ with range $[0,1]$ for both x and y
|
|
>
|
|
> -- [The fractal flame algorithm](/2024/11/playing-with-fire)
|
|
|
|
There are a couple problems here:
|
|
|
|
First, the assumption that fractals get displayed in a square image. Ignoring aspect ratios simplifies
|
|
the render process, but we usually don't want square images. As a workaround, you could render
|
|
a large square image and crop it to fit an aspect ratio, but it's better to render the desired
|
|
image size to start with.
|
|
|
|
Second, the assumption that fractals use the range $[0, 1]$. My statement above is an over-simplification;
|
|
for Sierpinski's Gasket, the solution set is indeed defined on $[0, 1]$, but all other images in the series
|
|
use a display range of $[-2, 2]$.
|
|
|
|
Finally, the camera controls available in Apophysis/[`flam3`](https://github.com/scottdraves/flam3/wiki/XML-File-Format)
|
|
have a number of settings that were simply not implemented so far:
|
|
|
|
<center></center>
|
|
|
|
The parameters remaining to implement are scale, zoom, rotation, and position.
|
|
|
|
## Scale
|
|
|
|
Fractal flames are defined on a continuous range. At some point, we must convert from fractal flame coordinates
|
|
into specific pixels, and scale is the parameter we use to do it. Specifically, scale is **the number of pixels
|
|
in one unit of the fractal flame coordinate system**.
|
|
|
|
For example, if you open the [reference parameters](../params.flame) in a text editor, you'll see the following:
|
|
|
|
```xml
|
|
<flame name="final xform" size="600 600" center="0 0" scale="150">
|
|
```
|
|
|
|
This says that the final image should be 600 pixels wide and 600 pixels tall, centered at the point $(0, 0)$,
|
|
with 150 pixels per unit. Dividing 600 by 150 gives us an image that is 4 units wide and 4 units tall.
|
|
And because the center is at $(0, 0)$, the final image is effectively looking at the range $[-2, 2]$ in the
|
|
fractal coordinate system (as mentioned above).
|
|
|
|
Scale can be used to implement a kind of "zoom" in images. If the reference parameters instead used `scale="300"`,
|
|
the same 600 pixels would instead be looking at the range $[-1, 1]$ in the fractal coordinate system.
|
|
|
|
This also demonstrates the biggest problem with using scale: it's a parameter that only controls the output image.
|
|
If the output image changed to `size="1200 1200"`, and scale stayed the same, the output image would have
|
|
a lot more white space. Instead, it's usually better to use a different parameter for controlling image size.
|
|
|
|
## Zoom
|
|
|
|
|
|
## Rotation
|
|
|
|
## Offset
|
|
|
|
|
|
|
|
import CodeBlock from "@theme/CodeBlock";
|
|
|
|
import cameraSource from "!!raw-loader!./camera"
|
|
|
|
<CodeBlock language="typescript">{cameraSource}</CodeBlock>
|
|
|
|
import {SquareCanvas} from "../src/Canvas";
|
|
import FlameCamera from "./FlameCamera";
|
|
|
|
<SquareCanvas name={"flame_camera"} width={'95%'} aspectRatio={'4/3'}><FlameCamera /></SquareCanvas>
|