🎉 Initial commit

This commit is contained in:
Geoff Murphy 2024-10-05 12:12:58 +10:00
commit 0be3c70181
10 changed files with 428 additions and 0 deletions

4
.gitignore vendored Executable file
View file

@ -0,0 +1,4 @@
/bin
/obj
/output
/tmp

44
makefile Executable file
View file

@ -0,0 +1,44 @@
OS := $(shell uname)
NAME=$(shell pwd | sed "s/.*\///g")
ifeq (${OS},Darwin)
CC=clang++
FLAGS=-std=c++11 -stdlib=libc++
RUN=${NAME}
else ifeq (${OS},Linux)
CC=g++
FLAGS=-std=c++11 -pthread
RUN=${NAME}
FILES=$(shell find -name *.cpp)
else
CC=g++
FLAGS=-std=c++11
RUN=${NAME}.exe
FILES=$(shell find -name *.cpp)
endif
all: clean build run images video play
build:
${CC} ${FILES} ${FLAGS} -o bin/${RUN}
run:
bin/./${RUN}
video:
ffmpeg -i output/frames/image_%05d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p output/video.mp4
play:
vlc -L output/video.mp4
images:
mogrify -verbose -format png output/frames/*.ppm
rm $(shell find output/frames -name "*.ppm")
clean:
rm -f -r bin/*
rm -f -r output/frames/*
rm -f output/video.mp4

1
src/fractal/buddhabulb.cpp Executable file
View file

@ -0,0 +1 @@
#include "buddhabulb.h"

6
src/fractal/buddhabulb.h Executable file
View file

@ -0,0 +1,6 @@
#ifndef BUDDHABULB_H_
#define BUDDHABULB_H_
#endif

191
src/fractal/buffer.cpp Executable file
View file

@ -0,0 +1,191 @@
#include "buffer.h"
/////////
///////// Buffer Functions
/////////
Buffer::Buffer(int _width, int _height){
width = _width;
height = _height;
itterations = 255;
samples = 4;
contrast = 2;
fractal = 1;
ratio = (float)width/(float)height;
setCursor(0, 0, 1, 0);
setStart(0, 0, 1, 0);
setEnd(0, 0, 1, 0);
buffer.resize(width, std::vector<int>(height));
}
void Buffer::clear(){
maxValue = 0;
for(int x=0; x<width; x++){
for(int y=0; y<height; y++){
buffer[x][y] = 0;
}
}
}
void Buffer::save(std::string _filename){
FILE *f = fopen( _filename.c_str(), "w" ); // Write image to PPM file.
fprintf(f, "P3\n%d %d\n%d\n", width, height, 255);
for(int y=0; y<height; y++){
for(int x=0; x<width; x++){
float bright = map((float)buffer[x][y], 0, (float)maxValue, 0, 1.0);
int value = (int)map(pow(bright, 1.0/contrast), 0, 1, 0, 255);
fprintf(f,"%d %d %d ", value, value, value);
}
}
}
/////////
///////// Buffer Settings
/////////
int Buffer::getMax(){
return maxValue;
}
void Buffer::setItterations(int _itterations){
itterations = _itterations;
}
void Buffer::setSamples(int _samples){
samples = _samples;
}
void Buffer::setContrast(float _contrast){
contrast = _contrast;
}
void Buffer::setFractal(unsigned char _fractal){
fractal = _fractal;
}
std::string Buffer::stats(){
std::ostringstream output;
output << "Buffer: " << width << "x" << height;
output << " Samples: " << samples << " Itterations: " << itterations;
output << " Contrast: " << contrast;
return output.str();
}
/////////
///////// Translate Coordinates
/////////
void Buffer::setCursor(float _x, float _y, float _s, float _r){
cur.x = _x;
cur.y = _y;
cur.s = _s;
cur.r = _r;
}
void Buffer::setStart(float _x, float _y, float _s, float _r){
start.x = _x;
start.y = _y;
start.s = _s;
start.r = _r;
}
void Buffer::setEnd(float _x, float _y, float _s, float _r){
end.x = _x;
end.y = _y;
end.s = _s;
end.r = _r;
}
void Buffer::cursorUpdate(float _f){
cur.x = start.x + (end.x-start.x)*_f;
cur.y = start.y + (end.y-start.y)*_f;
cur.s = start.s + (end.s-start.s)*_f;
cur.r = start.r + (end.r-start.r)*_f;
}
float Buffer::map(float _v, float _a1, float _a2, float _b1, float _b2){
return _b1 + (_v-_a1)*(_b2-_b1)/(_a2-_a1);
}
Coords Buffer::translate(int _x, int _y){
float angle = -cur.r * M_PI / 180.0;
float rx = (float)rand()/(float)RAND_MAX;
float ry = (float)rand()/(float)RAND_MAX;
Coords org; // origin point
org.x = ((((float)_x+rx) / (float)width * 2) - 1) * ratio; // X Origin
org.y = (((float)_y+ry) / (float)height * 2) - 1; // Y Origin
float x = cos(angle)*org.x*cur.s - sin(angle)*org.y*cur.s + cur.x; // New X
float y = sin(angle)*org.x*cur.s + cos(angle)*org.y*cur.s + cur.y; // New Y
Coords tmpCords = {x, y};
return tmpCords;
}
Pixel Buffer::translate(float _x, float _y){
float angle = cur.r * M_PI / 180.0;
Coords org; // origin point
org.x = cos(angle)*(_x-cur.x)/cur.s - sin(angle)*(_y-cur.y)/cur.s;
org.y = sin(angle)*(_x-cur.x)/cur.s + cos(angle)*(_y-cur.y)/cur.s;
float x = (org.x/ratio + 1) / 2 * width; // New X
float y = (org.y + 1) / 2 * height; // New Y
Pixel tmpPix = {(int)x, (int)y};
return tmpPix;
}
/////////
///////// Render Fractal
/////////
void Buffer::render(int _x, int _y){
Coords c = translate(_x, _y);
float a = c.x;
float b = c.y;
int n = 0;
float z = 0;
while(n<=itterations){
float aa = a*a - b*b;
float bb = 2.0 * a * b;
a = aa + c.x;
b = bb + c.y;
if(abs(a + b) > 4){ break; }
if(fractal==2 || fractal==0){
Pixel p = translate(a, b);
if(p.x>=0 && p.x<width && p.y>=0 && p.y<height){
buffer[p.x][p.y] += 1;
if(buffer[p.x][p.y]>maxValue){ maxValue = buffer[p.x][p.y]; }
}
}
n++;
}
if(fractal==1 || fractal==0){
if(n >= itterations){ n=0; }
buffer[_x][_y] += n;
if(buffer[_x][_y] > maxValue){ maxValue = buffer[_x][_y]; }
}
}

78
src/fractal/buffer.h Executable file
View file

@ -0,0 +1,78 @@
#ifndef BUFFER_H_
#define BUFFER_H_
#include <iostream>
#include <cmath>
#include <cstdio>
#include <sstream>
#include <string>
#include <vector>
#define M_PI 3.14159265358979323846 /* pi */
#define ALL 0
#define MANDELBROT 1
#define BUDDHABROT 2
#define BUDDHABULB 3
struct Cur{
float x; // X position of cursur
float y; // Y position of cursur
float s; // Scale of cursur
float r; // Rotation of cursur
};
struct Coords{
float x;
float y;
};
struct Pixel{
int x;
int y;
};
class Buffer{
private:
std::vector<std::vector<int>> buffer; // Buffer array
Cur cur; // Viewing cursur
Cur start;
Cur end;
float ratio; // Ratio of image width to hight
int itterations; // Number of itterations for render (defult 255)
float contrast; // Log contrast of render output (defult 2)
int maxValue; // Maximum value of array to normalise
unsigned char fractal; // Fractal type
public:
int width; // Width of buffer
int height; // Height of buffer
int samples; // Rendering subresolution (defult 2)
Buffer(int _width, int _height); // Constructor
void save(std::string _filename); // Save buffer to PPM image
void clear(); // Clear buffer
std::string stats(); // Print buffer stats to console
int getMax(); // Return max value in buffer
void setItterations(int _itterations); // Set number of render itterations
void setSamples(int _subres); // Set subresolution of render
void setContrast(float _contrast); // Set contast of output image
void setFractal(unsigned char _fractal); // set type of fractal to render
void setCursor(float _x, float _y, float _s, float _r);
void setStart(float _x, float _y, float _s, float _r);
void setEnd(float _x, float _y, float _s, float _r);
void cursorUpdate(float _f);
Coords translate(int _x, int _y);
Pixel translate(float _x, float _y);
float map(float _v, float _a1, float _a2, float _b1, float _b2);
void render(int _x, int _y);
};
#endif

33
src/fractal/timer.cpp Executable file
View file

@ -0,0 +1,33 @@
#include "timer.h"
Timer::Timer(){
startTime = clock();
std::cout << startTime << std::endl;
}
std::string Timer::getTime(){
clock_t elapsedTime = (clock() - startTime) / CLOCKS_PER_SEC;
unsigned char seconds = elapsedTime % 60;
unsigned char minutes = (elapsedTime / 60) % 60;
unsigned char hours = (elapsedTime / 3600) % 24;
unsigned char days = elapsedTime / 86400;
std::string tmpString = "";
if(days<10){ tmpString += "0"; }
tmpString += std::to_string(days);
if(hours<10){ tmpString += ":0"; }else{ tmpString+=":"; }
tmpString += std::to_string(hours);
if(minutes<10){ tmpString += ":0"; }else{ tmpString+=":"; }
tmpString += std::to_string(minutes);
if(seconds<10){ tmpString += ":0"; }else{ tmpString+=":"; }
tmpString += std::to_string(seconds);
return tmpString;
}

18
src/fractal/timer.h Executable file
View file

@ -0,0 +1,18 @@
#ifndef TIMER_H_
#define TIMER_H_
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
class Timer{
private:
clock_t startTime;
public:
Timer();
std::string getTime();
};
#endif

40
src/main.cpp Executable file
View file

@ -0,0 +1,40 @@
#include "main.h"
Buffer buffer(1920, 1080);
int main(int argc, char** argv){
Timer timer;
buffer.clear();
buffer.setContrast(2);
buffer.setSamples(8);
buffer.setItterations(255);
buffer.setFractal(ALL);
buffer.setStart(0, 0, 1, -10);
buffer.setEnd(0, 0, 0.8, 15);
std::cout << std::endl << buffer.stats() << std::endl << std::endl;
int frames = 200;
for(int f=0; f<=frames; f++){
buffer.clear();
buffer.cursorUpdate( (float)f/(float)frames );
for(int y=0; y<buffer.height; y++){
for(int x=0; x<buffer.width; x++){
for(int s=0; s<buffer.samples; s++){
buffer.render(x, y);
}
}
std::cout << " " << timer.getTime() << " Frame: " << f << " " << 100*y/buffer.height << "% maxValue: " << buffer.getMax() << " \r" << std::flush;
}
std::ostringstream filename;
filename << "output/frames/image_" << std::setfill('0') << std::setw(5) << f << ".ppm";
buffer.save( filename.str() );
}
std::cout << std::endl << std::endl << "Finished!" << std::endl << std::endl;
return 0;
}

13
src/main.h Executable file
View file

@ -0,0 +1,13 @@
#ifndef MAIN_H_
#define MAIN_H_
#include <cmath>
#include <iomanip>
#include <iostream>
#include <thread>
#include "fractal/buffer.h"
#include "fractal/buddhabulb.h"
#include "fractal/timer.h"
#endif