Skip to content

Instantly share code, notes, and snippets.

@rubenwardy
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rubenwardy/3d104ebcef8258b14bc8 to your computer and use it in GitHub Desktop.
Save rubenwardy/3d104ebcef8258b14bc8 to your computer and use it in GitHub Desktop.
#include <iostream>
#include "SDLEngine.hpp"
#include <sstream>
#include <vector>
#include <thread>
#include <mutex>
#define TILE_SIZE 64
#define TILE_TEX_SIZE 32 * TILE_SIZE * TILE_SIZE
struct Tile
{
int X;
int Y;
SDL_Texture *texture;
};
struct TileData
{
int X;
int Y;
Uint32 *pixels;
};
#include <unistd.h>
class TileRenderWorker
{
std::thread the_thread;
bool stop_thread;
void doTile(int X, int Y, double acorn, double bcorn, double size, double max_loop)
{
//std::cerr << "Building tile " << X << ", " << Y << std::endl;
Uint32 *pixels = static_cast<Uint32*>(malloc(TILE_TEX_SIZE));
for (double x = 0; x < TILE_SIZE; x++) {
for (double y = 0; y < TILE_SIZE; y++) {
double ax = x + X * TILE_SIZE;
double ay = y + Y * TILE_SIZE;
double count = 0;
double ca = acorn + ax * size / 1280;
double cb = bcorn + ay * size / 720;
double zx = 0;
double zy = 0;
do {
count++;
double tmp = zx*zx - zy*zy;
zy = 2*zx*zy + cb;
zx = tmp + ca;
} while(count < max_loop && zx*zx + zy*zy <= 4);
Uint32 result = (count / max_loop) * (count / max_loop) * 255.0;
Uint32 r2 = 255 / (count + 1);
pixels[(int)x + (int)y * TILE_SIZE] =
(result << 32) +
(result << 16) +
(result << 8) +
0xFF;
}
}
TileData tmp;
tmp.X = X;
tmp.Y = Y;
tmp.pixels = pixels;
{
std::lock_guard<std::mutex> guard(mut_out);
out.push_back(tmp);
}
}
public:
TileRenderWorker():
the_thread()
{}
~TileRenderWorker()
{
stop_thread = true;
if(the_thread.joinable())
the_thread.join();
}
std::vector<TileData> out;
std::mutex mut_out;
void run()
{
double acorn = -0.5;
double bcorn = 0.25;
double size = 1;
double max_loop = 1;
while(!stop_thread && max_loop < 100) {
for (int X = 0; X < 1280/TILE_SIZE; X++) {
for (int Y = 0; Y < 720/TILE_SIZE; Y++) {
doTile(X, Y, acorn, bcorn, size, max_loop);
}
}
max_loop += 1;
usleep(100000);
}
}
void start()
{
the_thread = std::thread(&TileRenderWorker::run, this);
}
};
class Game : public IEventReceiver
{
std::vector<Tile> tiles;
TileRenderWorker worker;
public:
void addTile(Uint32 *data, int X, int Y)
{
SDLEngine *engine = SDLEngine::get();
SDL_Texture *texture = SDL_CreateTexture(engine->getRenderer(),
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STREAMING,
TILE_SIZE, TILE_SIZE);
SDL_UpdateTexture(texture, NULL, data, TILE_SIZE * sizeof (Uint32));
free(data);
int i = 0;
for (Tile tile : tiles) {
if (tile.X == X && tile.Y == Y) {
SDL_DestroyTexture(tile.texture);
tiles.erase(tiles.begin() + i);
break;
}
i++;
}
Tile tmp;
// std::cerr << "Adding " << X << ", " << Y << std::endl;
tmp.X = X;
tmp.Y = Y;
tmp.texture = texture;
tiles.push_back(tmp);
}
void run()
{
SDLEngine *engine = SDLEngine::get();
engine->init();
engine->setEventReceiver(this);
double count = 0;
int frames_since = 0;
while (engine->run()) {
frames_since++;
if (engine->renderNeeded()) {
engine->start();
for (Tile tile : tiles) {
engine->renderTexture(tile.texture, TILE_SIZE * tile.X,
TILE_SIZE * tile.Y);
}
engine->end();
}
{
std::lock_guard<std::mutex> guard(worker.mut_out);
for (TileData data : worker.out)
addTile(data.pixels, data.X, data.Y);
worker.out.clear();
}
count += engine->dtime;
if (count > 1) {
std::ostringstream os;
os << "FractalTest | ";
os << frames_since;
os << " uFPS | ";
os << engine->renderProportion() * frames_since;
os << " rFPS [";
os << engine->renderProportion() * 100;
os << "%]";
engine->setWindowTitle(os.str().c_str());
frames_since = 0;
count = 0;
}
}
}
bool onEvent(SDL_Event &e)
{
if (e.type == SDL_KEYDOWN &&
e.key.keysym.sym == SDLK_UP) {
worker.start();
}
}
};
int main()
{
Game game;
game.run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment