Working proof of concept

parents
CFLAGS = -Wno-unused-command-line-argument -Wno-missing-field-initializers -Wall -Wextra -Wpedantic -lm
DEBUG_CFLAGS = -g -DDEBUG
LDLIBS = $(shell pkg-config --libs sdl2)
CFLAGS := $(CFLAGS) -O3
CFLAGS := $(CFLAGS) $(DEBUG_CFLAGS)
SRCDIR=src
BIULDDIR=build
# compiler
CC = gcc
OBJS = $(BIULDDIR)/mouse.o
all: mandelbrot
mandelbrot: $(SRCDIR)/mandelbrot.c $(OBJS)
$(CC) $(CFLAGS) $(LDLIBS) $^ -o $@
$(BIULDDIR)/mouse.o: src/mouse.c
$(CC) -c $(CFLAGS) $< -o $@
clean:
rm mandelbrot $(OBJS)
File added
File added
File added
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_surface.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_video.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <complex.h>
#include <pthread.h>
#include "mandelbrot.h"
#include "mouse.h"
int
mandelbrot(Complex c) {
Complex z = {0.0, 0.0};
int i;
for (i = 0; i < MAX_ITERATIONS; i++) {
double temp_real = z.real * z.real - z.imag * z.imag + c.real;
double temp_imag = 2 * z.real * z.imag + c.imag;
z.real = temp_real;
z.imag = temp_imag;
if (__builtin_hypot(z.real, z.imag) > 2)
return i;
}
return MAX_ITERATIONS;
}
struct{
SDL_Renderer *renderer;
ViewInfo view;
int start_x;
int end_x;
int start_y;
int end_y;
} typedef T_render_data ;
void *
t_render(void *render_data_vp)
{
T_render_data *data = (T_render_data *)render_data_vp;
SDL_SetRenderDrawColor(data->renderer, 0, 0, 50, 255);
SDL_RenderClear(data->renderer);
for (int x = 0; x < SCREEN_WIDTH; x++) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
double real = data->view.x_min + (x * (data->view.x_max - data->view.x_min)) / SCREEN_WIDTH;
double imag = data->view.y_min + (y * (data->view.y_max - data->view.y_min)) / SCREEN_HEIGHT;
Complex c = {real, imag};
int iterations = mandelbrot(c);
if (iterations == MAX_ITERATIONS){
SDL_SetRenderDrawColor(data->renderer, 0, 0, 0, 255);
} else {
double t = (double)iterations / MAX_ITERATIONS;
t = 0.5 + 0.5 * cos(log(t + 0.0001) * 3.0);
int r = (int)(255 * t);
int g = (int)(255 * t * 0.4);
int b = (int)(255 * t * 0.2);
SDL_SetRenderDrawColor(data->renderer, r, g, b, 255);
}
SDL_RenderDrawPoint(data->renderer, x, y);
}
}
pthread_exit(NULL);
}
void
render(SDL_Renderer* renderer, ViewInfo view, int start_x, int end_x, int start_y, int end_y) {
SDL_SetRenderDrawColor(renderer, 0, 0, 50, 255);
SDL_RenderClear(renderer);
for (int x = 0; x < SCREEN_WIDTH; x++) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
double real = view.x_min + (x * (view.x_max - view.x_min)) / SCREEN_WIDTH;
double imag = view.y_min + (y * (view.y_max - view.y_min)) / SCREEN_HEIGHT;
Complex c = {real, imag};
int iterations = mandelbrot(c);
if (iterations == MAX_ITERATIONS){
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
} else {
double t = (double)iterations / MAX_ITERATIONS;
t = 0.5 + 0.5 * cos(log(t + 0.0001) * 3.0);
int r = (int)(255 * t);
int g = (int)(255 * t * 0.4);
int b = (int)(255 * t * 0.2);
SDL_SetRenderDrawColor(renderer, r, g, b, 255);
}
SDL_RenderDrawPoint(renderer, x, y);
}
}
}
int
main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
App app = {
SDL_CreateWindow("Mandelbrot set exploer",
0, 0,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN),
SDL_CreateRenderer(app.window,
-1,
SDL_RENDERER_ACCELERATED)
};
ViewInfo view = {
.x_min = -2.0,
.x_max = 1.0,
.y_min = -1.5,
.y_max = 1.5,
.zoom = 1.0
};
Mouse mouse = {
.dragging = 0,
.start_x = 0,
.start_y = 0,
.original_view = view
};
const int FPS = 60;
const int FRAME_DELAY = 1000 / FPS;
Uint32 frame_start;
int frame_time;
int running = 1;
while (running)
{
frame_start = SDL_GetTicks();
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
running = 0;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.scancode)
{
case SDL_SCANCODE_Q:
case SDL_SCANCODE_ESCAPE:
running = 0;
break;
}
default:
handle_mouse(event, &mouse, &view);
break;
}
}
SDL_SetRenderDrawColor(app.renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(app.renderer);
//drawing happens here
pthread_t threads[THREADS];
int thread = 0;
render(app.renderer,
view,
0, SCREEN_WIDTH,
0,SCREEN_HEIGHT);
int msec = SDL_GetTicks() - frame_start;
float fps;
if(msec > 0)
fps = 1000.0 / (double) msec;
printf("fps:%f\n", fps);
/*for (int x = 0; x < SCREEN_HEIGHT; x += SCREEN_HEIGHT / THREADS * 2)
for (int y = 0; y < SCREEN_WIDTH; y += SCREEN_WIDTH / THREADS * 2)
{
T_render_data data = {
app.renderer,
view,
x, x + SCREEN_WIDTH / THREADS * 2,
y, y + SCREEN_HEIGHT/ THREADS * 2,
};
pthread_create();
}
*/
SDL_RenderPresent(app.renderer);
frame_time = SDL_GetTicks() - frame_start;
if (frame_time < FRAME_DELAY)
SDL_Delay(FRAME_DELAY - frame_time);
}
//SDL_FreeSurface(app.surfaceA);
SDL_DestroyRenderer(app.renderer);
SDL_DestroyWindow(app.window);
SDL_Quit();
}
#ifndef MANDELBROT_H
#define MANDELBROT_H
#include <SDL2/SDL.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define MAX_ITERATIONS 300
#define THREADS 4
struct{
double real;
double imag;
} typedef Complex;
struct{
SDL_Window *window;
SDL_Renderer *renderer;
} typedef App ;
struct{
double x_min;
double x_max;
double y_min;
double y_max;
double zoom;
} typedef ViewInfo ;
struct{
int dragging;
int start_x;
int start_y;
ViewInfo original_view;
} typedef Mouse ;
void render(SDL_Renderer* renderer, ViewInfo view, int start_x, int end_x, int start_y, int end_y);
#endif
#include "mandelbrot.h"
void
handle_mouse(SDL_Event event, Mouse* mouse, ViewInfo* view) {
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
mouse->dragging = 1;
mouse->start_x = event.button.x;
mouse->start_y = event.button.y;
mouse->original_view = *view;
}
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT) {
mouse->dragging = 0;
}
break;
case SDL_MOUSEWHEEL:
{
int x, y;
SDL_GetMouseState(&x, &y);
double mouse_real = view->x_min + (x * (view->x_max - view->x_min)) / SCREEN_WIDTH;
double mouse_imag = view->y_min + (y * (view->y_max - view->y_min)) / SCREEN_HEIGHT;
double zoom_factor = event.wheel.y > 0 ? 0.9 : 1.1;
double new_width = (view->x_max - view->x_min) * zoom_factor;
double new_height = (view->y_max - view->y_min) * zoom_factor;
view->x_min = mouse_real - (mouse_real - view->x_min) * zoom_factor;
view->x_max = mouse_real + (view->x_max - mouse_real) * zoom_factor;
view->y_min = mouse_imag - (mouse_imag - view->y_min) * zoom_factor;
view->y_max = mouse_imag + (view->y_max - mouse_imag) * zoom_factor;
view->zoom *= (1.0 / zoom_factor);
}
break;
case SDL_MOUSEMOTION:
if (mouse->dragging) {
int dx = event.motion.x - mouse->start_x;
int dy = event.motion.y - mouse->start_y;
double scale_x = (mouse->original_view.x_max - mouse->original_view.x_min) / SCREEN_WIDTH;
double scale_y = (mouse->original_view.y_max - mouse->original_view.y_min) / SCREEN_HEIGHT;
view->x_min = mouse->original_view.x_min - dx * scale_x;
view->x_max = mouse->original_view.x_max - dx * scale_x;
view->y_min = mouse->original_view.y_min - dy * scale_y;
view->y_max = mouse->original_view.y_max - dy * scale_y;
}
break;
}
}
#ifndef MOUSE_H
#define MOUSE_H
#include "mandelbrot.h"
#include <SDL2/SDL_events.h>
void handle_mouse(SDL_Event, Mouse*, ViewInfo*);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment