#ifndef APP_H #define APP_H #include #include #include #include #include #include #include #include "stfu/stf.hpp" #include "pngwriter/pngwriter.h" #include "shader.h" #include "fbo.h" static const std::string filenames[] = { "resources/attractor_2011-04-28_10-30-35-2.stf", "resources/attractor_2011-04-28_10-05-11-1.stf", "resources/attractor_2011-04-29_04-34-41-9.stf", "resources/attractor_2011-04-29_15-19-03-9.stf" }; class App { int counter; unsigned int width, height; shader mshader; shader clear_shader; fbo mfbo; static constexpr size_t number_of_lines = 6*50000; static constexpr size_t number_of_vertices = 2*number_of_lines; std::array lines; std::array parameters; std::array random_parameters; public: App(unsigned int w, unsigned int h) : counter(0), width(w), height(h), mshader("resources/myTeaShader.vert", "resources/myTeaShader.frag"), clear_shader("resources/myClearShader.vert", "resources/myClearShader.frag"), mfbo(width, height) { set_points(); //glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glPointSize(1.0); std::string filename = filenames[3]; set_parameters(filename); } ~App() { } void resize(int w, int h) { } void update() { ++counter; iterate(); if(counter % 500 == 0) { set_parameters(filenames[rand() % 4]); set_points(); } } void draw() { clear_shader.begin(); clear_shader.set_uniform("fade", .5f); if( counter < 5 ) clear_shader.set_uniform("fade", 1.0f); fade(); mshader.begin(); mshader.set_uniform("steps", counter); glRotatef(0.5, std::sin(counter/1337.0), 1.0, 0.0); scene(); } void fade() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); static const GLfloat quad[] = { 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0 }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &quad[0]); // draw a cube glDrawArrays(GL_QUADS, 0, 4); // deactivate vertex arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); } void scene() { glBlendFunc(GL_ONE, GL_ONE); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, &lines[0]); // draw a cube glDrawArrays(GL_POINTS, 0, number_of_vertices); // deactivate vertex arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); //save_screen(); } void iterate() { for(size_t i = 0; i < number_of_lines; ++i) { GLfloat* vectorNew = &lines[3*2*i]; GLfloat* vectorOld = &lines[3*2*i+3]; if(counter % 2) std::swap(vectorNew, vectorOld); vectorNew[0] = parameters[0]*(vectorOld[2] + parameters[1]); vectorNew[1] = parameters[2]*(vectorOld[0] + parameters[3]); vectorNew[2] = parameters[4]*(vectorOld[1] + parameters[5]); const double dist = vectorNew[0]*vectorNew[0] + vectorNew[1]*vectorNew[1] + vectorNew[2]*vectorNew[2]; if(dist > parameters[6]*parameters[6]) { const double sqrtDist = std::sqrt(dist); const double p = 1.0 - parameters[6] * (static_cast(sqrtDist / parameters[6]) + 1.0) / sqrtDist; vectorNew[0] *= p; vectorNew[1] *= p; vectorNew[2] *= p; } } for(size_t i = 0; i < 7; ++i){ parameters[i] += random_parameters[i]; } } void save_screen(){ unsigned char data[width*height*6]; glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT, data); char filename[256]; sprintf(filename, "render/shot_%08d.png", counter); pngwriter png(width, height, &data[0], filename); png.close(); } void set_parameters(std::string filename){ stfu::node file; file.read(filename.c_str()); for(unsigned int i = 0; i < 7; ++i) { stfu::node const attractorParameters = file.getChild("AttractorKernel").getChild("parameters"); parameters[i] = atof(attractorParameters.getValue(i).c_str()); random_parameters[i] = (rand() / (double)RAND_MAX - 0.5) * counter / 500000.0; } } void set_points(){ std::generate(lines.begin(), lines.end(), []() { return 2.0 * rand() / (double)RAND_MAX - 1.0; }); } }; #endif // APP_H