#ifdef REACTIVE_ENABLED #include"RtAudio.h" #endif #include"gl_window.hpp" #include"gl_shader.hpp" #include"autofilter.hpp" #include"glm/glm.hpp" #include"glm/gtc/type_ptr.hpp" #include"glm/gtc/matrix_transform.hpp" #ifdef _WIN32 #include"getopt.h" #include"ac.h" #else #include"acidcam/ac.h" #include<unistd.h> #endif #include<vector> #include<sstream> #include<string> #include<fstream> #include<iomanip> #include<iostream> #include<chrono> #include<algorithm> #include<cctype> #include<cmath> #include"keymap.hpp" #include"ipc_client.hpp" #define version_info "v1.9.0" #ifdef SYPHON_SERVER #include"syphon.h" #endif #include<unordered_map> #ifdef SYPHON_SERVER extern void ScreenGrabRect(int x, int y, int w, int h, cv::Mat &frame); #endif #ifdef FOR_LINUX #include"x11-screen.hpp" #endif #include"ffmpeg_write.h" #ifdef _WIN32 //#define SPOUT_SERVER #endif #ifdef SPOUT_SERVER #include"SpoutLibrary.h" #endif #include"plugin-program.hpp" #include"stereo.h" #ifdef MIDI_ENABLED #include"midi_cfg.hpp" extern midi::MIDI_Config config; #endif extern int findFilter(std::string f); namespace acidcam { extern cv::VideoCapture cap, cap_second; extern int redir; extern int syphon_enabled; #ifdef FOR_LINUX extern ScreenShot *screen_shot; #endif class AcidCam_Window : public glWindow { static constexpr int numVAOs = 1; static constexpr int numVBOs = 2; GLuint vao[numVAOs]; GLuint vbo[numVBOs]; ShaderProgram program; GLuint mv_loc, proj_loc; int width, height; float aspect; glm::mat4 p_mat, v_mat, m_mat, mv_mat; GLuint texture; float color_alpha_r, color_alpha_g, color_alpha_b; std::vector<ShaderProgram> shaders; cv::VideoWriter writer; bool writer_set = false; int shader_index; bool print_text; bool debug; float alpha; bool ac_on; glm::vec4 optx, random_var; KeyMap mapped_keys; float movement_rate; bool take_snapshot; std::string snapshot_prefix; bool restore_black; bool list_enabled; std::vector<int> var_list; int var_index; bool repeat; int color_map; int blend_index; int sx, sy; bool video_mode; int fps; int screen_x, screen_y; bool playback_mode; bool playback_sort; int p_timeout; bool rand_timeout; bool paused; bool stereo_; int stored_position, stored_var_position; bool rand_shader; bool shader_list_enabled; bool stereo_mode = false; FILE *fptr; std::vector<int> shader_list; std::unordered_map<std::string, int> shader_map; bool enable_cubeapp = false; bool blur_enabled; std::string output_format; #ifdef SPOUT_SERVER SPOUTLIBRARY* spoutsender; #endif glm::vec4 inc_value; glm::vec4 inc_valuex; bool p_run = false; AutoFilter af; bool af_enabled = false; std::string material_file; bool time_manip = false; bool audio_enabled = false; double time_manip_f = 1.0; bool time_keys[2]; bool restore_value = false; public: AcidCam_Window() = default; AcidCam_Window(const AcidCam_Window &) = delete; AcidCam_Window &operator=(const AcidCam_Window &) = delete; void setOutputFormat(std::string f) { output_format = f; } void loadAutoFilter(const std::string &f) { if(af.loadFile(f)) af_enabled = true; } void enableCube(bool value) { enable_cubeapp = value; if(value) std::cout << "acidcam: Cube mode enabled...\n"; } StereoCam stereo; void StereoX(int *id, int w, int h, double fps_) { stereo.Load(id); stereo.SetSize(w, h, fps_); stereo_ = true; stereo_mode = true; } #ifdef REACTIVE_ENABLED float amp = 1.0f; float amp_sense = 2.0f; void setAmp(float f, float s) { amp = f; amp_sense = s; } #endif #ifdef SPOUT_SERVER bool INIT_TEXTURE(GLuint& texID, unsigned int width, unsigned int height) { if (texID != 0) glDeleteTextures(1, &texID); glGenTextures(1, &texID); glBindTexture(GL_TEXTURE_2D, texID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); return true; } #endif cv::Mat image_file; bool image_mode = false; void setImageMode(const cv::Mat &m, int f) { image_file = m.clone(); image_mode = true; fps = f; } void setVideoMode(bool b, int f) { video_mode = b; fps = f; } void setFilePointer(FILE *fptr, int w, int h) { this->fptr = fptr; writer_w = w; writer_h = h; } GLuint senderTexture = 0; virtual void init() override { blur_enabled = false; shader_list_enabled = false; fptr = 0; rand_shader = false; stored_position = 0; stored_var_position = 0; stereo_ = false; paused = false; rand_timeout = false; video_mode = false; p_timeout = 1; blend_index = 0; color_map = -1; var_index = 0; list_enabled = false; restore_black = false; snapshot_prefix="AcidCamGL_Snapshot"; take_snapshot = false; optx = glm::vec4(0.5,0.5,0.5,0.5); index = 0; movement_rate = 0.07f; ac_on = false; alpha = 0.1f; debug = false; print_text = false; shader_index = 0; color_alpha_r = 0.1; color_alpha_g = 0.2; color_alpha_b = 0.3; inc_value = glm::vec4(rand() % 255, rand() % 255, rand() % 255, 1); inc_valuex = glm::vec4(rand() % 255, rand() % 255, rand() % 255, 1); repeat = false; GLfloat vertices[] = { -1.0f, -1.0f, 1.0f, // front face 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat texCoords[] = { 0, 0, // front 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, }; if(enable_cubeapp) { init_cube(); return; } playback_mode = false; glGenVertexArrays(1, vao); glBindVertexArray(vao[0]); glGenBuffers(numVBOs, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW); glfwGetFramebufferSize(win(), &width, &height); aspect = (float)width/(float)height; p_mat = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); cv::Mat frame; if(image_mode == true) { frame = image_file.clone(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame.cols, frame.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, frame.ptr()); sx = frame.cols; sy = frame.rows; } else if(!cap.isOpened()) { return; } else { cap.read(frame); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame.cols, frame.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, frame.ptr()); sx = frame.cols; sy = frame.rows; } #ifdef SPOUT_SERVER spoutsender = GetSpout(); if (!spoutsender) { MessageBoxA(NULL, "Load Spout library failed", "Spout Sender", MB_ICONERROR); exit(0); } senderTexture = 0; INIT_TEXTURE(senderTexture, window_width, window_height); #endif } int index; void setShader(int index) { if(index < 0 || index > shaders.size()-1) { std::cerr << "acidcam: Shader Index: Out of range setting default...\n"; index = 0; } program = shaders[index]; if(debug) { std::cout << "acidcam: Shader Program: " << index << " - Loaded: " << program.name() << "\n"; } shader_index = index; } void sortPlaylist() { unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::shuffle(var_list.begin(), var_list.end(), std::default_random_engine(seed)); } void setPlaybackMode(bool v, int timeout = 0, int beat = 0, int bpm = 0, bool s = false) { if(p_timeout == 0) { std::cout << "acidcam: Error you must set playback timeout with -N\n"; acidcam::updateError(); } playback_mode = v; if(s) std::sort(var_list.begin(), var_list.end()); if(bpm != 0 && beat != 0) { p_timeout = beat; std::cout <<"acidcam: Beats per minute: " << bpm << " frames per beat: " << p_timeout << "\n"; } else p_timeout = timeout; } GLuint material = 0; bool material_on = false; float img_cols = 0, img_rows = 0; void genMaterial(std::string s) { glGenTextures(1, &material); glBindTexture(GL_TEXTURE_2D, material); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); cv::Mat frame; auto lowerString = [](const std::string &sx) -> std::string { std::string val; for(int i = 0; i < sx.length(); ++i) { val += tolower(sx[i]); } return val; }; std::string sx = lowerString(s); if(sx.find(".mp4") != std::string::npos || sx.find(".mkv") != std::string::npos || sx.find(".avi") != std::string::npos || sx.find(".m4v") != std::string::npos || sx.find(".mov") != std::string::npos) { if(!cap_second.open(s)) { std::cout << "acidcam: Error could not open secondary material video...\n"; acidcam::updateError(); exit(EXIT_FAILURE); } else { std::cout << "acidcam: Opened secondary video [" << s << "]\n"; material_file = s; } if(!cap_second.read(frame)) { std::cout << "acidcam: Could not read frame from video.\n"; acidcam::updateError(); exit(EXIT_FAILURE); } } else { frame = cv::imread(s); } if(frame.empty()) { std::cout << "acidcam: Error could not load texture: " << s << "\n"; acidcam::updateError(); } cv::Mat flipped; cv::flip(frame, flipped, 0); cv::cvtColor(flipped, frame, cv::COLOR_BGR2RGB); img_cols = frame.cols; img_rows = frame.rows; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame.cols, frame.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, frame.ptr()); std::cout << "acidcam: Successfully loaded material: " << s << "\n"; material_on = true; } void setPrintText(bool b) { print_text = b; } void setPrefix(const std::string &s) { snapshot_prefix = s; } void setRestoreBlack(bool &b) { restore_black = b; } void loadKeys(const std::string &n) { mapped_keys.load(n); } int find_solo(const std::string &s) { for(int i = 0; i < ac::solo_filter.size(); ++i) { if(ac::solo_filter[i] == s) return i; } return -1; } void loadList(const std::string &l, bool s = false) { std::fstream file; file.open(l, std::ios::in); if(!file.is_open()) { std::cout << "acidcam: Error could not open playlist: " << l << "\n"; acidcam::updateError(); } while(!file.eof()) { std::string s; std::getline(file, s); if(file) { if(s.length()>0) { int value = find_solo(s); if(value == -1) { std::cout << "acidcam: Error could not find for playlist string: " << s << "\n"; //quit(); //return; } else var_list.push_back(value); } } } file.close(); std::cout << "acidcam: Playlist loaded [" << var_list.size() << "] items...\n"; if(s == true) { sortPlaylist(); std::cout << "acidcam: Playlist Shuffled...\n"; } } bool screen_mode = false; void enableScreenMode(bool b, int x, int y, int w, int h) { screen_mode = b; sx = w; sy = h; screen_x = x; screen_y = y; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); cv::Mat frame(h, w, CV_8UC3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame.cols, frame.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, frame.ptr()); } void takeSnapshot() { static int index = 0; ++index; if(index > 999999) index = 1; cv::Mat flipped; readFrame(flipped); time_t t = time(0); #ifdef _WIN32 struct tm mm; localtime_s(&mm, &t); struct tm* m = &mm; #else struct tm *m; m = localtime(&t); #endif std::ostringstream time_stream; time_stream << snapshot_prefix << "-" << (m->tm_year + 1900) << "." << std::setw(2) << std::setfill('0') << (m->tm_mon + 1) << "." << std::setw(2) << std::setfill('0') << m->tm_mday << "_" << std::setw(2) << std::setfill('0') << m->tm_hour << "." << std::setw(2) << std::setfill('0') << m->tm_min << "." << std::setw(2) << std::setfill('0') << m->tm_sec << "_" << flipped.cols << "x" << flipped.rows << "x" << index << "." << output_format; cv::imwrite(time_stream.str(), flipped); std::cout << "acidcam: Wrote: " << time_stream.str() << "\n"; if(redir == 1) { #if defined(__APPLE__) || defined(__linux__) if(redirect != 0) sendString(redirect->getString()); #endif } } void readFrame(cv::Mat &frame) { cv::Mat img; int width, height; glfwGetFramebufferSize(win(), &width, &height); img.create(height, width,CV_8UC3); GLsizei nrChannels = 3; GLsizei stride = nrChannels * width; stride += (stride % 4) ? (4 - stride % 4) : 0; GLsizei bufferSize = stride * height; std::vector<char> buffer(bufferSize); glPixelStorei(GL_PACK_ALIGNMENT, 4); glReadBuffer(GL_FRONT); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, img.data); cv::Mat flipped; cv::flip(img, flipped, 0); cv::Mat frame1; cv::cvtColor(flipped, frame1, cv::COLOR_RGB2BGR); if(window_width != width || window_height != height) { cv::resize(frame1,frame, cv::Size(window_width, window_height)); } else frame = frame1; } int writer_w = 0, writer_h = 0; void setWriter(cv::VideoWriter w, int writer_ww, int writer_hh) { writer = w; writer_set = true; writer_w = writer_ww; writer_h = writer_hh; } void write(cv::Mat &frame) { if(frame.empty()) return; if(fptr != 0) { cv::Mat reimage; if(frame.size() != cv::Size(writer_w, writer_h)) { cv::resize(frame, reimage, cv::Size(writer_w, writer_h)); write_ffmpeg(fptr, reimage); } else write_ffmpeg(fptr, frame); } else { if(frame.size() != cv::Size(writer_w,writer_h)) { cv::Mat re; cv::resize(frame, re, cv::Size(writer_w, writer_h)); writer.write(re); } else writer.write(frame); } #if defined(__APPLE__) || defined(__linux__) if(redirect != 0) { static unsigned long long frame = 1; int total = cap.get(cv::CAP_PROP_FRAME_COUNT); if(fps > 0 && (frame % static_cast<unsigned long long>(fps * 20)) == 0) { std::ostringstream stream; stream << "acidcam: wrote frame: " << frame << "/" << total << "/" << (frame / static_cast<unsigned long long>(fps)) << " seconds...\n"; sendString(stream.str()); } ++frame; if(frame > 1000000000000ULL) frame = 1; } #endif } void writeFrame() { static bool skip = true; if(skip == true) { skip = false; return; } cv::Mat frame; readFrame(frame); write(frame); } void setStereo(bool b) { stereo_mode = b; if(b == true) std::cout << "acidcam: Stereo mode enabled...\n"; } bool bInitialized = false; virtual void update(double timeval) override { if (paused) return; const double TIME_WRAP = 86400.0; if(timeval > TIME_WRAP) { timeval = fmod(timeval, TIME_WRAP); } if (time_manip == true && time_keys[0]) { if(time_manip_f > 1.0) { time_manip_f -= 0.05; std::cout << "acidcam: Time: " << time_manip_f << " shifted back.\n"; } } else if(time_manip == true && time_keys[1]) { time_manip_f += 0.05; std::cout << "acidcam: Time: " << time_manip_f << " shifted forward.\n"; } if(restore_value == true) { time_manip_f = timeval; restore_value = false; std::cout << "acidcam: Restored time value to current.\n"; } if(std::isnan(time_manip_f) || std::isinf(time_manip_f)) time_manip_f = 1.0; const double TIME_MANIP_WRAP = 86400.0; if(time_manip_f > TIME_MANIP_WRAP) { time_manip_f = fmod(time_manip_f, TIME_MANIP_WRAP); } if(time_manip) timeval = time_manip_f; #ifdef REACTIVE_ENABLED if (audio_enabled) { time_manip_f += (amp * amp_sense); timeval = time_manip_f; std::cout << "acidcam: audio amp + time: " << timeval << "\n"; } #endif if(enable_cubeapp) { update_cube(timeval); return; } if(af_enabled && af.size()>0) { AutoFilterIndex index{af.current()}; int sh = shader_map[index.shader]; program = shaders[sh]; int i = findFilter(index.filter); if(i == -1) { std::cout << "acidcam: Could not find filter: " << index.filter << "\n"; exit(EXIT_FAILURE); } else { setFilterIndex(i); if(!af.increment()) { af.next(); std::cout << "acidcam: [AutoFilter] - " << af.current() << "\n"; } } } std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); glClearColor(0.0, 0.0, 0.0, 1.0); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (rand_shader == true && shaders.size() > 1) program = shaders[rand() % shaders.size()]; program.useProgram(); mv_loc = glGetUniformLocation(program.id(), "mv_matrix"); proj_loc = glGetUniformLocation(program.id(), "proj_matrix"); GLuint samp = glGetUniformLocation(program.id(), "samp"); GLuint mat_samp = glGetUniformLocation(program.id(), "mat_samp"); GLuint calpha_r = glGetUniformLocation(program.id(), "value_alpha_r"); GLuint calpha_g = glGetUniformLocation(program.id(), "value_alpha_g"); GLuint calpha_b = glGetUniformLocation(program.id(), "value_alpha_b"); GLuint c_index = glGetUniformLocation(program.id(), "index_value"); GLuint c_tf = glGetUniformLocation(program.id(), "time_f"); GLuint alpha_pos = glGetUniformLocation(program.id(), "alpha_value"); GLuint optx_pos = glGetUniformLocation(program.id(), "optx"); GLuint rand_pos = glGetUniformLocation(program.id(), "random_var"); GLuint restore_blackx = glGetUniformLocation(program.id(), "restore_black"); GLuint inc_value_pos = glGetUniformLocation(program.id(), "inc_value"); GLuint inc_value_posx = glGetUniformLocation(program.id(), "inc_valuex"); GLuint material_size; material_size = glGetUniformLocation(program.id(), "mat_size"); v_mat = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0)); m_mat = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0)); mv_mat = v_mat * m_mat; #ifdef SYPHON_SERVER if (syphon_enabled) { syphon_bind(window_width, window_height); } #endif glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat)); glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(p_mat)); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); cv::Mat frame; if(image_mode == true) { frame = image_file.clone(); } else if (screen_mode == false) { if(stereo_ == false) { if (!cap.read(frame)) { if (repeat == true && repeat_filename.length() > 0) { cap.open(repeat_filename); if (cap.isOpened()) { cap.read(frame); std::cout << "acidcam: video loop...\n"; } else { std::cout << "acidcam: Capture device closed exiting...\n"; quit(); return; } } else { std::cout << "acidcam: Capture device closed exiting...\n"; quit(); return; } } } } else { #ifdef SYPHON_SERVER cv::Mat cvMat, temp_frame; ScreenGrabRect(screen_x, screen_y, window_width, window_height, cvMat); cv::cvtColor(cvMat, temp_frame, cv::COLOR_RGBA2BGR); cv::resize(temp_frame, cvMat, cv::Size(sx, sy)); frame = cvMat; #endif #ifdef FOR_LINUX if(screen_shot == nullptr) { screen_shot = new ScreenShot(); } cv::Mat cvMat, temp_frame; (*screen_shot)(cvMat, screen_x, screen_y, window_width, window_height); cv::cvtColor(cvMat, temp_frame, cv::COLOR_RGBA2BGR); cv::resize(temp_frame, cvMat, cv::Size(sx, sy)); frame = cvMat; #endif } if (playback_mode && list_enabled) { static size_t playback_index = 0; static int frame_time = 0; static int current_timeout = p_timeout; ++frame_time; if (p_timeout == 0 || frame_time > current_timeout) { ++playback_index; if (rand_timeout && p_timeout) current_timeout = 1 + rand() % p_timeout; } if (frame_time > p_timeout) frame_time = 0; if (playback_index >= var_list.size()) { playback_index = 0; sortPlaylist(); } if(!var_list.empty()) index = var_list[playback_index]; } if (video_mode == false && stereo_) { frame.create(cv::Size(window_width, window_height),CV_8UC3); stereo.Render(frame); cv::flip(frame, frame, 0); } else if(video_mode == true && stereo_mode) { ac::Stereo(frame); } if (shader_index == 0 || ac_on == true) { if (index >= 0 && index < ac::solo_filter.size()) { cv::Mat orig; if (blend_index > 0) { orig = frame.clone(); } CallCustom(ac::solo_filter[index], frame); if (blend_index > 0 && blend_index / 10 > 0) { cv::Mat copyf; double per = 1.0 / (blend_index / 10); ac::AlphaBlendDouble(frame, orig, copyf, per, 1.0 - per); frame = copyf.clone(); } if (color_map != -1) { cv::Mat output_f1 = frame.clone(); cv::applyColorMap(output_f1, frame, color_map); } if (restore_black == true) { ac::CallFilter("RestoreBlack", frame); if (color_map != -1) { cv::Mat output_f1 = frame.clone(); cv::applyColorMap(output_f1, frame, color_map); } } if (print_text == true) { std::ostringstream stream; stream << ac::solo_filter[index]; cv::putText(frame, stream.str(), cv::Point(40, 40), cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(255, 255, 255), 2); } } } else { if(stereo_ == false) cv::flip(frame, frame, 0); } glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame.cols, frame.rows, GL_BGR, GL_UNSIGNED_BYTE, frame.ptr()); if (material_on) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, material); cv::Mat frame1; if(cap_second.isOpened()) { if(!cap_second.read(frame1)) { cap_second.open(material_file); if(!cap_second.isOpened()) { std::cout << "acidcam: Error opening video: " << material_file << "\n"; acidcam::updateError(); } if(!cap_second.read(frame1)) { std::cout << "acidcam: Error reading frame..\n"; acidcam::updateError(); exit(EXIT_FAILURE); } } cv::flip(frame1, frame1, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame1.cols, frame1.rows, GL_BGR, GL_UNSIGNED_BYTE, frame1.ptr()); } } color_alpha_r += rand() % 100 * 0.01f; color_alpha_g += rand() % 100 * 0.01f; color_alpha_b += rand() % 100 * 0.01f; if (color_alpha_r > 1.5f) color_alpha_r = 0.1f; if (color_alpha_g > 1.5f) color_alpha_g = 0.1f; if (color_alpha_b > 1.5f) color_alpha_b = 0.1f; static bool idir = true; if (idir == true) { alpha += 0.1f; if (alpha >= 6.0) idir = false; } else { alpha -= 0.1f; if (alpha <= 1.0f) { idir = true; } } random_var = glm::vec4(rand() % 255, rand() % 255, rand() % 255, rand() % 255); static int inc_dir = 1; if (inc_dir == 1) { for (int i = 0; i < 3; ++i) { ++inc_value[i]; if (inc_value[i] >= 255) inc_dir = 0; } } else { for (int i = 0; i < 3; ++i) { --inc_value[i]; if (inc_value[i] <= 1) { inc_dir = 1; inc_value = glm::vec4(rand() % 255, rand() % 255, rand() % 255, 1); } } } static int inc_dirx = 1; if (inc_dirx == 1) { for (int i = 0; i < 3; ++i) { ++inc_valuex[i]; if (inc_valuex[i] >= 255) inc_dirx = 0; } } else { for (int i = 0; i < 3; ++i) { --inc_valuex[i]; if (inc_valuex[i] <= 1) { inc_dirx = 1; } } } for(int i = 0; i < 4; ++i) { if(optx[i] > 1000.0f) optx[i] = 1000.0f; else if(optx[i] < -1000.0f) optx[i] = -1000.0f; if(std::isnan(optx[i]) || std::isinf(optx[i])) optx[i] = 0.5f; } glUniform1i(samp, 0); glUniform1i(mat_samp, 1); glUniform1f(c_index, (float)index); glUniform1f(c_tf, static_cast<float>(timeval)); glUniform4fv(inc_value_pos, 1, glm::value_ptr(inc_value)); glUniform4fv(inc_value_posx, 1, glm::value_ptr(inc_valuex)); glUniform1f(calpha_r, color_alpha_r); glUniform1f(calpha_g, color_alpha_g); glUniform1f(calpha_b, color_alpha_b); glUniform1f(alpha_pos, alpha); glUniform4fv(optx_pos, 1, glm::value_ptr(optx)); glUniform4fv(rand_pos, 1, glm::value_ptr(random_var)); glUniform1f(restore_blackx, ((restore_black == true) ? 1.0 : 0.0)); GLint loc = glGetUniformLocation(program.id(), "iResolution"); glUniform2f(loc, width, height); glUniform2f(material_size, img_cols, img_rows); glDrawArrays(GL_TRIANGLES, 0, 6); #ifdef SYPHON_SERVER int tex = syphon_pushTexture(texture); glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex); glDrawArrays(GL_TRIANGLES, 0, 6); #endif if (shader_list_enabled && !shader_list.empty()) { for (size_t i = 0; i < shader_list.size(); ++i) { int shader_idx = shader_list[i]; if (shader_idx >= 0 && shader_idx < static_cast<int>(shaders.size())) { ShaderProgram &pass_program = shaders[shader_idx]; pass_program.useProgram(); GLuint pass_mv_loc = glGetUniformLocation(pass_program.id(), "mv_matrix"); GLuint pass_proj_loc = glGetUniformLocation(pass_program.id(), "proj_matrix"); GLuint pass_samp = glGetUniformLocation(pass_program.id(), "samp"); GLuint pass_tf = glGetUniformLocation(pass_program.id(), "time_f"); GLuint pass_alpha = glGetUniformLocation(pass_program.id(), "alpha_value"); GLuint pass_res = glGetUniformLocation(pass_program.id(), "iResolution"); glUniformMatrix4fv(pass_mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat)); glUniformMatrix4fv(pass_proj_loc, 1, GL_FALSE, glm::value_ptr(p_mat)); glUniform1i(pass_samp, 0); glUniform1f(pass_tf, timeval); glUniform1f(pass_alpha, alpha); glUniform2f(pass_res, width, height); glDrawArrays(GL_TRIANGLES, 0, 6); } } } if (take_snapshot == true) { takeSnapshot(); take_snapshot = false; } if (writer_set == true) writeFrame(); #ifdef SPOUT_SERVER if (!bInitialized) { bInitialized = spoutsender->CreateSender("acidcamGL", window_width, window_height); } if (bInitialized) { if (window_width > 0 && window_height > 0) { glBindTexture(GL_TEXTURE_2D, senderTexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, window_width, window_height); spoutsender->SendTexture(senderTexture, GL_TEXTURE_2D, window_width, window_height); } } #endif if (video_mode && fps != 0) { std::chrono::time_point<std::chrono::system_clock> nowx = std::chrono::system_clock::now(); auto m = std::chrono::duration_cast<std::chrono::milliseconds>(nowx - now).count(); if (fps > 0) { int fps_mil = 1000 / fps; if (m < fps_mil) std::this_thread::sleep_for(std::chrono::milliseconds(fps_mil - m - 1)); } } } void setDebug(bool d) { debug = d; } std::string repeat_filename; void setRepeat(std::string fn, bool r) { repeat = r; repeat_filename = fn; } void setColorMap(int map) { color_map = map; if(map != -1) { std::cout << "acidccam: Set color map: " << map << "\n"; } } std::string input_string; void typeKey(unsigned int key) { if(key >= '0' && key <= '9') input_string += static_cast<char>(key); } void setFilterIndex(const int &i) { index = i; if(i != 0) ac_on = true; if(debug) { std::cout << "acidcam: Filter Index: " << index << " - " << ac::solo_filter[index] << "\n"; } } int setCustomFilter(std::string s) { custom_filters["CustomFilterStack"] = std::vector<std::string>(); std::vector<std::string> &flist = custom_filters["CustomFilterStack"]; auto pos = s.find(","); while(pos != std::string::npos) { std::string left, right; left = s.substr(0, pos); s = s.substr(pos+1, s.length()); if(find_solo(left) == -1) { std::cout << "acidcam: Error filter: " << left << " not found!\n"; updateError(); } flist.push_back(left); pos = s.find(","); if(pos == std::string::npos && s.length() > 0) { if(find_solo(s) == -1) { std::cout << "acidcam: Error filter: " << s << " not found!\n"; updateError(); } flist.push_back(s); } } ac::solo_filter.push_back("CustomFilterStack"); std::cout << "acidcam: Custom Loaded: " << ac::solo_filter[ac::solo_filter.size()-1] << "\n"; return static_cast<int>(ac::solo_filter.size()-1); } int setCustomFilterByIndex(std::string s) { custom_filters["CustomFilterStack"] = std::vector<std::string>(); std::vector<std::string> &flist = custom_filters["CustomFilterStack"]; auto pos = s.find(","); while(pos != std::string::npos) { std::string left, right; left = s.substr(0, pos); s = s.substr(pos+1, s.length()); int num = atoi(left.c_str()); if(num < 0 || num > ac::solo_filter.size()-1) { std::cout << "acidcam: Error index out of range.\n"; updateError(); return 0; } flist.push_back(ac::solo_filter[num]); pos = s.find(","); if(pos == std::string::npos && s.length() > 0) { int num = atoi(s.c_str()); if(num < 0 || num > ac::solo_filter.size()-1) { std::cout << "acidcam: Error filter: " << num << " not found!\n"; updateError(); } flist.push_back(ac::solo_filter[num]);; } } ac::solo_filter.push_back("CustomFilterStack"); std::cout << "acidcam: Custom Loaded: " << ac::solo_filter[ac::solo_filter.size()-1] << "\n"; return static_cast<int>(ac::solo_filter.size()-1); } std::fstream *stdout_file; void setFile(std::fstream *fout) { stdout_file = fout; } void keypress(int key, int scancode, int action, int mode) { if(key == GLFW_KEY_ESCAPE) { quit(); return; } if(key == 500) { time_keys[0] = true; time_keys[1] = false; return; } if(key == 501) { time_keys[0] = false; time_keys[1] = true; return; } if(key == 502) { time_keys[0] = false; time_keys[1] = false; return; } if(key == 503) { time_manip = !time_manip; if(time_manip) std::cout << "acidcam: Manual time manipulation toggled on.\n"; else std::cout << "acidcam: Manual time manipulation toggled off.\n"; return; } if(action == GLFW_PRESS) { if(mode == GLFW_MOD_SHIFT) { switch(key) { case GLFW_KEY_LEFT: time_keys[0] = true; time_keys[1] = false; break; case GLFW_KEY_RIGHT: time_keys[1] = true; time_keys[0] = false; break; } } } if(action == GLFW_RELEASE) { int f = 0, s = 0; if(mapped_keys.checkKey(key, f, s)) { index = f; std::cout << "acidcam: Filter: " << ac::solo_filter[index] << "\n"; setShader(s); return; } switch(key) { case GLFW_KEY_1: if(mode == GLFW_MOD_SHIFT) { if(video_mode == true) { stereo_mode =!stereo_mode; if(stereo_mode) std::cout << "acidcam: Stereo: on\n"; else std::cout << "acidcam Stereo: off\n"; } } break; case GLFW_KEY_2: if(mode == GLFW_MOD_SHIFT) { time_manip = !time_manip; if(time_manip) std::cout << "acidcam: Manual time manipulation toggled on.\n"; else std::cout << "acidcam: Manual time manipulation toggled off.\n"; } break; case GLFW_KEY_3: if(mode == GLFW_MOD_SHIFT) { restore_value = true; } break; case GLFW_KEY_4: if(mode == GLFW_MOD_SHIFT) { audio_enabled = !audio_enabled; if(audio_enabled) { std::cout << "acidcm: audio reacitivty enabled.\n"; } else { std::cout << "acidcam: audio reacitvity disabled.\n"; } } break; case GLFW_KEY_SEMICOLON: blur_enabled = !blur_enabled; if(blur_enabled) std::cout << "acidcam: Blur Mode enabled...\n"; else std::cout << "acidcam: Blur Mode disabled...\n"; break; case GLFW_KEY_COMMA: if(color_map == 0) { std::cout << "acidcam: Color map disabled...\n"; color_map = -1; return; } if(color_map > 0) { color_map--; std::cout << "acidcam: Color Map Decreased to: " << color_map << "\n"; } break; case GLFW_KEY_PERIOD: if(color_map < 19) { color_map++; std::cout << "acidcam: Color map increased to: " << color_map << "...\n"; } break; case GLFW_KEY_L: if(var_list.size()>0) { static int offset = 0; list_enabled = !list_enabled; if(list_enabled == true && var_list[var_index] >= 0 && var_list[var_index] < ac::solo_filter.size()) { offset = index; index = var_list[var_index]; std::cout << "acidcam: filter mode [list] enabled...\n"; } else if(list_enabled == false) { index = offset; std::cout << "acidcam: filter mode [normal] restored...\n"; } } break; case GLFW_KEY_N: if(debug) std::cout << "acidcam: filter index set to end of list...\n"; if(list_enabled == false) index = ac::solo_filter.size()-3; break; case GLFW_KEY_P: if(debug) std::cout << "acidcam: filter index reset...\n"; if(list_enabled == false) index = 0; break; case GLFW_KEY_K: if(index+25 < ac::solo_filter.size()-3) index += 25; break; case GLFW_KEY_J: if(index-25 > 0) index -= 25; break; case GLFW_KEY_Z: take_snapshot = true; break; case GLFW_KEY_ENTER: if(mode == GLFW_MOD_SHIFT) { std::cout << "acidcam: Attempting to release objects....\n"; ac::release_all_objects(); break; } case GLFW_KEY_F: { int val = atoi(input_string.c_str()); if(val >= 0 && val <= ac::solo_filter.size()-3) { index = val; input_string = ""; std::cout << "acidcam: Filter: " << ac::solo_filter[index] << "\n"; } } break; case GLFW_KEY_S: { int val = atoi(input_string.c_str()); if(val >= 0 && val <= shaders.size()-1) { input_string = ""; setShader(val); } } break; case GLFW_KEY_C: { input_string = ""; break; } case GLFW_KEY_SPACE: if(mode == GLFW_MOD_SHIFT) { if(af.size()>0) af_enabled = !af_enabled; if(af_enabled && af.size()>0) std::cout << "acidcam: Autofilter [On]\n"; else if(af_enabled == false && af.size()>0) std::cout << "acidcam: Autofilter [Off]\n"; } else { ac_on = !ac_on; if(ac_on) std::cout << "acidcam: filters enabled...\n"; else std::cout << "acidcam: filters disabled...\n"; } break; case GLFW_KEY_LEFT: if(mode == GLFW_MOD_SHIFT) { time_keys[0] = false; break; } if(list_enabled == false) { if(index > 0) { --index; if(debug) { std::cout << "acidcam: Filter Index: " << index << " - " << ac::solo_filter[index] << "\n"; } } } else { if(var_index > 0) var_index -= 1; if(var_list[var_index] > 0 && var_list[var_index] < ac::solo_filter.size()-1) { index = var_list[var_index]; if(debug) { std::cout << "acidcam: Filter Index: " << index << " - " << ac::solo_filter[index] << "\n"; } } } break; case GLFW_KEY_RIGHT: if(mode == GLFW_MOD_SHIFT) { time_keys[1] = false; break; } if(list_enabled == false) { if(index < ac::solo_filter.size()-1) { ++index; if(debug) { std::cout << "acidcam: Filter Index: " << index << " - " << ac::solo_filter[index] << "\n"; } } } else { if(var_index < var_list.size()-1) var_index += 1; if(var_list[var_index] > 0 && var_list[var_index] < ac::solo_filter.size()-1) { index = var_list[var_index]; if(debug) { std::cout << "acidcam: Filter Index: " << index << " - " << ac::solo_filter[index] << "\n"; } } } break; case GLFW_KEY_M: rand_timeout = !rand_timeout; if(rand_timeout) std::cout << "acidcam: Rand playlist timeout enabled\n"; else std::cout << "acidcam: Rand playlist timeout disabled\n"; break; case GLFW_KEY_MINUS: if(blend_index > 0) { blend_index -= 10; std::cout << "acidcam: Blend Index Set to: " << blend_index << ".\n"; } break; case GLFW_KEY_EQUAL: if(blend_index < 100) { blend_index += 10; std::cout << "acidcam: Blend Index Set to: " << blend_index << ".\n"; } break; case GLFW_KEY_UP: if(af_enabled == false && shader_index > 0) { --shader_index; setShader(shader_index); } break; case GLFW_KEY_DOWN: if(af_enabled == false && shader_index < shaders.size()-1) { shader_index++; setShader(shader_index); } break; case GLFW_KEY_H: if(mode == GLFW_MOD_SHIFT) { if(af.size()>0) { static bool shuffle_on = false; shuffle_on = !shuffle_on; af.shuffle(shuffle_on); af.shuffle(); } } else { std::cout << "acidcam: Playlist shuffled...\n"; sortPlaylist(); } break; case GLFW_KEY_G: if(paused) { std::cout << "acidcam: program unpaused\n"; paused = false; } else { std::cout << "acidcam: program paused...\n"; paused = true; } break; case GLFW_KEY_Q: optx[0] -= movement_rate; break; case GLFW_KEY_W: optx[0] += movement_rate; break; case GLFW_KEY_E: optx[1] -= movement_rate; break; case GLFW_KEY_R: optx[1] += movement_rate; break; case GLFW_KEY_Y: optx[2] -= movement_rate; break; case GLFW_KEY_U: optx[2] += movement_rate; break; case GLFW_KEY_I: optx[3] -= movement_rate; break; case GLFW_KEY_O: optx[3] += movement_rate; break; case GLFW_KEY_T: optx = glm::vec4(0.5, 0.5, 0.5, 0.5); break; case GLFW_KEY_BACKSPACE: for(int i = 0; i < 4; ++i) { if(optx[i] > 1000.0f) optx[i] = 1000.0f; if(optx[i] < -1000.0f) optx[i] = -1000.0f; } break; case GLFW_KEY_PAGE_UP: { stored_position = index; stored_var_position = var_index; std::string namex; if(stored_position >= 0 && stored_position < ac::solo_filter.size()) { namex = ac::solo_filter[stored_position]; } else { namex = "Unknown"; } std::cout << "acidcam: Stored position set to: " << namex << " - " << stored_position << " playlist position: " << stored_var_position << "\n"; } break; case GLFW_KEY_PAGE_DOWN: { if(list_enabled == false) index = stored_position; else index = var_list[stored_var_position]; std::string namex; if(index >= 0 && index < ac::solo_filter.size()) { namex = ac::solo_filter[index]; } else { namex = "Unknown"; } std::cout << "acidcam: Index set to stored position: " << namex << " - " << index << "\n"; } break; case GLFW_KEY_SLASH: rand_shader = !rand_shader; std::cout << "acidcam: Random Shader Toggled...\n"; break; case GLFW_KEY_DELETE: shader_list_enabled = !shader_list_enabled; if(shader_list_enabled) { std::cout << "acidcam: shader list enabled: " << shader_list.size() << " shaders.\n"; } else std::cout << "acidcam: shader list disabled.\n"; break; } } #if defined(__APPLE__) || defined(__linux__) if(redirect != 0) { sendString(redirect->getString()); } #endif } void resize(int newWidth, int newHeight) { aspect = (float)newWidth / (float)newHeight; glViewport(0, 0, newWidth, newHeight); p_mat = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f); window_width = newWidth; window_height = newHeight; #ifdef SPOUT_SERVER INIT_TEXTURE(senderTexture, window_width, window_height); #endif #ifdef SYPHON_SERVER if(syphon_enabled) { syphon_size(width, height); } #endif } //std:::unordered_map<std::string, std::vector<std::string>> custom_filters; using List = std::vector<std::string>; std::unordered_map<std::string, List> custom_filters; using Prog = AC_Program *; std::unordered_map<std::string, Prog> plugins; void CallCustom(std::string index, cv::Mat &frame) { std::string val = index; if(stereo_mode) { frame.create(cv::Size(window_width, window_height), CV_8UC3); stereo.Render(frame); } if(blur_enabled) { ac::MedianBlur(frame); ac::MedianBlur(frame); ac::MedianBlur(frame); } cv::flip(frame, frame, 0); if(plugins.find(val) != plugins.end()) { plugins[val]->exec(frame); } else if(custom_filters.find(val) != custom_filters.end()) { for(int i = 0; i < custom_filters[val].size(); ++i) { if(plugins.find(custom_filters[val].at(i)) != plugins.end()) plugins[custom_filters[val].at(i)]->exec(frame); else ac::CallFilter(custom_filters[val].at(i),frame); } } else { ac::CallFilter(index, frame); } } void loadPlugins(std::string c) { if(c.length()==0)return; std::string path = c + "/index.txt"; std::fstream file; file.open(path, std::ios::in); if(!file.is_open()) { std::cout << "acidcam: Couldn't load custom files: " << path << "\n"; acidcam::updateError(); } while(!file.eof()) { std::string n; std::getline(file, n); if(file && n.length() > 0) { AC_Program *program = new AC_Program(); if(program->load(c + "/" + n)) { plugins[n] = program; std::cout << "acidcam: Loaded Plugin: " << n << "\n"; ac::solo_filter.push_back(n); } else { std::cout << "acidcam: Could not open plugin: " << n << "\n"; //acidcam::updateError(); } } } } void loadCustom(std::string &c) { std::string path = c + "/index.txt"; std::fstream file; file.open(path, std::ios::in); if(!file.is_open()) { std::cout << "acidcam: Couldn't load custom files: " << path << "\n"; acidcam::updateError(); } while(!file.eof()) { std::string n; std::getline(file, n); if(file) { std::fstream custom; custom.open(c + "/" + n, std::ios::in); if(!custom.is_open()) { std::cout << "acidcam: Error loading custom file: " << n << "\n"; acidcam::updateError(); } custom_filters[n] = std::vector<std::string>(); while(!custom.eof()) { std::string v; std::getline(custom, v); if(custom) { custom_filters[n].push_back(v); } } std::cout << "acidcam: Load Custom: " << n << "\n"; ac::solo_filter.push_back(n); custom.close(); } } } void loadShaderList(std::string lst) { std::fstream file; file.open(lst, std::ios::in); if(!file.is_open()) { std::cout << "acidcam: Error could not load shader list...\n"; acidcam::updateError(); } while(!file.eof()) { std::string s; std::getline(file, s); if(file) shader_list.push_back(shader_map[s]); } std::cout << "acidcam: shader list loaded...\n"; } void loadShaders(const std::string &text) { std::ostringstream stream; stream << text << "/" << "index.txt"; std::fstream file; file.open(stream.str(), std::ios::in) ; if(!file.is_open()) { std::cout << "acidcam: Error could not open: " << stream.str() << "\n"; acidcam::updateError(); } int index = 0; while(!file.eof()) { if(acidcam::redir == 1) { #ifndef _WIN32 if(redirect != 0) { std::string text = redirect->getString(); sendString(text); } #endif } std::string s; std::getline(file, s); if(file && s.length() > 0) { if(material_on == false && s.find("material") != std::string::npos) continue; std::ostringstream fs1,fs2; fs1 << text << "/" << s; fs2 << text << "/vertex.glsl"; ShaderProgram p; std::cout << "acidcam: Compiling Shader " << index << " [" << s << "] "; if(p.loadProgram(fs2.str(), fs1.str())==false) { std::cout << "Error could not load: " << fs1.str() << "\n"; acidcam::updateError(); } shader_map[s] = index; std::cout << "\n"; p.setName(s.substr(0, s.rfind("."))); shaders.push_back(p); ++index; } } file.close(); std::cout << "acidcam: Loaded " << shaders.size() << " Shaders...\n"; } float cameraX, cameraY, cameraZ; float cube_x, cube_y, cube_z; glm::mat4 r_mat; virtual void init_cube() { cameraX = 0; cameraY = 0; cameraZ = 8.0f; cube_x = 0.0f; cube_y = -2.0f; cube_z = 0.0f; color_alpha_r = 0.1; color_alpha_g = 0.2; color_alpha_b = 0.3; GLfloat vertices[] = { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, // left side -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, // top -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, // bottom -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, // right 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, // back face 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, }; GLfloat texCoords[] = { 0, 0, // front 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, // left 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0,0, // top 0,1, 1,1, 1, 1, 1, 0, 0, 0, 0, 0,// bottom 0, 1, 1, 1, 1,1, 1,0, 0,0, 0,0,// right 1,0, 0,1, 0,1, 1,0, 1,1, 0,0, // back 1,1, 0,1, 0,0, 1,0, 1,1 }; glGenVertexArrays(1, vao); glBindVertexArray(vao[0]); glGenBuffers(numVBOs, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW); glfwGetFramebufferSize(win(), &width, &height); aspect = (float)width/(float)height; p_mat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); cv::Mat frame; cap.read(frame); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame.cols, frame.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, frame.ptr()); } virtual void update_cube(double timeval) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); program.useProgram(); mv_loc = glGetUniformLocation(program.id(), "mv_matrix"); proj_loc = glGetUniformLocation(program.id(),"proj_matrix"); GLuint samp = glGetUniformLocation(program.id(), "samp"); GLuint mat_samp = glGetUniformLocation(program.id(), "mat_samp"); GLuint calpha_r = glGetUniformLocation(program.id(), "value_alpha_r"); GLuint calpha_g = glGetUniformLocation(program.id(), "value_alpha_g"); GLuint calpha_b = glGetUniformLocation(program.id(), "value_alpha_b"); GLuint c_index = glGetUniformLocation(program.id(), "index_value"); GLuint c_tf = glGetUniformLocation(program.id(), "time_f"); GLuint alpha_pos = glGetUniformLocation(program.id(), "alpha_value"); GLuint optx_pos = glGetUniformLocation(program.id(), "optx"); GLuint rand_pos = glGetUniformLocation(program.id(), "random_var"); GLuint restore_blackx = glGetUniformLocation(program.id(), "restore_black"); GLuint inc_value_pos = glGetUniformLocation(program.id(), "inc_value"); GLuint inc_value_posx = glGetUniformLocation(program.id(), "inc_valuex"); cameraZ = 8.0f; v_mat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, cameraY, -cameraZ)); cv::Mat frame; if (!cap.read(frame)) { if (repeat == true && repeat_filename.length() > 0) { cap.open(repeat_filename); if (cap.isOpened()) { cap.read(frame); std::cout << "acidcam: video loop...\n"; } else { std::cout << "acidcam: Capture device closed exiting...\n"; quit(); return; } } else { std::cout << "acidcam: Capture device closed exiting...\n"; quit(); return; } } if (shader_index == 0 || ac_on == true) { if (index >= 0 && index < ac::solo_filter.size()) { cv::Mat orig; if (blend_index > 0) { orig = frame.clone(); } CallCustom(ac::solo_filter[index], frame); if (blend_index > 0 && blend_index / 10 > 0) { cv::Mat copyf; double per = 1.0 / (blend_index / 10); ac::AlphaBlendDouble(frame, orig, copyf, per, 1.0 - per); frame = copyf.clone(); } if (color_map != -1) { cv::Mat output_f1 = frame.clone(); cv::applyColorMap(output_f1, frame, color_map); } if (restore_black == true) { ac::CallFilter("RestoreBlack", frame); if (color_map != -1) { cv::Mat output_f1 = frame.clone(); cv::applyColorMap(output_f1, frame, color_map); } } if (print_text == true) { std::ostringstream stream; stream << ac::solo_filter[index]; cv::putText(frame, stream.str(), cv::Point(40, 40), cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(255, 255, 255), 2); } } } cv::flip(frame, frame, 0); cameraZ += -5.0f; v_mat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, cameraY, -cameraZ)); m_mat = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f,0.0f,0.0f)); float rot_angle = static_cast<float>(fmod(1.75 * timeval, 2.0 * M_PI)); r_mat = glm::rotate(glm::mat4(1.0f), rot_angle, glm::vec3(0.0f, 1.0f, 0.0f)); r_mat = glm::rotate(r_mat, rot_angle, glm::vec3(1.0f, 0.0f, 0.0f)); r_mat = glm::rotate(r_mat, rot_angle, glm::vec3(0.0f, 0.0f, 1.0f)); m_mat = m_mat * r_mat; mv_mat = v_mat * m_mat; glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat)); glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(p_mat)); glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat)); glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(p_mat)); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE,0,0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,0,0); glEnableVertexAttribArray(1); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame.cols, frame.rows, GL_BGR, GL_UNSIGNED_BYTE, frame.ptr()); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); color_alpha_r += rand() % 100 * 0.01f; color_alpha_g += rand() % 100 * 0.01f; color_alpha_b += rand() % 100 * 0.01f; if (color_alpha_r > 1.5f) color_alpha_r = 0.1f; if (color_alpha_g > 1.5f) color_alpha_g = 0.1f; if (color_alpha_b > 1.5f) color_alpha_b = 0.1f; static bool idir = true; if (idir == true) { alpha += 0.1f; if (alpha >= 6.0) idir = false; } else { alpha -= 0.1f; if (alpha <= 1.0f) { idir = true; } } random_var = glm::vec4(rand() % 255, rand() % 255, rand() % 255, rand() % 255); static int inc_dir = 1; if (inc_dir == 1) { for (int i = 0; i < 3; ++i) { ++inc_value[i]; if (inc_value[i] >= 255) inc_dir = 0; } } else { for (int i = 0; i < 3; ++i) { --inc_value[i]; if (inc_value[i] <= 1) { inc_dir = 1; inc_value = glm::vec4(rand() % 255, rand() % 255, rand() % 255, 1); } } } static int inc_dirx = 1; if (inc_dirx == 1) { for (int i = 0; i < 3; ++i) { ++inc_valuex[i]; if (inc_valuex[i] >= 255) inc_dirx = 0; } } else { for (int i = 0; i < 3; ++i) { --inc_valuex[i]; if (inc_valuex[i] <= 1) { inc_dirx = 1; } } } const double TIME_WRAP = 86400.0; if(timeval > TIME_WRAP) { timeval = fmod(timeval, TIME_WRAP); } for(int i = 0; i < 4; ++i) { if(optx[i] > 1000.0f) optx[i] = 1000.0f; else if(optx[i] < -1000.0f) optx[i] = -1000.0f; if(std::isnan(optx[i]) || std::isinf(optx[i])) optx[i] = 0.5f; } glUniform1i(samp, 0); glUniform1i(mat_samp, 1); glUniform1f(c_index, (float)index); glUniform1f(c_tf, static_cast<float>(timeval)); glUniform4fv(inc_value_pos, 1, glm::value_ptr(inc_value)); glUniform4fv(inc_value_posx, 1, glm::value_ptr(inc_valuex)); glUniform1f(calpha_r, color_alpha_r); glUniform1f(calpha_g, color_alpha_g); glUniform1f(calpha_b, color_alpha_b); glUniform1f(alpha_pos, alpha); glUniform4fv(optx_pos, 1, glm::value_ptr(optx)); glUniform4fv(rand_pos, 1, glm::value_ptr(random_var)); glUniform1f(restore_blackx, ((restore_black == true) ? 1.0 : 0.0)); GLint loc = glGetUniformLocation(program.id(), "iResolution"); glUniform2f(loc, width, height); glEnable(GL_DEPTH_TEST); glEnable(GL_LEQUAL); glDrawArrays(GL_TRIANGLES,0,36); if (take_snapshot == true) { takeSnapshot(); take_snapshot = false; } if (writer_set == true) writeFrame(); } GLuint createShaderProgram() { GLuint vfProgram = program.createProgramFromFile("vertex.glsl", "frag.glsl"); return vfProgram; } }; }